From fa722149cef4249f501f752c85a2147519d23e31 Mon Sep 17 00:00:00 2001
From: ktseo41 404PAGE NOT FOUND
But if you don't change your direction, and if you keep looking, you may end up where you are heading.
진지하고 깊이 고민하는 성격입니다. 길게 성공하는 서비스에는 좋은 개발환경이 필요하다고 믿습니다.
책과 영화, 게임을 좋아합니다.
애플리케이션의 구글 페이지 경험 순위와 라이트하우스 점수 이해하기
코어 웹 바이탈은 구글에서 애플리케이션의 페이지 순위를 매기는 데 영향을 줍니다. 여기에서는 코어 웹 바이탈이 무엇인지, 어떻게 측정되는지, 그리고 이것이 사용자 및 검색 순위에 어떤 영향을 미치는지 자세히 살펴보겠습니다.
Malte Ubl은 Vercel의 CTO이자 전 구글 검색 디렉터로, 코어 웹 바이탈을 많이 활용하는 '페이지 경험' 순위 발표를 담당했습니다. 즉, 여기에 작성된 모든 내용은 공개적으로 문서화되어 있으며 적절한 경우 링크가 제공됩니다.
구글 검색에서 여러분의 사이트 순위는 구글의 코어 웹 바이탈 지표를 기반으로 사이트의 성능을 평가하는 구글의 페이지 경험 순위 시스템에 의해 영향을 받습니다.
구글은 실제 사용자가 웹사이트와 상호 작용하는 방식을 관찰하고 이를 다시 서버에 보고하는 방식으로 코어 웹 바이탈을 수집합니다 (작동 방식에 대한 자세한 내용은 아래 참조).
이러한 유형의 데이터를 현장 데이터 라고 하는데, 이는 사이트를 탐색하는 실제 사용자로부터 수집하기 때문입니다. 이는 사이트의 성능을 확인하기 위해 '실험실 환경'에서 실행한 테스트의 결과인 실험실 데이터 와는 다릅니다. 구글의 라이트하우스는 실험실 테스트의 한 예입니다.
이 글에서 가장 중요한 점은 바로 이것입니다.
구글은 사이트 순위를 매길 때 코어 웹 바이탈 현장 데이터만 고려합니다. 구글은 검색 순위를 매길 때 라이트하우스 점수를 어떤 식으로든 고려하지 않습니다.
페이지 경험은 코어 웹 바이탈을 활용하여 다른 사이트와 비교해 웹사이트의 성능을 확인하는 구글 검색의 순위 결정 요소입니다. 페이지 경험은 구글 검색의 여러 순위 결정 요소 중 하나로, 검색 결과 페이지에서 사이트의 순위를 결정하기 위해 모두 합산됩니다.
검색어와의 관련성 및 콘텐츠의 품질은 페이지 경험보다 훨씬 더 중요한 요소입니다. 그러나 여러분과 경쟁업체의 관련성이 매우 유사한 경우에는 페이지 경험에 따라 순위가 결정될 수 있습니다.
페이지 경험과 코어 웹 바이탈의 다른 점은 바로 이 점입니다.
코어 웹 바이탈은 다른 순위 결정 요소들보다 비교적 명확한 편입니다. 이를 최적화하는 것은 관련성을 개선하는 것보다 '추측'이 훨씬 덜 필요하며 콘텐츠 품질보다 측정하기 쉽습니다.
또한 코어 웹 바이탈을 개선하면 사용자 경험이 개선되어 전환을 유도할 수 있습니다.
페이지 경험 순위에 대한 전체 앱의 성능에 대한 권위 있는 데이터 소스는 구글 검색 콘솔입니다.
구글 검색 콘솔의 코어 웹 바이탈 페이지
페이지별 데이터에 액세스하는 간단한 방법은 두 가지 주요 섹션(코어 웹 바이탈과 라이트하우스)으로 그룹화되어 있는 구글의 PageSpeed 인사이트입니다.
"실제 사용자의 경험 알아보기"라는 레이블이 붙은 PageSpeed 인사이트의 상단 섹션에서 구글은 지난 28일 동안 크롬 브라우저(데스크톱 및 안드로이드 모바일 기기)에서 애플리케이션에 접속한 실제 사용자의 75번째 백분위수에 대한 글로벌 현장 데이터를 수집합니다.
구글은 이 실제 데이터의 첫 세 가지 지표인 최대 콘텐츠 렌더링 시간(LCP), 첫 입력 지연(FID), 레이아웃 변경 횟수(CLS)를 사용하여 점수에 따라 애플리케이션의 순위를 변경합니다. 2024년 3월에는 다음 페인트와의 상호작용(INP)이 FID를 대체합니다.
이 세 가지 코어 웹 바이탈은 웹 성능에 따라 앱의 순위에 영향을 미치는 데 구글이 사용하는 유일한 데이터이며, 여기에 표시된 점수는 애플리케이션의 비슷한 성능의 페이지와 함께 그룹으로 평균을 낸 것이지만 구글이 사용하는 수치와 정확히 일치합니다.
또한 데스크톱과 모바일용 탭이 모두 있는 것을 볼 수 있습니다. 이는 구글이 사이트의 모바일 버전과 데스크톱 버전을 각각 기준으로 모바일 사용자와 데스크톱 사용자에 대해 애플리케이션의 순위를 별도로 매기기 때문 입니다.
google.com에 대한 모바일 코어 웹 바이탈입니다.
코어 웹 바이탈 아래에 있는 세 가지 지표는 사용자 경험에 대한 추가 인사이트를 제공할 수 있지만 검색에서 애플리케이션의 순위에는 영향을 미치지 않습니다.
크롬 사용자경험보고서(CrUX)는 구글의 코어 웹 바이탈 프로그램의 공식 데이터세트이며, 수집 방법은 공개적으로 문서화되어 있습니다. 특히 보고서에 포함될 내용은 다음과 같습니다.
이 마지막 글머리 기호는 아이폰 사용자는 집계되지 않는다는 의미입니다. 이는 일부 시장에서는 안드로이드폰이 아이폰보다 느리게 작동하므로 느리게 사이트를 방문하는 비율이 더 많이 계산될 수 있다는 점과 관련이 있을 수 있습니다.
애플리케이션에 실제 사용자 데이터가 충분하지 않은 경우 코어 웹 바이탈을 측정할 수 없으며 애플리케이션 순위를 매길 때 고려되지 않습니다.
또 다른 빈번한 질문은 '사용자가 어디에서 오는지가 중요한가요?' '인터넷 연결 속도가 느린 국가에 사용자가 많으면 불이익을 받나요?' 입니다.
사용자가 어디에서 오는지는 중요합니다. 현장 데이터의 핵심은 실제 사용자를 반영하며, 전 세계 모든 지역의 모든 사용자가 동등하게 집계된다는 점입니다.
좋은 소식은 인터넷 연결과 디바이스 성능이 전 세계적으로 향상되고 있으며, Vercel과 같은 에지 네트워크를 사용하면 지구상의 모든 사용자에게 뛰어난 성능을 제공할 수 있다는 것입니다.
구글은 28일 슬라이딩 윈도 방식으로 코어 웹 바이탈 데이터를 수집합니다. 점수는 기본적으로 지난 28일 동안의 평균 점수입니다. 개선 조치를 취했거나 상황을 악화시킨 경우 해당 조치의 전체 영향을 파악하려면 한 달이 지나야 합니다.
아래에서 Vercel의 속도 인사이트를 통해 업데이트된 CWV 데이터에 더 빠르게 액세스하여 실시간으로 변화에 대응하고 순위 하락을 방지할 수 있는 방법을 확인할 수 있습니다.
PageSpeed 인사이트의 두 번째 섹션인 '성능 문제 진단'에서는 크롬 개발자 도구에 있는 것과 동일한 도구인 라이트하우스 내에서 애플리케이션의 성능을 시뮬레이션합니다.
이는 위의 현장 데이터 점수와 완전히 별개의 항목으로, 실제 사용자에 대한 구글의 기준을 아직 충족하지 못하는 경우 개선 제안을 위한 것입니다.
다시 한번 말씀드리자면, 라이트하우스의 어떤 항목도 사이트의 검색 순위에 반영되지 않으며, 웹 앱 개발에서 흔히 발생하는 함정을 피하는 데 도움이 되는 선택적 지침을 제공합니다.
google.com에 대한 모바일 라이트하우스 점수입니다.
페이지에서 가장 눈에 띄는 숫자 중 하나인 라이트하우스 성능 점수는 FCP(First Contentful Paint), 속도 지표, LCP, TBT(총 차단 시간), CLS에 가중치를 부여한 점수입니다. 가중치를 적용한 후 실제 코어 웹 바이탈은 이 점수의 50%만 차지하며 FID/INP는 고려되지 않습니다.
이 결과는 쓰로틀링된 네트워크 연결로 모토 G 파워를 에뮬레이션 한 디바이스에서 얻은 결과이며, 실제 사용자의 디바이스와는 사양이 크게 다를 수 있습니다.
이 점과 기타 실험실 데이터와 관련된 문제(예: 사용자가 보고된 페이지로 이동하기 전에 어떤 페이지에서 왔는지 고려하지 않는 점)로 인해 라이트하우스 점수는 유일한 UX 지표로 적합하지 않습니다.
예를 들어, 지표로서의 총 차단 시간(TBT)은 실제 사용자 경험을 반영하지 못하는 경우가 많습니다. 이는 사용자 이벤트가 있는 경우 리액트와 같은 최신 프레임워크는 인터럽트 실행을 통해 좋은 FID와 INP를 제공하지만, 실험실 테스트에서는 실제 사용자 상호작용 없이 CPU 사용량을 관찰할 때 이를 알 수 없기 때문입니다.
실험실 데이터에 대한 어려움에도 불구하고 라이트하우스는 여전히 유용한 정보를 제공하며, 특히 애플리케이션의 어느 부분이 사용자에게 문제를 일으킬 수 있는지 범위를 좁히는 데 유용합니다. 예를 들어
구글의 데이터는 애플리케이션의 검색 순위와 실제 사용자의 성능을 확인할 수 있는 권위 있는 출처입니다. 하지만 위에서 언급했듯이 구글이 제공하는 데이터는 28일의 슬라이딩 윈도우를 사용합니다.
즉, 개선 또는 후퇴를 적용하면 전체 영향을 확인하려면 최대 한 달이 걸릴 수 있습니다. 또한 성능 저하에 대한 수정 사항을 제출해야 하는 경우 구글이 개선 사항을 반영하는 데 한 달이 더 걸릴 수 있습니다.
Vercel은 이터레이션 속도를 극대화하기 위해 속도 인사이트를 만들었습니다. 크롬 브라우저는 사용자가 사이트에 접속할 때 코어 웹 바이탈 지표를 노출하므로, 사이트에 설치된 속도 인사이트 패키지는 이 지표에 액세스하여 실시간 데이터를 보고합니다. 그러면 문제가 나타나는 즉시 발견하고 수정하여 신속하게 대응할 수 있습니다.
프로젝트 보기의 속도 인사이트 탭 스냅샷
Vercel의 모든 기능이 무제한 불변 배포와 연계되어 있는 것처럼, 속도 인사이트도 배포 단위 또는 브랜치 단위로 볼 수 있어 각 git push
가 애플리케이션 성능에 미치는 영향을 쉽게 확인할 수 있습니다.
구글의 PageSpeed 인사이트와 달리 지난 28일보다 더 작은 기간으로 데이터를 필터링할 수 있어 변경의 즉각적인 효과를 확인하거나 대규모 코드베이스 변경과 관련된 임의의 기간을 측정할 수 있습니다.
또한 애플리케이션의 개별 경로를 확인하고 사용자의 75번째 백분위수('구글 기준')와 90번째, 95번째, 99번째를 기준으로 데이터를 볼 수 있습니다.
또한 전 세계 지역별로 결과를 필터링할 수 있어 실제 사용자가 거주하는 지역에 리소스를 더 효과적으로 할당할 수 있습니다.
색상 강도가 국가별 데이터 포인트의 상대적 양을 나타내는 P75 점수의 지리적 지도.
전 세계의 다양한 규제 제한에 상관없이 속도 인사이트 기능을 사용할 수 있도록 개별 방문자나 IP 주소에 연결되거나 연관되지 않고 정보를 제공하도록 설계되었습니다.
이제 코어 웹 바이탈의 정의, 측정 방법, 애플리케이션에 미치는 영향에 대한 개요를 살펴보았으니 "각 지표를 최적화하려면 어떻게 해야 하나요?"라고 궁금해하실 수 있습니다.
조만간 이 주제에 대한 더 많은 콘텐츠를 게시할 예정이지만, 지금은 개별 지표 최적화에 대한 구글의 기술 가이드를 추천합니다: 최대 콘텐츠 렌더링 시간(LCP), 레이아웃 변경 횟수(CLS), 첫 입력 지연(FID), 다음 페인트와의 상호작용(INP).
웹 개발자 여러분 안녕하세요! 최근 Cloudflare에서는 약간의 변화를 준비하고 있는데요. 이 글에서 저희가 무엇을 하고 어디로 가고 있는지 간단하게 알려드리려 합니다. 여러분들은 이미 Cloudflare를 웹 애플리케이션을 보호하거나, 속도를 높이거나, 확장할 수 있는 최고의 장소로 알고 계시겠지만, Cloudflare는 점점 더 애플리케이션을 배포하고 실행하는데도 최고의 장소가 되고 있습니다!
왜 애플리케이션을 Cloudflare에 배포해야 할까요? 두 가지 간단한 이유가 있습니다. 첫째, 여러 개별 시스템을 관리하는 번거로움을 줄여줍니다. 개발, 배포, 모니터링, 튜닝을 한곳에서 할 수 있습니다. 둘째, Cloudflare에 직접 배포함으로써 애플리케이션을 최적화할 수 있는 수단이 훨씬 더 많아지며, 그로 인해 애플리케이션을 사용자에게 더 빠르고 부드럽게 전달할 수 있습니다.
그래서 무엇이 바뀌는 건가요? 사실 꽤 많은 것이 바뀝니다. 저는 모든 세부 사항을 다시 이야기하며 여러분들을 지루하게 하지 않을 것입니다. 대신 제 뛰어난 동료들이 모든 세부 사항을 포함한 별도의 글을 작성했으니, 여기서는 대략적으로 파악해 보세요.
Cloudflare Pages와 Workers는 다음과 같은 서비스를 제공하는 통합된 개발 및 애플리케이션 호스팅 플랫폼으로 병합됩니다.
수학적으로는 틀렸다는 것이 증명되었지만, 저희는 1+1=3이라는 공식을 고집스럽게 믿고 있습니다. Cloudflare Pages + Workers가 각각의 합보다 훨씬 더 훌륭하다고 해석합니다. 실제로, 둘의 조합은 저희가 기대하며 개발하고 있는 독특한 개발 플랫폼의 훌륭한 기반입니다.
저희는 이 통합 여정을 몇 분기 전에 시작했으며, 초기부터 기존의 애플리케이션을 그대로 두지 않기로 합의했습니다. 대신, 이전의 애플리케이션을 새로운 세계로 옮겨갈 것입니다. 이제 점진적인 결과를 공유하기 시작하려고 합니다. 그리고 이번 분기 동안 훨씬 더 많은 것들이 출시될 예정입니다. 더 알고 싶으신가요? 제 동료 Nevi가 그녀의 블로그 게시물에 흥미진진한 세부 사항들을 공유했습니다.
간단히 말해서, 스마트 배치는 Cloudflare에 혁명을 가져왔습니다. 이 기능은 오늘날 다른 애플리케이션 호스팅 제공 업체도 따라올 수 없는 새로운 컴퓨팅 패러다임을 저희 플랫폼에서 가능하게 합니다. 인기 있는 여러 웹 프레임워크 중 하나로 만들어진 전형적인 풀스택 애플리케이션을 가지고 있나요? 그렇다면 이 기능은 바로 당신을 위한 것입니다! 그리고 이 기능은 Workers와 Pages 모두에서 작동합니다!
이전에는 항상 모든 애플리케이션을 저희 글로벌 네트워크의 "엣지", 즉 사용자에게 가능한 한 가까운 곳에서 실행했습니다. 스마트 배치를 사용하면 저희는 컴퓨팅(당신의 애플리케이션)이 실행되어야 하는 네트워크 내에서 최적의 위치를 지능적으로 결정합니다. 이는 애플리케이션의 동작과 애플리케이션이 상호작용하는 다른 네트워크 자원이나 엔드포인트를 관찰함으로써 이루어집니다. 그런 다음 일반적으로 데이터가 저장된 곳과 가까운 최적의 위치에 당신의 애플리케이션을 투명하게 생성하고, 저희의 네트워크를 통해 들어오는 요청을 해당 위치로 라우팅 합니다.
스마트 배치를 통해 애플리케이션을 작업을 수행하는데 필요한 데이터와 가까이에서 실행할 수 있습니다. 이는 데이터베이스, 오브젝트 저장소, 또는 다른 백엔드 엔드포인트와 상호작용하는 애플리케이션에 유용하며, 중앙집중식이고 글로벌하게 분산되어 있지 않은 경우에 특히 강력합니다.
사용자나 클라이언트의 요청은 여전히 285개가 넘는 데이터 센터 중 그들의 현재 위치에 가까운 한 곳의 초고속 네트워크로 전송됩니다. 하지만 애플리케이션을 바로 그곳에서 생성하는 대신, 애플리케이션과 통신하는 데이터나 백엔드 시스템과 가까운 최적의 데이터 센터로 요청을 라우팅 합니다.
그렇다고 엣지에서의 컴퓨팅이 더 이상 멋지지 않다는 의미는 아닙니다! 멋져요! 여전히 애플리케이션을 엣지에서 실행하는 것이 합당한 많은 사용 사례가 있으며 스마트 배치는 그 시나리오를 결정하고, 있어야 할 장소가 엣지라면 애플리케이션을 엣지에 유지합니다. A/B 테스팅, 현지화, 에셋 제공 등은 거의 항상 엣지에서 일어나야 할 사용 사례입니다.
흥미로우신가요? 이 시각적 데모를 확인하고, 제 동료인 Tanushree의 블로그 게시물에서 스마트 배치에 대해 자세히 알아보세요.
초고속으로 전 세계에 분산된 애플리케이션 플랫폼에 직접 통합된, 최고의 개발 환경을 구축한다는 목표를 계속해서 실현하고 있습니다. 로컬 기본 개발 워크플로우를 완벽하게 지원하는 Wrangler v3를 출시합니다. 오픈소스 Cloudflare Workers 자바스크립트 런타임인 workerd를 기반으로 하는 이 변화는 개발 서버 시작 시각을 10배, 그리고 스크립트 재로드 시간을 60배 단축해 생산성을 높이고 흐름을 더 오래 유지할 수 있게 합니다.
대시보드에서는 업그레이드된, 훨씬 더 강력한 VSCode 기반의 온라인 편집기를 도입하고 있습니다. 이제 브라우저에서 여러 자바스크립트 모듈을 편집하고, 엣지 미리 보기를 정확히 확인할 수 있으며, 친절한 에러 페이지와 타입 검사를 할 수 있습니다!
마지막으로 대시보드 에디터와 Wrangler 모두에서 workerd 맞춤형 크롬 개발자 도구가 최신 버전으로 업데이트되어 어디서든 더욱 뛰어난 디버깅 및 프로파일링 기능을 제공합니다.
이는 저희의 개발 도구 영역 개선에 대한 첫 번째 물결에 불과하며, 앞으로 몇 분기 동안 이 공간에서는 저희가 계속해서 변화를 이루는 것을 볼 수 있을 것입니다. 그러나 그 사이에, Adam, Brendan, 그리고 Samuel로부터 Wrangler v3의 모든 세부 정보와 VSCode 및 대시보드 에디터 개선에 대한 심층적인 게시물을 확인하세요.
AI, WASM, 그리고 강력한 풀스택 애플리케이션의 시대에서, 저희는 개발자들이 저희의 현재 자원 한계에 더 자주 직면하고 있다는 것을 알아차렸습니다. 저희는 이러한 애플리케이션이 번창하고 개발자들이 더 크고 복잡한 애플리케이션을 구축할 수 있도록 하고 싶습니다. 그래서, 다음 주(2023.05.17. 기준) 내로 애플리케이션 크기 제한(JavaScript/WASM 번들 크기)을 10MB(gzip 이후)로 늘리고, 시작 지연 시간제한(스크립트 컴파일 시간)을 200ms에서 400ms로 늘릴 예정입니다.
개발자들에게 더 많은 권한을 부여하기 위해, 메모리 제한 등을 늘리기 위해 등급을 도입하면서 요금 모델을 통합하고 간소화하는 방법에 대해 고민하고 있습니다. 이에 대한 자세한 정보는 조만간 공개될 예정입니다!
이러한 변경으로 개발자들은 더 멋진 애플리케이션을 구축하고 더 적은 비용으로 운영할 수 있게 됩니다! 멋지지 않나요?!?
드디어 기다림이 끝났습니다! 이제 Pages에서 최신 빌드 이미지를 사용하여 CI 및 통합 빌드 시스템을 구동합니다. 이번 개선으로 마침내 최신 버전의 Node.js, pnpm 및 오늘날 개발자가 사용하는 기타 여러 도구를 사용할 수 있게 되었습니다.
이번 개선 사항을 제공하면서 향후에도 최신 상태로 유지하기가 훨씬 쉽게 만들었을 뿐만 아니라 빌드 캐싱과 같은 새로운 기능도 추가했습니다!
업데이트는 모든 새 프로젝트에 기본적으로 제공되며, 기존 프로젝트는 새로운 기본값을 선택할 수 있습니다. 마음에 드시나요? 그렇다면 Greg의 이 블로그 글에서 계속 읽어보세요.
Cloudflare는 CDN이자 Worker 애플리케이션을 배포하는 장소일 뿐만 아니라 이제 풀스택 웹 애플리케이션을 실행하는 최고의 장소가 되고 있습니다. 여기에는 Angular, Astro, Next, Nuxt, Qwik, Remix, Solid, Svelte, Vue 등과 같은 모든 풀스택 웹 프레임워크가 포함됩니다.
저희의 큰 목표는 더 나은 인터넷을 구축하는 것이며, 이 사명에 대한 저희의 기여는 개발자뿐만 아니라 누구나 아이디어를 실시간으로 배포된 애플리케이션으로 전환할 수 있도록 지원하는 것입니다.
개발자들이 아이디어를 빠르게, 그리고 번거로움 없이 배포된 애플리케이션으로 전환할 수 있도록 두 가지를 구축했습니다.
첫째, 여러 웹 프레임워크 작성자들과 협력하여 모든 널리 사용되는 자바스크립트 웹 프레임워크에 대해 새로운 어댑터를 만들거나 기존 어댑터를 개선했습니다. 이 어댑터들은 애플리케이션이 저희 플랫폼에서 가장 효율적인 방식으로 실행되도록 보장하면서, 플랫폼의 모든 기능과 능력에 접근할 수 있게 합니다.
이러한 어댑터에는 요청이 많았던 Next.js 어댑터가 포함되어 있으며, 방금 프로덕션 준비를 완료하고 오늘 1.0.0을 출시합니다! 각 팀과 협력하여 Angular 및 Qwik을 위한 새로운 어댑터를 구축했으며, Astro, Nuxt, Solid 및 몇 가지를 개선했습니다.
둘째, 저희는 C3라고 부르는 새롭고 멋진 CLI를 개발했습니다. 이는 create-cloudflare CLI를 의미하는 단축어로, 저희의 기존 Wrangler CLI의 형제입니다. 만약 당신이 터미널이나 VSCode와 같은 로컬 에디터에서 대부분의 시간을 보내는 개발자라면, 이 CLI는 Cloudflare 우주로 진입하게 해주는 단일 진입점입니다.
C3 명령을 실행하면 시작할 수 있습니다. 저희는 사용자와 열심히 작업하는 프레임워크 작성자 사이에 있는 것을 원하지 않기 때문에, 사용자가 원하는 프레임워크를 선택하면 C3는 제어권을 선택한 프레임워크의 CLI에게 넘깁니다. 잠시 후 npm 의존성이 모두 설치되고 나면 애플리케이션이 배포된 URL을 받게 됩니다. 이게 다입니다. 거의 즉시 아이디어로부터 공유할 수 있는 URL까지! 와우.
정리하자면, 풀스택 웹 프레임워크에 대한 최고 수준의 지원과 플랫폼의 짧은 대기 시간 및 비용 효율성, 풀스택 웹 애플리케이션의 백엔드가 최적의 위치에서 자동으로 실행되도록 하는 스마트 배치, 그리고 개발자 도구의 나머지 모든 중요한 개선 사항이 결합되어 Cloudflare를 웹 애플리케이션을 구축하고 호스팅 하기 위한 최고의 장소로 만들어줍니다. 이것이 저희가 더 나은 인터넷을 만들기 위한 사명에 대한 기여이며, 웹을 전진시키는 방법입니다.
저희는 사람들이 비즈니스를 하고자 할 때, 또는 단지 창의력을 발휘하고 아이디어를 탐구하며 재미있게 보내고 싶을 때 찾는 장소가 되길 희망합니다. 이는 긴 여정이며, 앞으로 저희가 마주하게 될 흥미로운 도전들이 많습니다. 당신의 의견이 저희를 안내하는 데 결정적인 역할을 할 것입니다. 저희 모두는 이 일부가 될 기회를 얻게 되어 흥분하고 있으며, 최선을 다해보려고 합니다. 당신도 이 여행에 참여할 수 있으며, 바로 시작할 수 있습니다.
npm create cloudflare my-first-app
원문 : https://bytecodealliance.org/articles/making-javascript-run-fast-on-webassembly
20년 전과 비교하면 브라우저에서 자바스크립트는 훨씬 더 빠르게 실행됩니다. 브라우저 벤더사가 집중적으로 성능 최적화 작업에 시간을 할애했기 때문입니다.
오늘 우리는 다른 규칙이 적용되는, 완전히 다른 환경에서 자바스크립트 성능을 최적화하는 작업을 시작합니다. 그리고 이것은 웹어셈블리 덕에 가능합니다.
먼저 확실히 해야 할 것이 있습니다. 브라우저에서 자바스크립트를 실행할 때는 간단히 자바스크립트를 배포하는 것이 가장 합리적인 선택입니다. 브라우저 내의 자바스크립트 엔진(JS 엔진)은 탑재된 자바스크립트를 실행하기 위해 고도로 조정되어 있기 때문입니다.
하지만 만약 서버리스 함수에서 자바스크립트를 실행하고 있다면 어떨까요? 또는 iOS나 게임 콘솔과 같이 일반적인 JIT(Just-In-Time) 컴파일을 허용하지 않는 환경에서 자바스크립트를 실행하고 싶다면요?
이와 같은 사례들의 경우, 오늘 알아볼 새로운 자바스크립트 최적화 물결에 주의를 기울여야 합니다. 이 작업은 또 비슷한 환경들에서 빠르게 실행되기를 원하는 Python, Ruby, Lua과 같은 다른 런타임들의 모델 역할을 할 수도 있습니다.
그러나 본격적으로 알아보기 전에, 기본적인 작동 방식을 살펴봐야 합니다.
자바스크립트를 실행하려면, 자바스크립트 소스 코드는 어떤 방법으로든 기계어로 번역돼 실행되어야 합니다. 번역된 기계어는 인터프리터나 JIT 컴파일러와 같은, 다양한 기술을 사용하는 JS 엔진에서 수행됩니다. (자세한 사항은 JIT(Just-In-Time) 컴파일러 집중 과정를 참조하세요.)
그러나 만약 실행하려는 플랫폼에 JS 엔진이 없다면 어떻게 해야할까요? 코드와 함께 JS 엔진을 배포해야 합니다.
이를 위해 JS 엔진을 웹어셈블리 모듈로 배포해 다양한 종류의 머신 아키텍처에서 이식될 수 있도록 했습니다. 그리고 WASI(웹어셈블리 시스템 인터페이스)를 사용하면 다른 운영 체제에도 이식될 수 있습니다.
이는 전체 자바스크립트 환경이 이 웹어셈블리 인스턴스에 묶인다는 것을 의미합니다. 그래서 일단 배포하고 나면, 자바스크립트 코드를 전달하기만 하면 해당 코드가 실행됩니다.
그럼 기계의 메모리에서 직접 작업이 이뤄지는 대신, JS 엔진은 바이트코드부터 바이트코드가 조작하는 GCed(Garbage Collected) 객체까지 모든 것을 Wasm 모듈의 선형 메모리에 넣습니다.
JS 엔진으로는 Firefox에서 사용되는 SpiderMonkey를 사용했습니다. SpiderMonkey는 브라우저에서 숱한 테스트를 거친, 업계에서 가장 강력한 자바스크립트 VM 중 하나입니다. 신뢰할 수 없는 코드 또는 신뢰할 수 없는 입력을 처리하는 코드를 실행할 때 이런 종류의 보안 테스트 및 투자는 중요합니다.
SpiderMonkey는 또한 정밀 스택 스캔(precise stack scanning)이라는 기술을 사용합니다. 뒤에서 설명하겠지만, 이는 일부 최적화에 중요한 기술입니다. 또 이해하고 읽기 매우 쉬운 코드 베이스를 가지고 있는데, 이는 Fastly, Mozilla 및 Igalia 3개의 다른 조직의 구성원들이 협력하고 있는 상황이기 때문에 중요합니다.
지금까지 설명한 접근 방식에서 혁신적인 것은 없습니다. 사람들은 이미 몇 년 동안 이처럼 웹어셈블리로 자바스크립트를 실행해 왔습니다.
문제는 느리다는 것입니다. 웹어셈블리는 새로운 기계 코드를 동적으로 생성하고 순수한 웹어셈블리 코드 내에서 실행할 수 없습니다. 즉, JIT를 사용할 수 없습니다. 인터프리터만 사용할 수 있습니다.
이 제약 조건을 감안하면, 당신은 다음과 같이 질문할 수 있습니다...
JIT를 통해 브라우저가 자바스크립트를 빠르게 실행할 수 있기 때문에(그리고 웹어셈블리는 모듈 내부에서 JIT 컴파일을 할 수 없기 때문에) 웹어셈블리를 사용하는 것이 직관에 반하는 것처럼 보일 수 있습니다.
하지만 만약 이런 상황에도 불구하고 자바스크립트를 빠르게 실행할 수 있다면 어떨까요?
이게 가능할 때, 유용할 수 있는 몇 가지 사례를 살펴보겠습니다.
보안 문제로 인해 JIT를 사용할 수 없는 곳들이 있습니다 (예: 권한이 없는 iOS 앱, 일부 스마트 TV 및 게임 콘솔).
이런 플랫폼에서는 인터프리터를 사용해야 합니다. 하지만 이런 플랫폼에서 실행되는 애플리케이션은 오래 실행되며 많은 코드가 필요합니다… 역사적으로, 이런 환경은 실행 속도를 훨씬 더 늦추기 때문에 인터프리터를 사용하고 싶지 않은 환경입니다.
만약 기존 접근 방식을 빠르게 만들 수 있다면, 개발자들은 지나친 성능 저하 없이도 JIT가 없는 플랫폼에서 자바스크립트를 사용할 수 있습니다.
JIT가 문제가 아니지만 서버리스 함수와 같이 시작 시간이 문제인 것들도 있습니다. 여러분들도 한 번쯤은 들어봤을 콜드 스타트(cold-start) 지연 문제입니다.
가장 잘 갖춰진 자바스크립트 환경(순수히 JS 엔진만 가동하는 격리 환경)을 사용하는 경우에도 시작 지연 시간이 최소 5밀리 초까지 걸릴 수 있습니다. 여기에는 응용 프로그램을 초기화하는 데 걸리는 시간은 포함되지도 않습니다.
시작 시간 지연을 숨기는 방법들이 있습니다. 그러나 QUIC과 같은 제안에서 네트워크 계층에서 연결 시간이 최적화되고 있으므로 이를 숨기기가 점점 더 어려워지고 있습니다. 또한 여러 서버리스 기능을 함께 연결하는 것과 같은 작업을 수행할 때 이를 숨기는 것은 더욱 어렵습니다.
지연 시간을 숨기기 위해 이러한 기술을 사용하는 플랫폼은 종종 다른 요청 간에 인스턴스를 재사용합니다. 이는 때에 따라 서로 다른 요청 간에 전역 상태를 관찰할 수 있음을 의미하며 보안상 위험합니다.
콜드 스타트 문제로 인해 개발자들은 종종 모범 사례를 따르지 않습니다. 하나의 서버리스 배포에 많은 기능을 포함합니다. 이에 따라 장애 범위가 더 커질 수 있는 또 다른 보안 문제가 발생합니다. 해당 서버리스 배포의 한 부분이 악용되면 공격자는 해당 배포의 모든 항목에 접근할 수 있습니다.
그러나 이런 상황에서 자바스크립트 시작 시간을 충분히 빠르게 할 수 있다면, 갖가지 방법으로 시작 시간을 숨길 필요가 없습니다. 그저 마이크로초 안에 인스턴스를 시작하면 됩니다.
결과적으로 각 요청마다 새 인스턴스를 사용할 수 있습니다. 즉, 여러 요청 사이에 공유되는 상태가 존재하지 않습니다.
이 인스턴스들은 매우 가볍기 때문에 개발자는 자유롭게 코드를 세분화할 수 있고, 단일 코드 조각에 대한 장애 반경이 최소화됩니다.
이 접근 방식에는 또 다른 보안 이점이 있습니다. 단순히 경량화되고 세분화된 격리를 가능하게 하는 것 외에도, Wasm 엔진의 보안 경계는 더 신뢰할 수 있습니다.
격리를 생성하는 데 사용되는 기존 JS 엔진은 매우 복잡한 최적화를 수행하는 많은 저수준 코드를 포함하는 대규모 코드 베이스입니다. 때문에, 공격자가 VM을 탈출하고 VM이 실행 중인 시스템에 액세스 할 수 있도록 허용하는 버그가 발견되기도 쉽습니다. 이것이 바로 Chrome 및 Firefox에서 각 사이트가 완전히 분리된 프로세스에서 실행되도록 최대한 노력하는 이유입니다.
이와 비교해서, Wasm 엔진은 훨씬 적은 코드가 필요하므로 검사하기가 더 쉽고, 많은 부분이 메모리 안전성이 보장된 언어인 Rust로 작성됩니다. 그리고 웹어셈블리 모듈에서 생성된 기본 바이너리의 메모리 격리는 검증할 수 있습니다.
Wasm 엔진 내부에서 JS 엔진을 실행함으로써 우리는 외부에 더 안전한 샌드박스 경계를 또 다른 방어선으로 갖게 됩니다.
앞선 사례들을 살펴보니 Wasm에서 자바스크립트를 빠르게 만드는 것에는 큰 이점이 있었습니다. 그래서 어떻게 할 수 있을까요?
이 질문에 답하려면, JS 엔진이 시간을 할애하는 영역을 이해해야 합니다.
JS 엔진이 수행하는 작업은 대략 두 부분으로 나눌 수 있습니다: 초기화와 런타임.
저는 JS 엔진을 청부업자라고 생각합니다. 이 청부업자는 자바스크립트 코드를 실행하고 결과를 얻는 작업을 완료하기 위해 존재합니다.
청부업자는 실제로 프로젝트 실행을 시작하기 전에 약간의 예비 작업을 수행해야 합니다. 초기화 단계에는 실행의 시작 단계에서 한 번만 실행되면 되는 모든 것들이 포함됩니다.
모든 프로젝트에서 청부업자는 고객이 원하는 작업을 살펴본 다음, 해당 작업을 완료하는 데 필요한 리소스들을 설정합니다.
예를 들어, 청부업자는 프로젝트 브리핑 및 기타 문서들을 읽고 작업하기 쉬운 형식으로 변환합니다. 예를 들어 모든 문서를 저장하고 정리하면서 프로젝트 관리 시스템을 세팅합니다.
JS 엔진의 경우 이 작업은 소스 코드의 최상위 레벨을 읽어가며 함수를 바이트 코드로 파싱 하고, 선언된 변수에 메모리를 할당하고, 이미 정의된 값들을 세팅하는 것과 비슷합니다.
서버리스와 같은 특정 환경에서는, 각 애플리케이션 초기화 전에 발생하는 또 다른 초기화 부분이 있습니다.
바로 엔진 초기화입니다. 먼저 JS 엔진 자체를 시작해야 하고 내장 함수들을 환경에 추가해야 합니다.
이는 작업을 시작하기 전에 이케아 의자와 테이블을 조립하는 것처럼 사무실 자체를 세팅하는 것과 비슷하다고 생각합니다.
이 작업은 상당한 시간이 걸릴 수 있으며 서버리스 사용 사례에서 콜드 스타트 문제를 만드는 원인이기도 합니다.
초기화 단계가 완료되면 JS 엔진이 코드 실행 작업을 시작할 수 있습니다.
이 영역의 속도를 스루풋(throughput)이라고 하며 이 스루풋은 다양한 변수의 영향을 받습니다. 예를 들어보면,
이것이 JS 엔진이 시간을 보내는 두 단계입니다.
그럼 이 두 단계의 작업을 어떻게 더 빠르게 진행할 수 있을까요?
우리는 Wizer라는 도구로 초기화를 빠르게 만들기 시작했습니다. 천천히 설명하겠지만 성급하신 분들을 위해 먼저 보여드리겠습니다, 간단한 자바스크립트 애플리케이션을 실행할 때 아래와 같은 속도 향상이 있었습니다.
간단한 애플리케이션을 Wizer로 실행하면 0.36 밀리초(또는 360 마이크로초)밖에 걸리지 않았습니다. 이는 일반적인 자바스크립트 접근 방식에서보다 13배 이상 빠릅니다.
우리는 스냅샷이라는 것을 사용해 시작 시간을 향상시켰습니다. Nick Fitzgerald가 WebAssembly Summit talk about Wizer에서 자세히 설명했습니다.
그래서 어떻게 작동하냐구요? 코드가 배포되기 전 빌드 단계의 일환으로, 초기화가 끝날 때까지 JS 엔진을 사용하여 자바스크립트 코드를 실행합니다.
이 시점에 JS 엔진은 모든 자바스크립트를 파싱해 바이트코드로 전환하고, 이 바이트코드는 JS 엔진 모듈에 의해 선형 메모리에 저장됩니다. 또한 이 단계에서 엔진은 많은 메모리 할당 및 초기화를 수행합니다.
이 선형 메모리는 매우 독립적이기 때문에, 모든 값이 채워지면 그저 메모리를 가져와 데이터 섹션으로써 Wasm 모듈에 연결할 수 있습니다.
JS 엔진 모듈이 인스턴스화 되면, 데이터 섹션의 모든 데이터에 접근할 수 있습니다. 엔진이 어떤 데이터가 필요하다면 필요한 데이터 섹션(또는 그저 메모리 페이지를)을 자체 선형 메모리에 복사할 수 있습니다. 따라서 JS 엔진은 시작할 때 어떤 설정도 할 필요가 없습니다. 사전에 초기화된 모든 값이 준비되어 대기 중입니다.
현재는 이 데이터 섹션을 JS 엔진과 동일한 모듈에 연결합니다. 하지만 앞으로 모듈 연결이 준비되면 데이터 섹션을 별도의 모듈로 이용할 수 있습니다. 그럼 JS 엔진 모듈을 다양한 자바스크립트 애플리케이션에서 재사용할 수 있습니다.
이렇게 되면 정말 깔끔한 분리가 가능합니다.
JS 엔진 모듈은 엔진용 코드만 포함하게 됩니다. 즉, 일단 컴파일되면 해당 코드를 효과적으로 캐시 하고 많은 다른 인스턴스 간에 재사용할 수 있습니다.
반면 애플리케이션 모듈에는 Wasm 코드가 포함되지 않습니다. 초기화된 나머지 JS 엔진 상태와 함께 자바스크립트 바이트코드를 포함하는 선형 메모리만 포함합니다. 이렇게 하면 이 메모리를 쉽게 필요한 곳으로 보낼 수 있습니다.
이건 마치 JS 엔진 청부업자에게 사무실이 전혀 필요하지 않은 것과 같습니다. 대신 여행용 케이스만 가지고 다닙니다. 여행용 케이스에는 전체 사무실이 있고, JS 엔진이 작동할 수 있도록 모든 설정과 준비도 되어 있습니다.
그리고 이 방식의 가장 멋진 점은 자바스크립트에 의존적이지 않다는 것입니다. 웹어셈블리의 기존 속성을 사용하는 것뿐입니다. 따라서 Python, Ruby, Lua 또는 기타 런타임에서도 이와 동일한 기술을 사용할 수 있습니다.
따라서 이 접근 방식을 사용해 매우 빠른 초기화 시간을 얻을 수 있습니다. 그럼 스루풋은요?
일부 사용 사례의 경우 스루풋이 그렇게 나쁘지 않습니다. 매우 짧게 실행되는 자바스크립트 조각인 경우, 어쨌든 JIT를 거치지 않고 전체가 인터프리터를 통해 실행됩니다. 따라서 이 경우 스루풋은 브라우저에서와 거의 동일하며, 기존의 JS 엔진이 초기화를 완료하기 전에 완료됩니다.
그러나 더 오래 실행되는 자바스크립트라면 JIT가 금방 작동하기 시작합니다. 일단 작동하기 시작하면 스루풋 차이가 분명해지기 시작합니다.
위에서 말했듯이 현재 순수한 웹어셈블리 내에서 코드를 JIT 컴파일하는 것은 불가능합니다. 다만 JIT에 적용되는 개념 중 일부를 Ahead-Of-Time 컴파일 모델에 적용할 수 있음이 밝혀졌습니다.
JIT가 사용하는 한 가지 최적화 기술은 인라인 캐싱(Inline Caching, 이하 IC)입니다. 인라인 캐싱을 통해, JIT는 자바스크립트 바이트코드가 과거에 실행된 모든 방식에 대한 빠른 기계어 경로를 포함하는 스텁의 연결 리스트를 생성합니다. (자세한 사항은 JIT(Just-In-Time) 컴파일러 집중 과정 참고하세요)
이 리스트가 필요한 이유는 자바스크립트의 동적 타입 때문입니다. 코드 라인이 다른 타입을 사용할 때마다 새 스텁을 생성하고 목록에 추가해야 합니다. 그러나 이전에 같은 타입을 사용해 실행한 적이 있다면 이미 생성된 스텁을 사용할 수 있습니다.
인라인 캐싱은 일반적으로 JIT에서 사용되기 때문에, 인라인 캐싱이 매우 동적이고 프로그램마다 고유하다고 생각되는 경우가 많습니다. 그러나 AOT 환경에서도 적용될 수 있음이 밝혀졌습니다.
그리고 자바스크립트 코드를 살펴보지 않아도, 생성해야 할 많은 IC 스텁들을 알 수 있습니다. JS에는 많이 사용되는 패턴이 있기 때문입니다.
좋은 예는 객체의 속성에 접근하는 것입니다. 이는 많은 자바스크립트 코드에서 일어나며 IC 스텁을 사용해 속도를 높일 수 있습니다. 특정 "모양(shape)" 또는 "숨겨진 클래스"(즉, 동일한 방식으로 배치된 속성들)가 있는 객체의 경우 특정 속성에 접근할 때 해당 속성은 항상 동일한 오프셋에 있습니다.
전통적으로 JIT의 이러한 종류의 IC 스텁은 모양에 대한 포인터와 속성의 오프셋이라는 두 가지 값을 하드 코딩합니다. 이를 위해서는 사전에(Ahead-Of-Time)는 알 수 없는 정보가 필요합니다. 그러나 우리는 IC 스텁을 매개변수화 할 수 있습니다. 모양과 속성 오프셋을 스텁에 전달되는 변수로 취급할 수 있습니다.
이렇게 하면 메모리에서 값을 로드하는 단일 스텁을 생성한 다음, 모든 곳에서 이 스텁 코드를 사용할 수 있습니다. 자바스크립트 코드가 실제로 수행하는 작업과 관계없이 이러한 공통 패턴들에 대한 모든 스텁을 AOT 컴파일된 모듈에 만들어들 수 있습니다. 심지어 브라우저에서도 이 IC를 공유하면 유용할 수 있습니다. JS 엔진이 더 적은 기계어를 생성하게 돼 시작 시간과 명령 캐시 지역성(instruction-cache locality)을 개선하기 때문입니다.
이번 사례에서는 이 개념이 특히 중요합니다. 자바스크립트 코드가 실제로 수행하는 작업과 관계없이, 이러한 공통 패턴에 대한 모든 스텁을 AOT 컴파일된 모듈에 마련해둘 수 있음을 의미하기 때문입니다.
우리는 몇 킬로바이트의 IC 스텁으로 모든 자바스크립트 코드의 대부분을 다룰 수 있다는 것을 발견했습니다. 예를 들어 2KB의 IC 스텁으로 Google Octane 벤치마크에서 자바스크립트의 95%를 커버할 수 있습니다. 예비 테스트에서 이 비율은 일반적인 웹 브라우징에서도 유지되는 것으로 보입니다.
이런 종류의 최적화를 적용하면 초기 JIT와 동등한 스루풋에 도달할 수 있을 것입니다. 해당 작업을 완료하고 나면 브라우저의 JS 엔진 팀이 초기 JIT에서 그랬듯이, 더 디테일한 최적화를 추가하고 성능을 연마할 것입니다.
앞서 말한 것들이 프로그램이 뭘 하고 어떤 타입들이 프로그램에서 사용되는지 알지 못한 채로, 미리(Ahead-Of-Time) 할 수 있는 것들입니다.
그러나 JIT가 가지고 있는 것과 같은 종류의 프로파일링 정보에 접근할 수 있다면 어떨까요? 그럼 코드를 완전히 최적화할 수 있습니다.
다만 여기에는 문제가 있습니다. 개발자는 종종 자신의 코드를 프로파일링하는 데 어려움을 겪습니다. 대표적인 샘플 워크로드를 찾는 건 어렵습니다. 따라서 좋은 프로파일링 데이터를 얻을 수 있을지 확신할 수 없습니다.
프로파일링을 위해 좋은 도구를 사용할 수 있는 방법을 알아낼 수만 있다면, 자바스크립트를 오늘날의 JIT만큼 빠르게 실행할 수도 있습니다 (그리고 이 방식에는 예열 시간도 필요 없습니다!).
우리는 이 새로운 접근 방식에 대해 매우 기대가 크고, 어디까지 추진할 수 있을지 기대하고 있습니다. 또 다른 동적 타입 언어들이 같은 방식으로 웹어셈블리에 제공되는 것을 보기를 기대하고 있습니다.
당장 시작할 수 있는 몇 가지 방법이 있습니다. 궁금한 점이 있는 경우 Zulip에서 물어보세요.
자체 플랫폼에서 자바스크립트를 실행하려면 WASI를 지원하는 웹어셈블리 엔진을 내장해야 합니다. 이를 위해 Wasmtime를 사용할 수 있습니다.
그런 다음 JS 엔진이 필요합니다. 이 작업의 일환으로 SpiderMonkey를 WASI로 컴파일하기 위해 Mozilla의 빌드 시스템에 대해 전폭적인 지원을 하고 있습니다. 그리고 Mozilla는 Firefox를 빌드하고 테스트하는 데 사용되는 것과 동일한 CI 설정에 SpiderMonkey용 WASI 빌드를 추가하려고 합니다. 이는 WASI가 SpiderMonkey의 프로덕션 목표 중 하나가 되게 하고, WASI 빌드가 시간이 지나도 계속 작동함을 보장합니다. 즉, 앞서 설명한 방식 그대로 SpiderMonkey를 사용할 수 있습니다.
마지막으로, 사용자가 사전 초기화된 JS를 가져와야 합니다. 이를 돕기 위해 Wizer를 오픈 소스화 했고, 이를 빌드 도구에 통합해 JS 엔진 모듈의 사전 초기화된 메모리를 채우는, 애플리케이션별 웹어셈블리 모듈을 생성할 수 있습니다.
Python, Ruby, Lua 등과 같은 언어 커뮤니티의 일원이라면 해당 언어에 대한 버전도 빌드할 수 있습니다.
먼저, 앞서 SpiderMonkey를 이용했던 것처럼, 시스템 호출에는 WASI를 사용하여 런타임을 웹어셈블리로 컴파일해야 합니다. 그런 다음 스냅샷으로 빠른 시작 시간을 얻으려면 역시 앞서 설명한 것처럼 Wizer를 빌드 도구에 통합해 메모리 스냅샷을 생성할 수 있습니다.
자바스크립트 생태계는 올바르게 나아가고 있다.
이전 2개의 시대를 지나면서 여러 교훈을 얻고 발전해나가고 있음
3세대 프레임워크(Next.js, Nuxt.js, SveltKit, Remix 등)들은 1세대가 목표했던 올인원 솔루션을 다시 목표로 하고 있음.
2세대 프레임워크(React.js, Vue.js, Svelte) 겪었던 문제들을 해결해면서 장점들도 가져가고 있다.
3세대 프레임워크의 주요 초점들
기타 키워드들
웹 컴포넌트
웹어셈블리
script setup
을 백포팅하는데 집중중Suspense
안정화될 것 장점 | 단점 | |
---|---|---|
Flutter | 훌륭한 공식 라이브러리 생태계 React Native보다 더 많이 사용됨 | 높은 학습 비용 |
React Native | Codepush 기능 사용 가능 채용에 용이한 풍부한 개발자 풀 | 빈약한 공식 라이브러리 생태계 |
많은 사람들처럼, 저 역시 현지 라디오 방송국에서 흘러나오는 음악만 듣던 시절이 있었습니다. (30세 이상의 많은 사람들이 그랬을 거예요. 이게 아직 공감되지 않는다면, 잠시만 기다려 보세요.) 당시에는, 그것만으로 충분히 행복했습니다. 제게 필요한 모든 것을 갖춘 것 같았으니까요.
그러나 결국 다른 음악이 제 인생에 자리 잡기 시작했습니다. 새로운 친구들과 인터넷을 통해 이전에 좋아했던 것들과는 다른 새로운 아티스트들을 알게 되었죠. 제가 이전에는 좋아했던, 아니 적어도 좋아한다고 생각했던 음악에서 점점 멀어지게 되었습니다.
이 음악은 달랐습니다. 한 주 동안 사랑에 빠졌다가 다음 주에 질리는 일은 없었습니다. 음악을 듣는 것이 끝없는 순환의 일부가 아니었습니다.
오히려 그 반대였어요. 들으면 들을수록 더 좋아하고 감사하게 되는 음악이었죠. 깊이가 있었죠. 물론 그때까지 제가 좋아했던 시끄럽고 왜곡된 기타, 펀치라인 가사, 그럴듯하게 꾸며진 멜로디는 없었지만요. 놀랍게도 그 점이 오히려 노래를 더 좋게 만들었습니다.
그때 저는 제가 생각했던 것만큼 만족스럽지 않았을 수도 있다는 사실을 깨닫기 시작했습니다.
어쩌면 제 행복은 무지를 전제로 한 것일지도 모른다는 생각이 들었습니다.
아마도 음악에 한정되지 않더라도 이 이야기에 공감하실 수 있을 것 같습니다.
아마도 한때 좋아하지 않았던 음식이나 음료가 이제는 좋아하는 것 중 하나가 되었을지도 모릅니다. 아니면 예상치 못한 영화, 책, 게임, 팟캐스트, 인플루언서, 취미 등이 자신과 잘 맞는다고 느끼게 된 적이 있을지도 모릅니다.
세부 사항은 중요하지 않습니다. 제가 말하고자 하는 것은
잘난 척하는 힙스터의 프런트엔드 버전처럼 들리지는 않길 바랍니다. 그런 의도는 아니거든요. 올리브 가든에서 버드 라이트를 마시는 것이 좋은 시간이라고 생각하신다면, 좋아요, 대신 스틱빵은 좀 내놓으세요. (역자 주: 올리브 가든은 미국의 편안하고 저렴한 이탈리안 레스토랑 체인점이고 버드 라이트 역시 가볍게 마시기 좋은 미국의 맥주 브랜드. 스틱빵은 올리브 가든에서 제공하는 빵으로 맛있다고 알려져 있음. 익숙한 것 너머에 더 좋은 것이 있을 수 있다는 것을 말하기 위해 예시로 든 것.)
제가 하고자 하는 말은, 여러분이 자신도 모르게 더 좋은 것을 놓치고 있을지도 모른다는 생각을 부드럽게 공유하려는 것입니다.
익숙한 경계를 넘어 더 나은 것을 찾는다는 이 개념은 어쩌면 다른 삶의 영역과 마찬가지로 도구와 워크플로우에도 적용될 수 있습니다.
그리고 아마도, 그저 아마도 당신의 현재 만족감은, 최소한 어느 정도는 단순히 무엇을 놓치고 있는지 모르기 때문에 비롯되는 것일지도 모릅니다.
저는 이전에 '리액트는 프런트엔드 프레임워크의 새로운 기본이다' 라는 글을 쓴 적이 있는데, 리액트를 기본적으로 사용하는 대부분 사람은 이 프레임워크가 얼마나 낙후되어 있는지 잘 인식하지 못한다고 생각합니다.
그리고 여기서부터 우리의 비유에서 미흡한 부분이 보이기 시작합니다.
개인적인 취향에 국한해서 이야기해보면, 당신이 좋아하는 것에 대해 논쟁하거나 당신의 마음을 바꾸려고 블로그 포스트를 쓰지 않을 것입니다. (적어도 지금 이 나이에는) 누가 신경 쓸까요? 재밌게 즐기면 됩니다.
이러한 결정에는 진정한 책임이 수반됩니다. 단순히 우리가 좋아하는 것에 대한 것만은 아닙니다. 순전히 우리 자신을 위해 무언가를 만드는 것이 아니라면 개발에서 즐거움은 부차적인 요소이며, 가장 중요한 것은 사용자의 경험입니다.
여러분이 사용하고 있는 도구를 좋아한다면 정말 멋진 일입니다. 저는 그렇기를 바랍니다. 하지만 그것은 기껏해야 부수적인 임무일 뿐이며, 최악의 경우 잠재적으로 해로운 방해 요소가 될 수 있습니다. 개발자 경험(DX)이 사용자 경험(UX)을 대체해서는 안 됩니다.
그러니 어설픈 비유를 선택한 것을 용서해 주세요. 원한다면 평생 같은 음악을 계속 들을 수도 있습니다. 저도 그렇게 생각합니다. 하지만 우리가 사용하는 도구에 있어서는 기존의 편안함을 뛰어넘어야 할 매우 타당하고 중요한 이유가 있습니다.
리액트가 경쟁자들보다 뒤떨어진다는 생각은 생소할 수 있습니다. 많은 분처럼 여러분도 여전히 리액트가 프런트엔드에서 최신 표준이라고 생각할 수 있습니다. 따라서 본격적으로 목록으로 들어가기 전에 그 거품을 빠르게 파헤쳐 보겠습니다.
이 글을 쓰게 된 계기는 Alex Russell이 Mastodon에 쓴 글 때문입니다.
누군가 오늘 저에게 IE를 지원하지 않아도 되는 새로운 앱에서 리액트를 사용하는 이유가 있는지 물어왔습니다.
저는 단 하나의 이유도 생각해 낼 수 없었습니다...
리액트가 얼마나 구식이 되었는지 아주 놀라웠습니다.
Alex는 해당 스레드에서 웹 컴포넌트에 대한 리액트의 지원 부족을 언급했습니다. 이 기능은 수년 동안 리액트에서 눈에 띄게 누락되어 왔습니다. 그리고 네, "로드맵에 추가될 예정"이라고 합니다. 하지만 이 글을 쓰는 현재로서는 구현이나 예상 출시일에 대한 확고한 약속은 없습니다.
웹 컴포넌트는 그중 하나일 뿐입니다. 하지만 웹 컴포넌트는 "다른 모든 것이 이미 하고 있거나 더 잘하는 것"의 목록에 있는 유일한 항목은 아닙니다. (아래에서 몇 가지를 더 다룰 것입니다.)
리액트는 프레임워크 게임 초창기부터 표준을 정립한 덕분에 큰 혜택을 누렸습니다. 하지만 유연성과 적응성에서 심각한 단점을 수반했습니다. 2013년경에 시작된 이래로 리액트가 내린 모든 결정은 또 다른 기술 부채를 안고 있으며, 이는 동시대 동종 업계에서는 찾아볼 수 없는 문제입니다.
리액트는 2008년 제약 조건에 맞춰 설계된 13년 기술입니다. 2023년에는 혁신적인 것은 아무것도 없습니다. 사실, 현대에 기능적인 반응형 프런트엔드 프로그래밍을 하는 데 가장 느린 방법입니다...
리액트는 노후화되었고, 대부분 사람이 얼마나 많이 또는 얼마나 열악한지 깨닫지 못하는 것 같습니다. 위의 인용문을 다른 방식으로 표현하자면 (그리고 음악에 대한 서문과 다시 연결해 보겠습니다.)
(테일러 스위프트의 새 일곱 번째 앨범 출시 전이죠. Taylor's Version 발매를 포함하지 않습니다.)
따라서 당신이 지난 몇 년 동안 리액트를 사용해 온 많은 개발자 중 한 명이라면, 오랫동안 리액트를 사용해 왔기 때문에 잊어 버렸거나 전혀 몰랐던 것들이 있을 수 있습니다.
최신 프런트엔드가 빠르게 발전하는 만큼, 리액트를 왕좌에 올려놓았던 세상이 여러 면에서 더 이상 존재하지 않는다는 사실을 깨닫는 데는 매우 느린 것 같습니다. (그랬던 적이 있다면, 애초에 페이스북의 특정 문제와 유사한 문제를 가진 조직은 많지 않았습니다).
지난 10년 동안, 웹 브라우저는 자바스크립트와 CSS에서 놀라운 성장을 보여주며 새로운 기능들을 채택해 왔습니다. 기술과 사용자의 기대도 발전했고, 현재의 도구 생태계는 예상보다 훨씬 더 많이 반복하고 적응하며 리액트를 넘어선 발전을 이루었습니다. 그러한 발전은 기존의 소프트웨어로는 따라갈 수 없는 방식으로 이루어졌습니다.
리액트를 "레거시 소프트웨어"라고 부르는 것이 논란의 여지가 있다는 것을 알고 있지만, 이는 공정하다고 생각합니다. 비교적 복잡하고, 비교적 오래되었으며, 많은 규칙과 문제점을 포함하고 있고, 초보자는 종종 두려워하며, 리액트가 기반으로 하는 아키텍처 결정은 반복 능력에 방해가 되는 요소가 된 지 오래되었습니다.
이 시점에서 제가 아직 여러분을 완전히 소외시키지 않았다면(일종의 엘리트주의, 장황한 서론, 괄호 내용의 과도한 사용의 조합으로 인해), 여러분이 완전히 리액트 세계에만 집중하느라 놓쳤을지도 모르는 몇 가지를 공유하고 싶습니다. 여러분의 현재 재생 목록에 있는 것보다 더 좋다고 느낄 수 있는 곡들을 발견하게 될지도 모른다는 희망으로요.
다른 글에서도 언급했지만, "검증되지 않은" 프레임워크의 이름이 개발 프로젝트의 잠재적 도구로 떠오를 때마다 사람들이 가장 먼저 궁금해하는 것은 다음과 같은 질문입니다. 생태계가 얼마나 큰가?
이 글의 전제를 읽자마자 그런 생각을 하셨을 수도 있습니다. 리액트에서 다른 프레임워크로 옮길까? 아직 충분히 큰 프레임워크가 있을까?
왜 우리는 생태계 규모에 집착하는 걸까요?
물론 우리는 이 프레임워크가 몇 년 안에 사라지거나 유지보수가 중단되지 않을 것이라는 확신을 두고 싶습니다. 충분히 그럴 만합니다. 그리고 네, 저희는 너무 새롭거나 검증되지 않은 것에 모든 것을 걸진 않을 것입니다. 하지만 뷰, 스벨트, 프리액트, 솔리드, 아스트로 등은 모두 그 시점을 훌쩍 지났으며 잘 지원되고 유지되고 있습니다. 따라서 단순히 그것 때문만은 아닙니다.
그렇다면 진짜 문제는 무엇일까요? 제 생각에는
패키지가 우리의 프레임워크를 위해 구축되어야 한다고 훈련받았기 때문입니다.
이러한 사고방식은 제이쿼리에서 시작되었다고 볼 수 있지만, 리액트가 이를 가속했다고 생각합니다.
리액트를 사용하면 캐러셀, 지도, 아코디언 등 특정 작업을 수행하기 위해 모듈이나 위젯, 라이브러리가 필요할 때마다 반드시 리액트로 만들어야 했고, 일반 웹이나 자바스크립트는 사용할 수 없었습니다. 리액트의 모든 규칙과 상태 처리, 컴포넌트 라이프사이클의 특이점 때문에 리액트용으로 명시적으로 작성되지 않은 패키지나 라이브러리는 작동하지 않을 가능성이 높았습니다.
특히 "자바스크립트일 뿐"이라고 자주 주장하는 프레임워크의 경우, 그렇게 할 필요가 없습니다. 단지 자바스크립트라면 실제로 자바스크립트인 모든 것에서 그냥 작동해야 합니다.
물론 다른 프런트엔드 프레임워크에도 상태와 아키텍처에 대한 자체 규칙과 관습이 있습니다. 비유적으로, 그들의 마당에 있는 갈퀴를 밟을 수도 있습니다.(역자주: 다른 프레임워크에서도 비슷한 문제가 발생할 수 있다는 뜻) 그리고 스벨트나 뷰 또는 그 밖의 다른 프레임워크와 함께 작동하도록 특별히 구축된 것들은 항상 존재할 것이고, 또 그래야만 합니다.
하지만 결정적으로, 그리고 가능한 한 강력하게 강조하고 싶습니다.
다른 현대적인 도구와 프레임워크를 사용하여 빌드하는 경우, 바닐라 자바스크립트 패키지가 잘 작동할 가능성이 훨씬 더 높으며, 그 패키지는 수천 개가 넘습니다. 렌더링 주기나 기타 프레임워크 관련 문제를 일으킬 가능성도 훨씬 적습니다. 말할 것도 없이, 이들 모두 웹 컴포넌트를 사용할 수 있는 옵션도 있습니다.
특별히 제작된 패키지나 라이브러리가 필요하지 않은 경우가 많습니다. 왜냐하면 당신의 것은 이미 플랫폼과 호환이 되기 때문이며, 따라서 이미 존재하는 모든 것과 호환됩니다.
프리액트 시그널은 프리액트와 함께 사용하도록 만들어졌지만, 어떤 프레임워크나 심지어 바닐라 자바스크립트에서도 가져와서 사용할 수 있는 놀라운 예입니다. 웹 컴포넌트 역시 리액트가 아닌 거의 모든 최신 프레임워크와 호환됩니다.
프레임워크에 부족한 부분이 있다면 플랫폼에 이미 필요한 기능이 있을 가능성이 높습니다. (예를 들어, 폼 제출의 경우, 리액트에서 항상 골칫거리였지만 이제 양방향 데이터 바인딩과 브라우저에서 제공하는 규칙을 사용하면 무한히 쉬워졌습니다.)
그리고 최악의 경우, 필요한 것을 만드는 것이 리액트에서보다 훨씬 더 쉬워질 수도 있습니다. (useState
를 다른 프레임워크의 버전과 비교해 보면 알 수 있습니다.)
새로운 프레임워크는 매우 보수적인 개발자들에게 단점으로 여겨지곤 하는데, 그들은 모든 면에서 철저하게 검증되지 않은 것을 시도해 보기를 경계하기 때문입니다. 하지만 기술 부채와 오래된 브라우저 지원에 대해 걱정할 필요가 적고, 기존의 좋은 아이디어와 최신 브라우저 기능을 더 자유롭게 반복할 수 있다는 점에서, 새롭다는 것은 오히려 '장점'이라는 것을 기억해야 합니다.
훅은 리액트의 최신 진화 단계로, 클래스 컴포넌트를 대체했습니다.
정당하게 칭찬할 부분에는 칭찬을 하겠습니다. 훅은 프런트엔드 영역에서 엄청난 전환점이었습니다. 이것은 우리 애플리케이션에서 로직과 상태를 구성하는 방법을 혁명적으로 바꿨습니다. 훅은 부인할 수 없을 만큼 훌륭하며, 거의 모든 프레임워크가 상태 관리를 위한 훅과 유사한 모델을 고수하게 되었습니다.
하지만 리액트 훅은 더 이상 새로운 것이 아닙니다. (사실, 훅을 사용하는 안정적인 리액트는 제 아이와 거의 같은 나이이고 몇 주 후에 유치원에 입학합니다.)
훅은 더 이상 경쟁 우위나 주목할 만한 기능이 아니라 기본입니다. 그저 우리가 일을 하는 방식일 뿐입니다.
프리액트의 시그널은 여기서 언급할 가치가 있으며, 스벨트의 매우 단순한 스토어도 마찬가지입니다. 솔리드에도 시그널이 있습니다. 심지어 훅에서 직접적으로 영감을 받은 뷰 3의 컴포지션 API도 리액트 구현에 비해 몇 가지 주요 이점이 있습니다.
훅은 훌륭한 패턴이며, 리액트는 이를 대중화시킨 공로를 인정받아 마땅합니다. 하지만 거의 모든 다른 프레임워크가 더 적은 규칙과 보일러 플레이트 없이 훅을 더 잘 수행합니다.
시그널의 개념이 익숙하지 않으시다면, 지나치게 단순화시킨 표현이지만, 반응형 상태의 한 단계 더 나은 진화, 즉 전체 컴포넌트가 아니라 다시 렌더링할 필요가 있는 노드만 다시 렌더링하도록 기본값을 개선한 업데이트된 훅이라고 생각하시면 됩니다.
고백할 게 있습니다. 저는 useMemo
와 useCallback
의 차이점이 무엇인지, 언제 사용해야 하고 사용하지 말아야 하는지 아직 정확히 알지 못합니다. 말 그대로 오늘 오전에 바로 이 주제에 대한 글을 여러 개 읽었음에도 불구하고요. (농담이 아닙니다.)
두 번째 고백하자면, useEffect
의존성 배열에 들어가야 하는 것과 들어가서는 안 되는 것, 또는 그 이유가 여전히 직관적이지 않다는 것입니다. 저는 useEffect
호출을 작성할 때마다 린터가 좋아하는 모양으로 코드를 리팩터링하는 데 15분 정도를 소비하는 것 같은 느낌이 드는데, 실제로는 괜찮고 앱을 무한한 심연으로 빨아들이지 않을 것이라고 99% 확신하는 경우에도 마찬가지입니다.
리액트를 사용하신다면 아마 이런 고백에 공감하실 수 있을 겁니다. 어쩌면 이런 혼란과 모호함을 당연한 것으로 받아들였을지도 모릅니다. 하지만 그렇다면 한 가지 알아두세요.
다른 프레임워크에서는 이런 종류의 렌더링 사이클 미세 관리를 수년 동안 하지 않아도 되었습니다.
프레임워크는 실제로 필요하지 않은 리렌더링에 귀중한 자원을 낭비하지 않도록 이미 상황을 알고 있습니다. 그들은 필요하지 않은 것을 지속해 재평가하지 않고 값만 업데이트할 수 있을 만큼 똑똑합니다.
...대부분의 경우에 그렇습니다. 그들도 완벽하지는 않습니다. 하지만 무엇을 해야 하는지 알고, 기본적으로 성능 좋은 방식으로 수행하는 데는 리액트보다 훨씬 낫습니다.
다른 프레임워크에서도 몇 가지를 최적화해야 할 수도 있습니다. 완벽하지는 않습니다. 하지만 그렇게 할 때쯤이면 리액트에서 해야 했던 지점을 훨씬, 훨씬 지나고 있을 것입니다.
컴포넌트가 DOM에 들어갈 때 무언가를 수행하게 하고 싶거나, 다른 데이터나 변수를 기반으로 동적으로 무언가를 다시 계산하기를 원할 때 거의 모든 다른 프레임워크는 useEffect
보다 더 나은 방법을 가지고 있습니다.
여기서 너무 길게 설명할 필요는 없을 것 같습니다. React 커뮤니티 내에서도 useEffect
는 악명 높은 위험한 것으로 간주하며 심지어는 아예 피하는 경우도 많기 때문입니다. 하지만 저를 믿으세요. React 기반이 아닌 다른 어떤 프런트엔드 프레임워크도 이렇게 정상적이고 유용한 기능을 사용하는 것을 두려워하지 않으며, 그 어느 곳에도 이와 같은 모호한 규칙은 없습니다.
컴포넌트가 마운트될 때 무언가를 하기 위해 서드파티 패키지를 살펴보는 사람은 아무도 없습니다.
이것은 사람들이 새로운 (리액트가 아닌) 프레임워크가 등장할 때 즉시 묻는 또 다른 질문입니다. 확장성이 있을까요? 하지만 저는 이 질문이 약간 시대에 뒤떨어진 질문이라고 생각합니다.
기억할 가치가 있는 것은 리액트를 탄생시킨 세계에는 다른 문제들이 있었다는 것입니다.
당시에는 대부분의 프런트엔드 UI가 바닐라 자바스크립트나 제이쿼리(또는 이와 유사한 대안)로 빌드되었습니다. 그리고 지금 우리가 알고 있듯이 이러한 앱 구축 방식은 특정 한계를 넘어서는 확장이 불가능했습니다.
그 이유는 상호작용하고자 하는 모든 요소와 DOM 노드에 대해 직접 선택자를 작성해야 했고, 상태를 추적하고 동기화하는 방법을 직접 수동으로 만들어야 했기 때문입니다. 이 작업에는 보통 DOM을 읽고 쓰는 작업이 포함되는데, 이 작업은 지저분하고 오류가 발생하기 쉬우며 무엇보다도 속도가 느렸습니다. (그래서 가상 DOM이 등장했지만, 그것조차도 몇 년 동안 완전히 구식이 되었습니다.)
당시에는 모듈식 코드를 작성하는 것이 불가능에 가까울 정도로 어려웠고, JS 파일은 수천 줄은 아니더라도 수백 줄로 늘어나는 경우가 많았습니다. 여러 작성자가 같은 프로젝트에서 작업하는 경우 서로의 코드를 재창조하거나 반복하거나 심지어 재정의하는 경우가 많았습니다(코드가 공유 글로벌 네임스페이스에 들어가는 경우가 많았기 때문에 충돌 가능성이 훨씬 더 높았습니다). 그리고 앱의 규모가 크거나 복잡할수록(Facebook) 문제는 더욱 심각해졌습니다.
기억해야 할 것은 다음과 같습니다. 앱이 기하급수적으로 성장하더라도 합리적으로 유지 관리가 가능한가? 이것이 프런트엔드와 관련하여 "확장성이 있는가?" 를 기준이라는 점입니다.
리액트는 이러한 문제 중 많은 부분을 해결했습니다. 하지만 현대 공학의 기적이라기보다는 단순히 상태를 관리 및 공유하고, 데이터를 반응형으로 만들고, 복잡성을 추상화하며, 충돌, 네임스페이스 충돌, 재정의 없이 개발자가 동일한 프로그래밍 패턴을 공유할 수 있는 좋은 방법을 고안해 해냈습니다.
리액트는 프런트엔드 확장성을 위한 최고의, 유일한, 심지어 '최초의' 솔루션이 아니라 동일한 패러다임의 여러 버전 중 하나일 뿐입니다.
(또한 가장 오래된 버전 중 하나이기도 합니다.)
이를 어떻게 알 수 있을까요? 리액트의 성능을 다른 모든 프런트엔드 프레임워크와 대규모로 비교하는 수많은 벤치마크 테스트가 실행되어 그 결과가 공개되어 있습니다. (온라인에서 쉽게 구할 수 있기 때문에 여기서는 링크하지 않습니다.) 이 모든 테스트는 프런트엔드 분야의 거의 모든 다른 옵션이 리액트와 동등하거나 더 나은 성능을 발휘하며, 많은 경우 훨씬 더 나은 성능을 발휘한다는 것을 확인시켜 줍니다.
여기서는 앱의 크기가 커짐에 따라 복잡성이 선형적으로 증가하지 않고 최소한으로 유지되도록 하는 일반적인 의미의 확장을 언급하고 있습니다. 물론 일부 프레임워크는 마크다운 파일에서 정적 HTML을 빌드하는 것과 같은 더 전문화된 작업 측면에서 훨씬 더 나쁘거나 좋게 확장될 수 있습니다.
몇 년 전, 서버 렌더링 콘텐츠(주로 Next.js를 통해)에 관한 한 리액트가 거의 유일한 해결책이었던 시절이 있었습니다. 사람들은 리액트를 클라이언트가 아닌 서버에서 단일 페이지 앱(SPA)으로 HTML로 렌더링할 수 있다는 사실에 당연히 흥분했습니다. 속도와 SEO 개선 효과는 무시할 수 없었고, 처음에는 다른 프레임워크가 따라잡는 데 다소 시간이 걸렸습니다.
하지만 일반적으로, 특히 이 글의 주제와 마찬가지로 가장 먼저 개선을 시작하는 것이 최고인 경우는 거의 없습니다.
스벨트키트는 사용자가 아무것도 할 필요 없이 기본적으로 서버 렌더링되며, 렌더링 패턴을 세밀하게 제어할 수 있습니다. 뷰의 메타 프레임워크인 Nuxt는 게임에 더 일찍 참여했습니다(Next.js에서 영감을 받은 것이 분명합니다).
프레시(Deno의 프런트엔드 프레임워크)는 "아일랜드"(클라이언트 렌더링)로 지정한 것을 제외하고는 전적으로 서버 렌더링이며, 그 외에는 정적 HTML로만 제공됩니다. 프레시는 또한 프리액트를 사용합니다(이 역시 리액트보다 훨씬 빠르며, 훨씬 더 성능이 좋고 인체공학적인 버전의 useState
와 반응성 모델인 시그널를 가지고 있습니다.).
아스트로는 서버 렌더링 기능을 가지고 있으며, 원하는 컴포넌트를 서버 렌더링할 수 있습니다. 다른 프레임워크의 컴포넌트도 잘 렌더링할 수 있으며, 경우에 따라서는 Next.js의 주요 성능 업그레이드로 주목받기도 했습니다.
솔리드스타트(솔리드의 메타 프레임워크)에는 서버 렌더링이 있습니다. 퀵은 전적으로 이 프레임워크를 중심으로 구축되었습니다. Ember 및 Angular와 같은 오래된 프레임워크도 스토리가 있으며, 다른 프레임워크들도 있을 것이라 확신합니다.
요점은 과거에 리액트는 클라이언트 뷰 프레임워크 컴포넌트를 서버에서 렌더링하는 개념을 가진 몇 안 되는 프레임워크 중 하나였다는 것입니다. 하지만 지금은 서버 렌더링이 필수입니다. 많은 최신 프레임워크는 서버에서 렌더링할 수 있는 옵션을 제공할 뿐 아니라 기본값으로 렌더링합니다.
PHP가 돌아왔습니다.
리액트는 페이스북이 페이스북 고유의 문제를 해결하기 위해 만들었다는 점을 기억하는 것이 중요하다고 생각합니다.
데이터는 한 방향(하향식)으로만 흘러야 한다는 리액트의 강력한 의견 중 하나는 2010년대 초에 Facebook이 직면했던 엔지니어링 도전이 어떻게 리액트의 아키텍처를 형성했는지를 보여주는 좋은 예입니다.
한동안은 단방향 데이터 흐름이 모범 사례로 간주하는 것처럼 보였습니다. 하지만 요즘에는 양방향 데이터 바인딩의 함정에 대한 해결책을 대부분 찾아냈고, 많은 경우 이것이 실제로 훨씬 더 편리하다는 것을 알게 되었습니다.
리액트에서 폼을 작업하는 것은 악명이 높습니다. 이는 사용자의 모든 키 입력이 두 단계 과정을 거치기 때문입니다. 입력에서 값을 얻어온 다음, 그 값을 상태에 설정해야 합니다(이에 따라 입력이 불필요하게 다시 렌더링되며 이미 있던 정확한 값을 포함하게 되지만 리액트 상태와 동기화됩니다.). 물론 보통은 너무 빨라서 눈치채지 못하지만, 추가 작업이 많이 필요합니다.
스벨트, 뷰 등 다른 많은 자바스크립트에서는 이 문제가 없습니다. 상태를 양방향으로 자동 업데이트되도록 바인딩할 수 있습니다. 상태가 변경되면 DOM이 업데이트되고, DOM이 변경되면 상태가 업데이트됩니다.
이렇게 하면 여러 단계를 거칠 필요가 없습니다. 예를 들어 텍스트 상자의 값만 캡처하려는 경우 양방향 데이터 바인딩을 수행하면 됩니다. 그러면 사용자가 필드에 입력하면 데이터가 자동으로 업데이트되므로 추가 단계 없이 적절한 시점에 데이터를 가져올 수 있습니다. 그 사이에 값을 설정하거나 필드를 지우는 등의 작업을 수행해야 하는 경우에도 한 줄로 간단하게 처리할 수 있습니다.
양방향 데이터 바인딩을 사용하면 한쪽이 다른 쪽을 따라잡고 있는지 계속 확인할 필요 없이 데이터와 DOM을 동기화 상태로 유지할 수 있습니다.
이 기능을 사용하면 문제가 발생할 수 있나요? 물론 그럴 수 있습니다. 하지만 모범 사례에 대한 독단적인 이상은 도움이 되기보다는 오히려 방해가 될 수 있습니다. 단방향 데이터 흐름이 대표적인 예입니다.
리액트로 주로 작업한다면 프런트엔드 컴포넌트에서 스타일을 처리하는 과정을 두 번, 세 번, 혹은 그 이상 반복했을 가능성이 높습니다.
.css 파일을 JSX 컴포넌트로 바로 가져왔을 수도 있고, CSS 모듈, 스타일 컴포넌트 및/또는 테일윈드를 사용했을 수도 있습니다(아마도 classnames
또는 tailwind-merge
패키지와 함께, 또는 둘 다와 추가 테일윈드 애드온을 함께 사용했을 수도 있습니다). 그리고 이것들은 가장 인기 있는 옵션일 뿐입니다.
테일윈드는 그 자체로 토끼굴입니다(그리고 그 자체로 프런트엔드 프레임워크로 제가 특별히 좋아하지 않습니다. 저는 플랫폼의 결에 반하는 것은 단기적인 이득을 얻는 대신 결국 장기적인 손실로 이어진다고 생각합니다.) 하지만 어쨌든 이러한 스타일링 솔루션이 존재하고 상당수 채택된 것은 적어도 부분적으로는 리액트가 처음 출시될 때부터 공식 스타일링 옵션이 없는 공백이 있었기 때문입니다.
특히 뷰와 스벨트는 모두 자체적인 컴포넌트 스타일링 스토리를 가지고 있습니다. 둘 다 컴포넌트 수준 스코핑을 지원합니다(뷰는 참여 동의(opt-in) 방식이고, 스벨트에서는 참여 철회(opt-out) 방식입니다.). 둘 다 바닐라 CSS와 훌륭하게 작동합니다(원하는 방식이라면). 하지만 다른 모든 프런트엔드 프레임워크와 마찬가지로 이 두 프레임워크는 CSS 모듈, 테일윈드, Sass 또는 기타 사용하고자 하는 다른 프레임워크와도 호환됩니다.
하지만 가장 중요한 점은 CSS의 모든 문제(실제로 문제라고 생각하든 그렇지 않든)가 내장된 스타일 처리 기능으로 완벽하게 해결된다는 점입니다. 범위 지정 CSS는 상상할 수 있는 거의 모든 문제를 해결하기 때문에 다른 곳에서처럼 복잡한 패키지와 설정이 필요하지 않습니다.
CSS가 나쁘다는 이유 목록을 읽어보세요(실제로는 그렇지 않지만, CSS를 잘 모르는 사람들은 그렇게 말하길 좋아합니다). CSS에 대한 거의 모든 비판은 범위 지정 스타일링으로 해결되며, 여러 비(非)반응형 프레임워크에 이미 이 기능이 내장되어 있습니다.
저는 리액트를 주로 교육받은 개발자들이 배우기가 얼마나 어려웠는지 되돌아보고 다른 프레임워크의 학습 곡선도 비슷하게 평가할 것으로 생각합니다. 아마 그것이 우리가 새로운 시도를 하지 못하게 하는 이유 중 하나일 것입니다. 왜냐하면 처음이었기 때문에 정말 어려웠기 때문입니다.
상태 관리, 프로퍼티, 중첩, 컴포넌트 수명 주기, 훅, 그리고 물론 JSX를 작성하는 방법까지... 정말 많은 것들이 있습니다. 아무리 열렬한 리액트 팬이라도 초보자가 빠르게 익히기가 쉽지 않다는 것을 인정할 것입니다. (그렇지 않다고 말하는 사람은 아마 초보자였을 때를 잊어버린 사람일 것입니다.)
공감하실 수 있다면 좋은 소식이 있습니다.
저는 이것을 두 번째 악기를 배우는 것에 비유합니다 (음악에 다시 연결하기 위해서가 아니라). 처음 연주를 배울 때는 특정 악기를 배우는 것 외에도 음악에 대한 모든 것을 배우고, 악기로 원하는 소리를 내는 방법을 배우게 됩니다. 하지만 두 번째 악기를 배울 때는 많은 부분을 건너뛸 수 있습니다. 모든 개념이 익숙해집니다. 음악을 이해하니까요. 여러분이 해야 할 일은 기존의 지식과 근육 기억을 약간 다른 형태로 옮기는 것뿐입니다.
프런트엔드도 비슷합니다. 모든 프런트엔드 프레임워크에는 컴포넌트가 있고, 모두 타입스크립트와 호환되며, 모두 프로퍼티, 자식, 반응 상태라는 개념이 있습니다. 이러한 것들은 우리가 일반적으로 좋아하고 좋다고 동의한 것들입니다. 다만 구현 방식이 다를 뿐입니다.
말하자면, 리액트는 의심할 여지 없이 이러한 아이디어를 확산하는 데 도움이 되었지만, 리액트가 이러한 아이디어를 이상적으로 구현하는 것으로 생각하는 것은 어리석은 일입니다.
훌륭한 것은 반복을 통해 만들어지며, 대부분의 경우 나중에 나온 프런트엔드 영역의 다른 선택은 리액트의 핵심 아이디어를 기반으로 발전한다는 뚜렷한 이점을 가지고 있습니다.
즉, 리액트는 main
보다 한참 뒤처진 git 브랜치와 비슷합니다. 리액트가 당신 은하계를 공전하는 별이라면 깨닫지 못할 수도 있지만... 프런트엔드는 이미 발전했습니다. 생태계는 이러한 아이디어를 받아들여 더 나은 것을 만들기 위해 달려왔습니다.
이제 더 성능이 뛰어나고 덜 복잡하며 배우기 어려운 옵션이 넘쳐납니다. 그리고 이미 리액트를 알고 있다면 그 어떤 것도 배우기 어렵지 않을 것입니다.
다음 두 섹션은 게시물의 초안에는 포함되어 있지 않았으며, 2023년 8월 15일에 원본 버전에 대한 피드백을 해결하기 위해 추가되었습니다.
이러한 주제를 논할 때 자주 듣는 말은 대략 다음과 같습니다.
항상 새롭고 빛나는 것만 쫓는 멍청한 자바스크립트 개발자들! 그들은 프로젝트를 장기적으로 유지하는 데는 관심이 없어. 새롭고 멋진 프레임워크는 내일이면 잊히고 코드가 실행되지도 않을 거라고!
여기에 조금의 진실이 있습니다. 사실, 자바스크립트 개발자들(감히 말하자면 보통의 프런트엔드 개발자들)은 다른 프로그래밍 전문가들이 경계하는 것에 비해 조금 더 새로운 것에 끌리는 경향이 있는 것 같습니다.
...그런데 실제로는 얼마나 사실일까요? 전 세계 모든 자바스크립트 개발자가 새로운 것이 나타나는 순간 그들의 기술 스택 전체를 다시 작성하러 나설 것이라 확신하나요? 아니면 끊임없는 온라인 유행 흐름에 의해 양산되어 그렇게 느껴지는 것일까요?
저는 이 현상이 실제보다 더 과장돼 보이는 것이라고 생각합니다. 왜냐하면 얼리 어답터들은 모든 주목을 받는 경향이 있기 때문입니다. 그들은 많은 블로그 게시물을 작성하고 동영상을 제작합니다. 이것들이 공유되고 회자되면서 실제보다 훨씬 더 많은 종류의 행동이 일어나고 있는 것처럼 보이는 경향이 있기 때문에 실제보다 훨씬 더 과장되어 보이는 것 같습니다. (이 말이 절반만이라도 사실이라면 리액트의 시장 점유율은 지금보다 훨씬 낮아졌을 것입니다.)
제가 만난 대부분의 프런트엔드 개발자들은 다른 종류의 개발자들과 마찬가지로 자신이 알고 있는 것을 고수합니다. 단지 새로운 것을 시도하는 데 비용이 상대적으로 덜 들기 때문에 그렇게 한다고 생각합니다.
하지만 이러한 관점은 현장에서 사용할 수 있는 다른 선택지의 성숙도를 과소평가하는 것입니다.
뷰는 리액트만큼이나 오래 사용되어 왔으며 현재 버전(v3)은 거의 3년 전에 출시되었습니다. 최신 버전의 스벨트는 리액트 훅이 출시된 지 2개월 후에 출시되었으며(2개월 전에 리액트 훅이 새롭고 반짝이는 것이라고 생각하셨나요?), 스벨트키트는 거의 1년 전에 1.0을 출시했습니다. 프리액트는 버전 10에 있습니다. 솔리드는 2년이 넘도록 1.0+ 버전입니다. 아스트로는 1년 전에 1.0을 출시했습니다. 여기서 언급할 퀵과 프레시는 가장 최근에 출시되었지만 올해 초 기준으로 모두 1.0 버전입니다.
따라서 이러한 항목 중 일부가 아직 너무 새롭더라도 괜찮습니다. 이해합니다. 하지만 리액트 대안에 대한 고려를 짧은 기간 때문에 축소시키는 것은 이 분야의 성숙도와 깊이를 간과하는 잘못된 판단입니다.
이 주제에 대해서는 이미 많은 글이 있기 때문에 너무 길게 설명하지는 않겠습니다(제가 쓴 다른 글에도 있고, 온라인에서 쉽게 찾을 수 있습니다). 하지만 간단히 말하자면 리액트는 미미할 정도로만 느리게 느껴질 수 있지만(특히 매우 고급/최신 하드웨어와 매우 빠른 인터넷 연결을 사용하고 있다면 더욱 그렇습니다), 그 차이는 사소한 것이 아닙니다.
리액트는 성능(번들 크기와 실행 속도를 모두 의미합니다) 측면에서 많은 경우 2배 이상 뒤쳐집니다. (번들 자체는 10배 이상 차이가 날 수도 있습니다.) 최근 실행된 JS 웹 프레임워크 벤치마크에 따르면 리액트의 성능은 평균적으로 솔리드보다 거의 50%, 뷰보다 25%, 스벨트보다 40%, 프리액트보다 35% 느린 것으로 나타났습니다. (이 테스트에서는 다른 프레임워크가 사용되지 않았습니다.)
이 비교는 useTransition
훅과 리덕스와 같은 추가 라이브러리를 사용하지 않고 리액트 훅만 사용했을 때였습니다.
다른 연구도 있습니다. 연구마다 수치가 조금씩 다를 것이고, 연구 결과에는 항상 미묘한 차이가 있을 것입니다. 하지만,
실제 사례를 통해 설명하자면, 저는 안드로이드 폰에서 작성하는 폼에 리액트가 사용된다면 그걸 알 수 있습니다. 느린 속도와 상태와 일치하도록 DOM을 업데이트하는 루프가 반복되기 때문입니다. 그리고 리액트가 아니면 눈치채기가 힘듭니다.
하지만 사례는 잊어버리세요. 방금 데이터를 봤으니까요. 그리고 이 수치가 크게 느껴지지 않을 수도 있고, 기술 스택을 선택할 때 성능은 여러 고려 사항 중 하나일 뿐이라는 것을 알고 있습니다. "모든 것은 상황에 따라 다릅니다."
하지만 25 ~ 50%의 성능 개선은 성능 향상 측면에서 엄청난 수치라는 점을 기억하세요. 사용자의 프런트엔드 로딩 속도를 최대 두 배까지 향상한다는 것은 단순히 약간의 성능 향상의 수준을 훨씬 뛰어넘어 규모에 따라 엄청난 차이를 가져올 수 있는 수치입니다.
웹사이트를 로딩하거나 작업이 완료되기를 기다릴 때 매 초가 얼마나 중요한지 수많은 연구를 인용하지 않아도 알 수 있을 것입니다. 또한 대용량 자바스크립트 번들을 다운로드할 대역폭이 없거나 프레임워크가 페이지를 변경할 때마다 최대 2배 더 오래 기다릴 수 있는 컴퓨팅 성능이 떨어지는 사용자를 고려하는 것이 얼마나 중요한지 굳이 설명할 필요가 없으리라 생각합니다.
이렇게 큰 로딩 또는 처리량을 줄인 엔지니어는 이를 이력서에 눈에 띄는 위치에 기록할 것입니다. 이는 중요한 문제입니다.
리액트와 나머지 필드 사이의 성능 차이는 미미하지 않습니다. 오히려 최소화된 것입니다.
아마도 수십 단락 전부터 궁금해지기 시작했을 것입니다. 리액트가 그렇게 구식이라면 대안은 무엇일까요?
여기서는 몇 가지를 다루고 그 사용 사례에 대해서도 언급하겠습니다. 리액트의 문제 중 하나는 오랫동안 모든 사람을 위한 모든 것이 되려고 노력해 왔다는 점이며, 리액트 형태의 도구가 유용할 수는 있지만 하나의 스위스 군용 칼보다 두세 가지 다른 도구가 더 나을 수 있다고 생각합니다.
하지만 본격적으로 들어가기 전에 두 가지를 간단히 짚고 넘어가겠습니다.
위에서 언급한 다른 모든 최신 프레임워크를 다루기 위해 여기에 여러 옵션을 나열하고 있습니다. 이 모든 프레임워크에 대해 배우거나 사용할 것이라 예상하지는 않습니다. 굳이 하나를 선택해야 한다면 스벨트 또는 뷰를 선택하세요. 저는 철저함을 위해 모두 나열한 것뿐이라는 점을 알아두세요.
모든 옵션을 나열하지는 않았습니다. 언급하지 않은 다른 옵션도 있습니다.
예를 들어 Ember와 Angular는 생략했는데, 그 이유는 둘 다 리액트보다 오래되었고 일반적으로 벤치마크 테스트에서 리액트를 크게 앞지르는 경향이 없기 때문입니다(미안해요, Mel).
또한 Alpine 및 Petite Vue와 같은 경량 옵션은 생략했는데, 이는 리액트보다는 제이쿼리의 대체품에 가깝고 프레임워크처럼 무거운 것이 필요하지 않은 경우에 빛을 발하기 때문입니다.
마지막으로, 이 카테고리에서 약간 벗어난 매우 훌륭한 도구도 생략했습니다. Eleveny는 프레임워크라기보다는 순수한 정적 사이트 생성기에 가깝기 때문입니다. (하지만 개츠비를 사용 중이라면 한번 살펴볼 가치가 있습니다.)
이제 주간 추천을 소개합니다.
2023년도 수료생 여러분, 스벨트를 사용하십시오.
미래에 대한 한 가지 팁만 드릴 수 있다면, 그것은 스벨트일 것입니다.
농담은 제쳐두고, 이 목록에서 리액트보다 추천할 만한 것을 하나만 꼽으라면 스벨트가 될 것입니다. 저는 2019년에 트위터에서 "스벨트는 헛소리를 뺀 리액트다"라고 오랫동안 주장해 왔고(RIP), 시간이 지날수록 그 주장은 더욱 진실이 되어가고 있습니다.
스벨트는 사용하기 쉽고, 비교적 배우기 쉬우며(특히 이미 리액트를 사용해 본 적이 있다면 더욱 그렇습니다. 구문도 비슷한 경우가 많습니다), 거의 모든 경우에서 훨씬 더 성능이 뛰어나고, 리액트가 할 수 있는 모든 것을 할 수 있습니다. 이 사이트와 요즘 제가 하는 모든 사이드 프로젝트는 스벨트키트으로 작성됩니다.
스벨트는 가장 빠른 옵션과 비교해도 손색이 없을 정도로 빠릅니다. 개발자 설문조사에서 가장 사랑받는 프레임워크의 최상위권 또는 그 근처에서 자주 등장할 정도로 DX가 놀랍습니다.
스벨트는 가능한 한 웹 플랫폼에 가깝게 개발되었기 때문에 매우 강력하면서도 개념은 대체로 친숙할 것입니다. 또한 스벨트에는 트랜지션, 이징, CSS 처리, 컴포넌트 범위 스타일 등 다양한 기능이 기본으로 포함되어 있습니다.
프레임워크 크기에 대해 궁금해하실 수도 있지만, 스벨트는 자바스크립트 런타임이 아니라 컴파일러라는 점에서 다른 점이 있습니다. 빌드 시 사용하지 않는 모든 것이 제거되고 코드가 작은 바닐라 자바스크립트 비트로 트랜스파일됩니다. 즉, 스벨트의 번들은 일반적으로 리액트의 몇분의 1 크기입니다.
스벨트의 자체 메타 프레임워크인 스벨트키트는 정적, 서버 렌더링, 엣지 배포, 라우트별 혼합까지 가능한 매우 다재다능하고 강력합니다. 2022년 말에 1.0 버전이 출시되었으며 프로덕션에 바로 사용할 수 있습니다. (Next.js를 만드는 Vercel에서도 지원합니다.)
위와 같은 이유로 최고의 만능 옵션으로 프런트엔드의 즐거움을 재발견하고 싶은 경우.
리액트로 하는 모든 작업. 스벨트는 리액트 자체를 대체할 수도 있고, 스벨트키트는 Next.js, 개츠비, 리믹스를 대체할 수 있을 만큼 다재다능합니다(또는 한 번에 모두 대체할 수도 있습니다).
뷰는 아마도 리액트와 가장 유사한 선택지일 수 있으며, 다음으로 큰 생태계를 가지고 있을 것입니다. 하지만 리액트보다 성능이 훨씬 뛰어나고 UI에 좀 더 중점을 둡니다.
어떤 면에서는 뷰가 리액트에서 가장 작은 도약이라고 할 수 있는데, 특히 뷰 3에서 유사한 훅 기반 접근 방식을 사용한다는 점에서 더욱 그렇습니다. 그러나 뷰는 JSX보다 기본 HTML에 가까운 템플릿 언어를 사용하므로 map
및 삼항식과 같은 해결 방법을 사용하지 않고도 템플릿 파일에 조건문과 루프를 훨씬 쉽게 작성할 수 있습니다.
뷰는 Nuxt의 Next.js와 유사한 메타 프레임워크를 가지고 있으며, 잘 유지 관리되고 항상 강력한 새 기능을 추가하고 있습니다. 또한 뷰는 범위 지정 CSS 처리 및 쉬운 전환/애니메이션과 같은 기능을 즉시 사용할 수 있어 리액트보다 약간 더 많은 기능과 도구를 기본적으로 제공하고 있습니다.
커뮤니티 규모/전체 프레임워크의 인기가 중요한 요소인 경우, 리액트와 비슷하지만, 더 많은 기본 기능이 포함되거나 HTML과 유사한 것을 원하는 경우, 프레임워크가 대기업에 소유되지 않고 독립적인 것을 선호하는 경우.
리액트 자체 또는 Nuxt가 Next.js를 사용하는 모든 것을 대체할 수 있습니다.
솔리드는 제가 더 나은 리액트라고 부르는 것입니다. 많은 경우 리액트와 거의 (완전히는 아니더라도) 동일해 보이지만 솔리드가 훨씬 더 성능이 뛰어납니다. 사실 빠른 옵션 중 하나입니다.
솔리드는 기본적으로 리액트에서 시작하여 복잡성, 성능 문제 및 많은 보일러 플레이트를 제거하도록 재구성됩니다. 솔리드에서는 시그널이 개념이 나타나며 컴포넌트 렌더링과 수명주기에 대한 혼란과 발목을 잡는 요소가 상당 부분 제거됩니다. 2013년 이후 우리가 배운 모든 교훈을 바탕으로 현대에 리액트가 만들어졌다면 솔리드는 리액트라고 해도 과언이 아닐 것입니다.
솔리드는 현재 베타 버전이긴 하지만 솔리드스타트에서 자체 메타 프레임워크도 제공합니다. 하지만 솔리드 자체는 충분히 사용하기에 충분히 성숙했으며 인상적인 후원사 갤러리를 자랑합니다.
일반적으로 리액트(및 JSX)를 좋아하지만, 더 현대적이고 빠르거나 더 쉬웠으면 하는 경우, 성능이 절대적인 최우선 순위인 경우.
리액트와 리액트 DOM. 솔리드스타트는 언젠가 Next.js를 대체할 수 있을 것으로 보이지만, 이 글을 쓰는 현재로서는 아직 베타 버전입니다.
프레시는 서버사이드 렌더링 프런트엔드 프레임워크로, Deno에 구축된 아일랜드 아키텍처를 사용합니다. 이 목록에 있는 다른 대부분의 항목보다 조금 더 어리지만, Deno로 구동되는 엣지에서 실행할 수 있는 최소한의 JS, 아일랜드 기반 프레임워크로서 가능성이 가득합니다. 즉, 서버 코드가 더 빠르고, 더 안전하며, 기본적으로 타입스크립트를 사용하고, Deno가 기존 Node보다 제공하는 다른 모든 이점(예: 더 쉬운 퍼스트 파티 린팅, 테스트 및 코드 서식 설정)을 누릴 수 있다는 뜻입니다.
모든 프레시 컴포넌트는 정적으로 렌더링되어 응답 시 자바스크립트 없이 HTML로 제공되거나, 클라이언트에서만 렌더링되는 "아일랜드"로 제공됩니다. 필요에 따라 혼합하여 사용할 수 있습니다. Deno에서 실행되므로 전 세계 모든 기기에서 최대한 빠르게 로드되는 매우 빠르고 동적인 콘텐츠를 제공할 수 있습니다.
프레시는 프리액트를 사용하므로 속도가 빠르다는 것을 알 수 있으며, 리액트를 사용하던 사용자도 어렵지 않게 익힐 수 있습니다. 그리고 다시 한번 말씀드리지만, Deno를 기반으로 구축하면 기분이 좋습니다.
클라우드에서 전 세계적으로 사용할 수 있는 서버사이드 앱, 최소한의 자바스크립트만 제공하거나 최신 기술을 기반으로 구축하는 것을 좋아합니다.
리믹스는 아마도 리액트 세계에서 프레시에 가장 가까운 것일 것입니다.
아스트로는 정적 이상의 기능을 제공하는 차세대 고성능 정적 사이트 생성기입니다. 아스트로는 이 목록에서 가장 최신 옵션 중 하나이지만 이미 매우 안정적인 1.0 릴리스에 있으며 광범위한 찬사와 채택을 받고 있습니다.
주로 차세대 SSG를 위해 개발되었지만(리액트 팬이라면 주목하세요. JSX와 MDX를 지원합니다), 이제 동적인 서버 측 기능도 제공합니다. 콘텐츠가 많거나 정적인 사이트에는 개츠비보다 더 추천하고 싶습니다.
진짜 킬러 기능은 다음과 같습니다. 아스트로는 기본적으로 자바스크립트를 전혀 제공하지 않습니다. 원하는 기능만 선택해서 사용할 수 있습니다.
또한 아스트로는 사용하려는 프런트엔드 프레임워크와 호환되므로 리액트, 뷰, 스벨트 등으로 템플릿을 제작하고 싶으시다면 가능합니다!
대부분 정적이거나 콘텐츠/마크다운 기반 사이트를 구축하는 경우(일부 서버 측 렌더링이나 로직이 필요할 수도 있음), 최소한의 자바스크립트만 제공하려는 경우, 자체 프런트엔드 프레임워크를 가져오고 싶은 경우.
개츠비 또는 유사한 리액트 기반 콘텐츠 도구.
리액트를 사용하시는 분이라면 이미 프리액트에 대해 알고 계시겠지만, 여기서는 언급할 필요가 있습니다. 프리액트는 리액트의 훨씬 더 날렵하고 빠른 버전입니다. 리액트를 대체하는 용도로 시작했지만, 리액트에는 없는 몇 가지 뛰어난 기능(이미 언급한 시그널과 같은)을 추가하기 시작했습니다.
기본적으로 리액트를 고수하고 싶지만 더 빠르기를 원하는 경우.
리액트. (사실, 앞에 P가 추가될 뿐입니다. P는 성능을 의미합니다. 제가 다 지어낸 말이니 프리액트 팀을 탓하지 마세요).
퀵 서버는 하이드레이션과 성능에 대한 새로운 접근 방식으로 리액트와 유사한 코드(JSX)를 렌더링합니다. 실제로는 "하이드레이션"이라고 할 수 없으며, 자바스크립트를 DOM에 직렬화하여 필요할 때만 작은 부분만 로드합니다. 퀵은 이 목록에서 더 심층적으로 다루고 있지만 가능한 한 빨리 실행해야 하는 상호작용이 많은 경우 한번 살펴볼 가치가 있습니다.
브라우저에 많은 자바스크립트를 전송하고 있으며, 이를 더욱 효율적으로 처리할 방법을 원합니다.
리액트 자체를 대체할 수 있으며, 엣지에서 매우 효율적으로 실행할 수 있습니다.
솔직히 저는 이 주제에 대해 잘 아는 사람이 아니기 때문에 깊이 들어가지는 않겠습니다. 웹 컴포넌트 자체나 웹 컴포넌트 프레임워크에 대한 경험이 부족하기 때문에 이 주제에 대해 잘 말할 수 없습니다.
그렇긴 하지만, 웹 컴포넌트 프레임워크/라이브러리의 혜택을 받을 수 있는 특정 종류의 프로젝트가 Lit, Stencil, Polymer 등과 같이 존재합니다. 이러한 라이브러리는 특정 프런트엔드 프레임워크에서 "독점적인" 컴포넌트를 생성하는 대신 실제 웹 컴포넌트를 작성하는 데 도움이 되며, 이 컴포넌트는 모든 웹 프로젝트에 이식할 수 있습니다.
제 생각에 대부분의 프로젝트는 여전히 순수 웹 컴포넌트보다 프런트엔드 프레임워크를 사용하는 것이 더 유리합니다. 아니면 최소한 두 가지를 함께 사용하는 것이 더 유리합니다. 앞으로는 상황이 달라질 수도 있겠지만, 현재로서는 대부분의 경우 여전히 순수 웹 컴포넌트 접근 방식에 유리하다고 생각합니다.
하지만 순수한 웹 컴포넌트 기반 접근 방식을 고려해야 하는 사용 사례도 분명히 있습니다. 그리고 그런 프로젝트의 경우 리액트는 확실히 과잉입니다. 위에서 언급한 웹 컴포넌트 라이브러리가 훨씬 더 적합할 것입니다.
여러 환경에서 동일한 컴포넌트를 재사용해야 하거나, 프레임워크 변경에 대비해 미래에 대비하고 싶거나, 플랫폼 사용을 선호하고 웹 컴포넌트 작성의 단점을 감당할 준비가 되어 있는 경우.
사용 사례에 따라 부분적으로만 리액트를 대체할 수 있습니다.
이 글은 작년에 제가 쓴 리액트의 자기충족적 예언과 매우 유사합니다. 동일한 영역을 다루고 있으며, (새로운 방식이나 새로운 관점에서 바라보긴 하지만) 동일한 주장을 하고 있습니다.
같은 내용을 반복할 생각은 없었지만, 우연찮게도 이 글이 게시될 무렵에 제가 리액트를 풀타임으로 사용하게 되면서 이 부분에 대해 많이 생각하게 된 것은 분명합니다.
저는 리액트의 인기는 상당 부분 사람들이 그 너머를 보지 않기 때문이라고 믿게 되었습니다. 최고는 아니지만 대부분 사람은 최고를 찾는 것이 아니라 그저 충분히 좋은 것을 찾고 있습니다. (우리는 인간입니다. 우리 모두의 결정에는 개인적이고 감정적이며 비합리적인 이유가 많이 있으며, 그것은 괜찮습니다. 우리는 바쁘니까요.)
적어도 프런트엔드 세계에서는 기술을 선형적으로 도입하기보다는 비약적으로 도입하는 것 같습니다. 모두가 리액트에 뛰어들게 된 이유 중 하나는 당시 모든 사람이 구식 기술에 갇혀 더 나은 것을 찾고 있었기 때문입니다. 우리는 점진적으로 새로운 것을 향해 조금씩 나아가는 것이 아니라(어쩌면 처음부터 그렇게 할 수 없었기 때문일 수도 있습니다), 현재 위치에서 다음 단계로 도약하는 거대한 도약을 했습니다.
하지만 중요한 것은 우리가 몇 년 전 그 도약을 한 이후로 거의 같은 자리에 앉아 있었다는 것입니다.
제 생각에 우리는 또 다른 도약에 가까워지고 있습니다.
그것이 무엇일지, 왜 그럴지는 모르겠습니다. 하지만 그 당시 제이쿼리에서 느꼈던 것처럼 리액트가 실제로 해결하지 못하는 문제들을 느끼기 시작한 것 같습니다. 그리고 결국에는 발전할 때가 되었다는 것이 분명해질 것으로 생각합니다.
그 새로운 것은 무엇일까요? 저도 모르겠어요. 그냥 웹 플랫폼이 될 수도 있습니다. 프레임워크가 필요 없을지도 모르죠. 위의 프레임워크가 될 수도 있고, 우리가 아직 보지 못한 무언가가 될 수도 있습니다. 어쩌면 어떤 것도 없을 수도 있고, 다양한 도구가 등장하고 하나의 표준으로 통합되지 않을 수도 있습니다(위의 모든 옵션 중에서 가능성이 가장 낮은 것으로 보이는 이유는 다시 말하지만, 인간이기 때문입니다. 인간은 바쁜 작은 원숭이이기 때문에 기본값을 좋아합니다.)
하지만 그 새로운 것이 무엇이든, 리액트와 그것의 차이는 시간이 지남에 따라 점점 더 커질 것으로 생각합니다.
그러니 하루하루가 이전보다 더 나은 날이 되어 여러분이 놓치고 있던 것을 탐구할 수 있기를 바랍니다.
들어주셔서 감사합니다.
원문: https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/
오늘 iOS 및 iPadOS 16.4 베타 1이 출시되었으며, 홈 화면 웹 앱에 대한 웹 푸시 및 기타 기능이 지원됩니다.
오늘 사파리 16.4의 첫 번째 베타 버전도 출시됩니다. 이번 버전은 정규표현식 후방탐색, Import Maps, 오프스크린 캔버스, 미디어 쿼리 범위 지정, @property
, font-size-adjust
, 선언적 쉐도우 DOM 등 135개 이상의 기능이 포함된 대규모 릴리즈입니다. 이러한 새로운 WebKit 기능에 대한 자세한 내용은 사파리 16.4가 공개될 때 작성하겠습니다. 한편, 새로운 기능 및 수정 사항의 종합적인 목록은 사파리 16.4 베타 1 릴리즈 노트에서 확인할 수 있습니다.
사파리는 잠시 제쳐두고 iOS 및 iPadOS의 홈 화면 웹 앱에 관해 이야기해 보겠습니다.
최초의 아이폰부터, 사용자는 브로슈어 사이트, 블로그, 신문, 온라인 상점, 소셜 미디어 플랫폼, 스트리밍 비디오 사이트, 생산성 소프트웨어, 아트워크 제작용 앱 등 모든 웹 사이트를 홈 화면에 추가할 수 있었습니다. 지난 10년 동안 iOS 및 iPadOS의 사파리 사용자는 공유 버튼을 탭 하여 공유 메뉴를 연 다음 '홈 화면에 추가'를 탭 하면 이 작업을 수행할 수 있었습니다. 그럼, 해당 웹사이트의 아이콘이 홈 화면에 나타나게 되고, 이 아이콘을 빠르게 탭해서 해당 사이트로 돌아갈 수 있습니다.
웹 개발자는 매니페스트 파일(display
멤버를 standalone
또는 fullscreen
으로 설정해야 합니다.)을 생성하여 웹사이트와 함께 제공할 수 있습니다. 그렇게 하면 해당 사이트는 홈 화면 웹 앱이 됩니다. 그런 다음 해당 아이콘을 탭 하면 웹 앱이 브라우저에서 열리지 않고 iOS 또는 iPadOS의 다른 앱처럼 열립니다. 사파리나 다른 브라우저와는 별도로 앱 스위처에서 앱 미리보기를 볼 수 있습니다.
iOS 및 iPadOS 16.4 베타 1에서 홈 화면 웹 앱에 웹 푸시 기능이 추가되었습니다. 웹 푸시는 웹 개발자가 푸시 API, 알림 API, 서비스 워커를 모두 연동하여 사용자에게 푸시 알림을 보낼 수 있도록 해줍니다.
홈 화면에 추가된 웹 앱은 웹 앱에서 제공하는 '구독' 버튼을 탭 하는 등 사용자의 직접적인 상호 작용에 대한 응답으로 푸시 알림 수신 권한을 요청할 수 있습니다. 그러면 iOS 또는 iPadOS는 사용자에게 웹 앱에 알림 전송 권한을 부여할지 묻는 메시지를 표시합니다. 허용되면 사용자는 iPhone 및 iPad의 다른 앱과 마찬가지로 알림 설정에서 웹 앱별로 해당 권한을 관리할 수 있습니다.
웹 앱의 알림은 다른 앱의 알림과 똑같이 작동합니다. 알림은 잠금 화면, 알림 센터 및 페어링 된 애플 워치에 표시됩니다.
이는 작년 가을 macOS Ventura용 Safari 16.1에 추가된 것과 동일한 W3C 표준 기반 웹 푸시입니다. 브라우저 감지 대신 기능 감지를 사용하는 등 모범 사례에 따라 웹 앱에 표준 기반 웹 푸시를 구현한 경우 iPhone 및 iPad에서 자동으로 작동합니다.
iOS 및 iPadOS의 웹 푸시는 모든 애플 디바이스에서 네이티브 푸시를 지원하는 동일한 애플 푸시 알림 서비스를 사용합니다. 애플 개발자 프로그램의 회원이 아니어도 사용할 수 있습니다. 서버 푸시 엔드포인트를 제어하고 있는 경우 *.push.apple.com
의 URL을 허용하기만 하면 됩니다.
웹 푸시 설정 방법에 대해 자세히 알아보려면 webkit.org에서 웹 푸시 만나기 문서를 참조하거나 WWDC22 세션 비디오 웹 푸시 만나기를 시청하세요.
알림은 강력한 도구이지만, 너무 많은 알림에 압도당하는 상황에 빠지기 쉽습니다. iPhone 및 iPad의 홈 화면 웹 앱에 대한 알림은 집중 모드와 통합되어 사용자가 언제 어디서 알림을 받을지 정확하게 설정할 수 있도록 합니다. 두 대 이상의 iOS 또는 iPadOS 장치에서 동일한 웹 앱을 홈 화면에 추가한 사용자의 경우 집중 모드가 모든 장치에 자동으로 적용됩니다.
iOS 및 iPadOS 16.4 베타 1의 홈 화면 웹 앱은 이제 배지 API를 지원합니다. iOS 및 iPadOS의 다른 앱과 마찬가지로 이제 웹 앱에서도 배지 수를 설정할 수 있습니다. setAppBadge
와 clearAppBadge
는 사용자가 웹 앱을 포어그라운드에서 열어두거나 웹 앱이 백그라운드에서 푸시 이벤트를 처리하는 동안, 즉 배지 수를 표시할 수 있는 권한이 부여되기 전에도 배지 수를 변경할 수 있습니다.
앱 아이콘에 배지를 표시할 수 있는 권한은 iOS 및 iPadOS의 다른 앱과 똑같은 방식으로 부여됩니다. 사용자가 알림을 허용하는 권한을 부여하면 홈 화면의 아이콘에 현재 배지 수가 즉시 표시됩니다. 그런 다음 사용자는 iOS 또는 iPadOS의 다른 앱과 마찬가지로 알림 설정에서 배지에 대한 권한을 구성할 수 있습니다.
iOS 및 iPadOS용 WebKit 16.4 베타 1은 웹 애플리케이션 매니페스트 표준의 ID 멤버에 대한 지원을 추가합니다. 이는 웹 애플리케이션의 고유 식별자 역할을 하는 문자열(URL 형태)로, OS에서 원하는 방식으로 사용하기 위한 것입니다. iOS 및 iPadOS는 여러 기기에서 집중 모드 설정을 동기화할 목적으로 매니페스트 ID를 사용합니다.
iOS는 처음부터 동일한 웹 앱의 다중 설치를 지원해 왔습니다. 하나의 웹 앱을 기기에 두 번 이상 설치할 수 있는 기능은 여러 계정을 지원하고 업무용과 개인용을 구분하는 등의 추가적인 유연성을 제공하는 등 유용할 수 있다고 생각합니다.
홈 화면에 웹 앱을 추가할 때 사용자에게 앱 이름을 변경할 기회가 주어집니다. iOS 및 iPadOS 16.4 베타 1에서는 이 이름을 매니페스트 ID와 결합하여 웹 앱을 고유하게 식별할 수 있습니다. 이렇게 하면 사용자가 하나의 디바이스에 여러 개의 웹 앱 사본을 설치하고 각 사본에 서로 다른 ID를 부여할 수 있습니다. 예를 들어, 'Shiny(개인용)'의 알림은 집중 모드에서 무음으로 설정하고 'Shiny(업무용)'의 알림은 허용할 수 있습니다. 사용자가 여러 장치에서 즐겨 찾는 웹사이트에 동일한 이름을 지정하면 한 장치의 집중 모드 설정이 동기화되어 다른 장치에도 적용됩니다.
iOS 및 iPadOS 16.4 베타 1에서는 이제 타사 브라우저에서도 공유 메뉴에서 웹사이트 및 웹 앱을 홈 화면에 추가할 수 있는 기능을 사용자에게 제공할 수 있습니다.
iOS 및 iPadOS의 애플리케이션은 activityItems
배열이 있는 UIActivityViewController
를 생성하여 공유 메뉴를 표시합니다. 공유 메뉴에 '홈 화면에 추가'가 포함되려면 다음 조건을 만족해야 합니다.
activityItems
배열에 WKWebView가 포함되어 있어야 합니다.위에서 설명한 대로 사용자가 홈 화면에 추가한 후 display
멤버를 standalone
또는 fullscreen
으로 설정하는 매니페스트 파일이 있는 모든 웹사이트는 사용자가 해당 아이콘을 탭 하면 웹 앱으로 열립니다. 이는 웹사이트를 홈 화면에 추가한 브라우저와 관계없이 마찬가지입니다.
웹 앱 동작을 요청하도록 구성된 매니페스트 파일이 없는 경우(그리고 사이트를 웹 앱 가능으로 표시하는 meta
태그가 없는 경우) 해당 웹사이트는 홈 화면 북마크로 저장됩니다. iOS 및 iPadOS 16.4 베타 1부터 홈 화면 북마크는 사용자의 현재 기본 브라우저에서 열립니다.
웹 개발자는 일반적으로 브라우저의 인터페이스 전체에 웹사이트를 나타내는 아이콘을 제공합니다. 홈 화면의 아이콘이 제공되지 않는 경우 이전에는 iOS 및 iPadOS에서 사이트의 스크린샷으로 아이콘을 만들었습니다. 이제 iOS 및 iPadOS 16.4 베타 1에서는 사이트 이름의 첫 글자와 사이트의 색상을 사용하여 모노그램 아이콘을 생성하고 표시합니다.
웹사이트 또는 웹 앱에 사용할 아이콘을 제공하려면 매니페스트 파일에 아이콘을 나열하면 되는데, 이는 iOS 및 iPadOS 15.4부터 지원된 기능입니다. 또는 오랫동안 지원되어 온 기법인 HTML 문서 head
에 apple-touch-icons
을 나열하는 방법을 사용할 수 있습니다. (두 가지 방법을 모두 사용하는 경우 apple-touch-icon
이 매니페스트에 선언된 아이콘보다 우선합니다.)
웹 푸시, 배지 API, 매니페스트 ID 외에도 iOS 및 iPadOS 16.4 베타 1용 Webkit의 다른 많은 새로운 기능은 홈 화면 웹 앱에 중점을 둔 웹 앱 개발자에게 특히 흥미로울 것입니다. 여기에는 다음 사항들이 포함됩니다.
전체 기능 목록은 사파리 16.4 베타 1의 릴리즈 정보를 참조하세요.
원문: https://adlrocha.substack.com/p/adlrocha-what-if-we-had-local-first
목요일에 진행되는 첫 번째 게시글에서는 여러분과 함께 "만약에" 연습을 해보고자 합니다. 이 "만약에"라는 기법은 Spotify("음악 라이브러리를 소유할 필요가 없다면?")나 Uber("모든 자동차가 잠재적으로 택시가 될 수 있다면?") 같은 회사들이 현재 사업 모델에 도달하기 위해 사용했던 기법이라고 합니다.
저희도 한 번 스스로에게 비슷한 질문을 해보죠. "만약 인터넷이 오프라인 우선이라면? 그리고 로컬 우선 소프트웨어가 오프라인 SaaS 모델로 가는 길을 열어준다면 어떨까요?" 실제로 이 논문("로컬 우선 소프트웨어: 클라우드임에도 불구하고 데이터를 소유하는 방법")의 저자들은 이 논문에서 이와 똑같은 질문을 제기했으며, 오늘 우리가 다루고자 하는 질문도 같습니다. 오프라인 우선 인터넷은 어떤 모습일까요?
"요즘 온라인에서 얼마나 쉽게 협업하는지를 보면 놀랍습니다. 구글 문서 도구를 사용해 문서, 스프레드시트, 프레젠테이션을 공동 작업하고, 피그마에서 사용자 인터페이스 디자인을 함께 작업합니다. 또한 슬랙을 사용하여 동료와 소통하고, 트렐로에서 작업을 추적하는 등 다양한 서비스를 이용합니다. 메모를 작성하고, 프로젝트나 이벤트를 계획하고, 연락처를 기억하는 등 다양한 업무 용도로 이러한 서비스와 기타 여러 온라인 서비스에 의존하고 있습니다."
클라우드 앱이 우리의 삶을 훨씬 더 편리하게 만들었다는 데 모두 동의합니다. 오늘날 우리가 사용하는 이러한 실시간 협업 클라우드 앱이 없었다면 효율적인 원격 근무는 불가능했을 것입니다. 그럼에도 불구하고 이러한 모든 애플리케이션은 여전히 몇 가지 불편함과 위협을 안고 있습니다. 몇 가지 예를 들면, 이러한 서비스에서 생성한 데이터의 소유자는 사용자가 아닙니다. 이러한 서비스를 제공하는 회사가 파산해 서버를 중단하면 어떻게 될까요? 게다가 이러한 서비스들은 모두 중앙 집중식 인프라에 의존하기 때문에 공격, 보안 침해, 서비스 중단에 취약합니다.
창의력을 발휘해 "오페라 프리마(역자 주: 문학, 영화 등 예술 분야에서 작가의 첫 작품을 의미)"를 거의 완성한 상태에서 서버에 장애가 발생해 모든 작업이 사라진다고 상상해 보세요. 또는 더 나쁜 경우(더 가능성이 높은 시나리오)로, 집에서 연결이 끊겨서 클라우드 서비스를 탓할 수도 없는 상황이라면 어떻게 될까요? 비행기나 인터넷 연결이 안정적이지 않은 곳에서 이러한 도구로 작업하는 사용자 경험은 말할 것도 없습니다. 실시간 협업은 우리의 삶을 크게 개선해 주었지만, 아마 이보다 더 나아질 수 있을 것입니다.
"요약하자면, 클라우드는 협업을 제공하지만, 구식 앱은 소유권을 제공합니다. 두 가지 장점을 모두 누릴 수는 없을까요? 클라우드 앱이 제공하는 편리한 기기 간 접근 및 실시간 협업, 그리고 '구식' 소프트웨어가 가지는 데이터에 대한 개인 소유권을 모두를요."
이것이 바로 원격 데이터 센터의 서버보다 로컬 스토리지(디바이스 내부)와 로컬 네트워크(가정용 Wi-Fi 등)를 우선적으로 사용하는 "로컬 우선 소프트웨어"의 근거입니다. 이러한 비전을 구축하는 것은 쉽지 않으며, 서버(또는 분산 스토리지와 릴레이. 무슨 말인지 아시겠죠? 😉)는 백업 및 상호 연결 목적으로 여전히 필요할 것입니다.
따라서 "로컬 우선 소프트웨어"의 의미를 평가하기 위해 이 논문에서 저자들은 다음과 같은 7가지 이상을 추구해야 한다고 정의합니다.
로딩 스피너 없이, 바로 작업 가능합니다: 몇 년 전보다 더 강력한 디바이스를 사용하지만 소프트웨어는 점점 더 느려지고 오류가 발생하기 쉽다는 것을 모두 동의할 것입니다. "로컬 우선 소프트웨어"는 인터넷 의존도를 낮추고 로컬 스토리지를 사용하여 현재 소프트웨어보다 더 빨라져야 합니다.
작업이 하나의 기기에 갇히지 않아야 합니다: 이건 어려운 문제입니다. 현재의 클라우드 앱이 모든 기기에서 원활하게 작업할 수 있게 해주는 것과 마찬가지로 "로컬 우선 소프트웨어"도 이를 가능하게 해야 합니다. 더 나아가 다른 사람(및 다른 사람의 기기)과 협업할 수 있어야 하므로 데이터가 내 기기에만 머물러서는 안 됩니다. 이를 실현하기 위해서는 장치 간의 안정적인 동기화 시스템이 필요합니다.
물론 네트워크는 선택 사항입니다: 로컬 우선 애플리케이션은 데이터의 기본 복사본을 각 장치의 로컬 파일 시스템에 저장하기 때문에 사용자는 오프라인 상태에서도 언제든지 이 데이터를 읽고 쓸 수 있습니다. 나중에 네트워크 연결이 가능할 때 다른 장치와 동기화됩니다. 데이터 동기화가 반드시 인터넷을 통해 이루어질 필요는 없습니다: 로컬 우선 앱은 블루투스 또는 로컬 WiFi를 사용하여 주변 장치와 데이터를 동기화할 수도 있습니다. 또한, 원활한 오프라인 지원을 위해서는 소프트웨어가 웹 브라우저의 탭이 아닌 장치에 로컬로 설치된 실행 파일로 실행되는 것이 바람직합니다. 웹 앱이 오프라인에서 작동하도록 설정하는 것은 가능하지만, 사용자가 애플리케이션에 필요한 모든 코드와 데이터가 다운로드되었는지 여부를 알기는 어려울 수 있습니다. 모바일 앱의 경우 앱을 사용하기 전에 전체 앱을 다운로드하여 설치하는 것이 이미 표준입니다.
원활한 협업이 가능해야 합니다: 이 원칙을 논문에 있는 몇 가지 매력적인 이미지로 설명해 보겠습니다. 간단히 말하면, 충돌, 충돌, 그리고 더 많은 충돌입니다. 이런 경험을 해보지 않은 사람이 있을까요?
개인적으로 가장 마음에 드는(그리고 "로컬 우선 애플리케이션"에 포함할 수 있다고 생각하는) 협업 방식은 git 방식입니다. 로컬 버전의 코드에서 작업하고 주기적으로 변경 사항을 저장소에 푸시하여 모든 사람이 사용할 수 있도록 합니다. 현재 이 작업은 개발자가 수동으로 수행하지만 애플리케이션 기본 코드에서 자동화하여 네트워크에 연결할 수 있을 때마다 디바이스가 새로운 변경 사항을 푸시하도록 할 수 있습니다. 물론 이렇게 한다고 해서 충돌이 발생하지 않는 것은 아니지만, 해결할 수 있는 방법을 우리는 이미 알고 있습니다.
데이터를 장기 보관할 수 있어야 합니다: 데이터는 오래 보관되어야 합니다. 로컬 디바이스에 저장되고 다른 디바이스에도 동기화될 수 있으니 로컬 우선 앱이 완벽하다고 할 수 있습니다.
기본적으로 보안 및 개인정보가 보호되어야 합니다: 즉, 내 기기(및 내가 상호작용하는 기기)의 데이터와 채널이 암호화됩니다.
사용자가 최종 소유권 및 통제권을 보유해야 합니다: 많은 경우 사용자가 원하지 않는 책임입니다. 그렇기 때문에 중앙집중식 백업 서버, 분산형 스토리지 등과 같은 폴백 시스템이 존재해야 하며, 디지털 생활에 대한 책임이 부담스러운 사용자는 자신의 소유권을 다른 사람에게 위임할 수 있습니다.
그렇다면 현재 클라우드 애플리케이션들은 이러한 원칙을 얼마나 충족하고 있을까요?
좋지는 않습니다..
"웹 브라우저를 오프라인 친화적으로 만들기 위한 많은 노력(매니페스트, 로컬 스토리지, 서비스 워커, 프로그레시브 웹 앱 등)에도 불구하고 웹 앱의 아키텍처는 여전히 근본적으로 서버 중심적입니다. 대부분의 웹 앱에서 오프라인 지원은 나중에 고려해야 할 사항이며, 따라서 그 결과도 취약합니다. 많은 웹 브라우저에서 사용자가 쿠키를 지우면 로컬 저장소의 모든 데이터도 삭제되는데, 이는 캐시에는 문제가 되지 않지만 브라우저의 로컬 스토리지는 장기적으로 중요한 데이터를 저장하는 데 적합하지 않습니다."
저의 글 "웹 앱을 오프라인에서 작동하게 만드는 방법"을 기억하시나요? 안타깝게도 제가 이 글에서 공유한 "오프라인" 설계는 로컬 우선 애플리케이션을 구축하기에는 여전히 너무 "서버 중심적"입니다. 상황을 어느정도 개선할 수는 있지만, 우리의 목표를 달성하고 7가지 원칙을 모두 충족하기에는 충분하지 않습니다.
그런 의미에서 CouchDB/PouchDB와 같이 서로 다른 장치 간에 오프라인 동기화 스토리지를 구현하는 데 철학적으로 이미 도움이 되는 기술이 있습니다.
"CouchDB는 다중 마스터 복제 방식을 개척한 것으로 유명한 데이터베이스입니다. 여러 대의 컴퓨터가 각각 데이터베이스의 완전한 복사본을 가지고 있고, 각 복제본이 독립적으로 데이터를 변경할 수 있으며, 모든 복제본 쌍이 서로 동기화하여 최신 변경 사항을 교환할 수 있습니다. CouchDB는 서버에서 사용하도록 설계되었으며, Cloudant는 호스팅 버전을 제공하고, PouchDB와 Hoodie는 동일한 동기화 프로토콜을 사용하지만 최종 사용자 장치에서 실행되도록 설계된 형제 프로젝트입니다."
하지만, 이것만으로 우리의 모든 원칙을 충족시키기에 충분하지 않습니다. CouchDB에서는 애플리케이션 코드를 통해 충돌을 명시적으로 해결해야 합니다.(특정 시나리오에서는 쉬운 일이 아닙니다.)
그렇다면 현재 우리 고민 지점에 필요한 협업 및 충돌 해결을 제공할 수 있는 기술이 있을까요? 다행히도 있습니다. 충돌 없는 복제 데이터 유형(일명 CRDT) 을 소개해 드리겠습니다.
CRDT는 해시 맵이나 리스트 같은 범용 데이터 구조이지만, 처음부터 다중 사용자를 가정했다는 특별한 특징이 있습니다.
위의 이미지로 CRDT를 설명해 보겠습니다. 데이터 저장소가 동일한 초기 상태인 두 개의 디바이스가 있습니다. 각각의 디바이스는 데이터에 대해 독립적인 업데이트를 수행합니다. CRDT 구조는 이러한 변경 사항을 업데이트 작업으로 등록하여 두 장치 간에 네트워크 통신이 가능하면 해당 업데이트를 교환하고 병합하여 데이터 구조의 공통 상태에 도달할 수 있도록 합니다. CRDT가 자동으로 해결할 수 없는 유일한 변경 유형은 여러 사용자가 동시에 동일한 객체의 동일한 속성을 업데이트하는 경우이며, 이 경우 CRDT는 충돌하는 값을 추적하고 애플리케이션이나 사용자가 해결하도록 남겨 둡니다. 따라서 결국 충돌을 피하는 방법은 이러한 다중 사용자 수정을 최대한 방지하도록 CRDT 데이터 구조를 현명하게 설계하는 것입니다.
"CRDT는 텍스트 파일보다 더 다양한 데이터 유형에서 작동한다는 점을 제외하면 Git과 같은 버전 관리 시스템과 어느 정도 유사합니다. CRDT는 모든 통신 채널 (예: 서버, P2P 연결, 로컬 장치 간 블루투스, USB 스틱 등)을 통해 상태를 동기화할 수 있습니다. CRDT가 추적하는 변경 사항은 한 번의 키 입력만큼 작을 수 있으므로 구글 문서 도구 스타일의 실시간 협업이 가능합니다. 하지만 더 큰 변경 집합을 수집하여 Git의 풀 리퀘스트처럼 공동 작업자에게 일괄적으로 보낼 수도 있습니다. 데이터 구조가 범용이기 때문에 CRDT의 저장, 통신 및 관리를 위한 범용 도구를 개발할 수 있어 모든 앱에서 이러한 기능을 다시 구현할 필요가 없습니다."
CRDT는 제가 열광하는 분야이며, 이미 Atom 에디터의 Teletype(P2P 코드 협업용)과 같이 그 활용을 탐구하는 애플리케이션이 있습니다. 논문 저자 중 한 명이 만든 이 동영상을 통해 CRDT에 대해 알아보는 것을 적극 추천합니다. 조만간 CRDT에 대한 뉴스레터 발행을 기대해 주세요.
이 논문에서는 협업 칸반 보드 또는 협업 드로잉 앱과 같은 "로컬 우선 애플리케이션" 구현에 대한 몇 가지 PoC를 공유합니다.
이러한 앱의 구현과 사용을 통해 다음과 같은 결론을 도출했습니다.
- CRDT 기술은 작동합니다.
- 오프라인 작업에 대한 사용자 경험은 훌륭합니다.
- 함수형 반응형 프로그래밍과 결합하면 개발자 경험을 향상할 수 있습니다.
- 충돌은 우려했던 것만큼 큰 문제가 되지 않습니다.
- 문서 히스토리를 시각화하는 것이 중요합니다.
- URL은 공유를 위한 좋은 메커니즘입니다.
- P2P 시스템은 완전한 "온라인"이나 "오프라인"이 아니며, 그 안에서 데이터가 어떻게 이동하는지 추론하기 어려울 수 있습니다.
- CRDT는 대량의 변경 이력을 축적하여 성능 문제를 일으킵니다.
- 클라우드 서버는 여전히 검색, 백업, 버스트 컴퓨팅을 위한 최적의 장소입니다.
- 네트워크 통신은 여전히 해결되지 않은 문제로 남아 있습니다.
CRDT에는 P2P 네트워킹 계층이 필요하지 않으며, 통신을 위해 서버를 사용하는 것도 괜찮습니다. 하지만 로컬 우선 소프트웨어의 장기 목표를 완전히 실현하려면 애플리케이션이 공급업체가 관리하는 모든 백엔드 서비스보다 오래 지속되기를 원하므로 분산형 솔루션이 논리적 최종 목표입니다.
프로토타입에 P2P 기술을 사용한 것은 엇갈린 결과를 얻었습니다. 한편으로는 이러한 기술들이 아직 프로덕션에 적용할 수 있는 단계에 이르지 못했습니다. 특히 또 다른 흥미로운 연구 및 탐색 분야인 NAT 통과는 사용자가 현재 연결되어 있는 특정 라우터나 네트워크 토폴로지에 따라 불안정할 수 있습니다. 하지만 P2P 프로토콜과 분산형 웹 커뮤니티가 제시하는 약속은 상당합니다. 인터넷에 접속할 수 없는 컴퓨터 간의 실시간 협업은 중앙화된 API에 의존하게 된 세상에서 마법처럼 느껴집니다.
이제 몇 주 전에 제가 발행한 글 새로운 인터넷에 대한 저의 비전을 바탕으로 "만약에"라는 상상을 극단적으로 확장해 보겠습니다. "로컬 우선 애플리케이션"은 UX, 보안 및 개인 정보 보호 측면에서 우리가 마땅히 누려야 할 인터넷으로의 도약처럼 보입니다. 논문 저자에 따르면 네트워크 통신은 여전히 해결되지 않은 문제로 남아있습니다. 하지만.. 해결이 될 수도 있지 않을까요? web3 분야에서는 "로컬 우선 애플리케이션"이 제기하는 문제에 대한 많은 해결책을 모색하고 있습니다(그리고 그중 상당수는 이미 해결되었을 수도 있습니다).
최근에 본 트윗을 인용하며 마치겠습니다. "탈중앙화된 웹의 대부분은 '전혀' 말이 되지 않으며, 말이 되는 극히 일부분은 매우 소중하고 훌륭합니다." 우리가 만들고 있는 이 소중하고 멋진 소프트웨어로 새로운 인터넷으로 가는 길을 닦아봅시다.
Vue.js 제작자 Evan You가 Vue 3가 Vue 2와 무엇이 다른지, 특히 가상 DOM의 사용이 어떻게 발전했는지 설명합니다.
2년 전 자바스크립트 프레임워크인 Vue.js에 관한 다큐멘터리에서 이 프레임워크는 자바스크립트 생태계 주요 프레임워크인 페이스북의 React와 구글의 Angular에 비해 일종의 인디 대안으로 묘사되었습니다. "덜 기업적이고 [...] 더 서민적인 느낌입니다."라고 한 강연자가 설명했습니다.
가장 트렌디한 자바스크립트 프레임워크인 React와 비교했을 때 가장 눈에 띄는 차이점은 웹 표준 옹호자들이 Vue를 지지한다는 점입니다. 그 이유에 대한 단서는 Vue의 공식 문서에서 찾을 수 있는데, 문서에서는 "React에서는 모든 것이 자바스크립트일 뿐입니다. HTML 구조는 JSX를 통해 표현될 뿐만 아니라 최근에는 CSS 관리도 자바스크립트 안에 넣는 추세입니다."라고 설명합니다. 반면에 Vue는 "고전적인 웹 기술을 수용하고 그 위에 구축한다"고 말합니다. (참고: 해당 인용문은 Vue 2 문서에서 발췌한 것으로, 최신 Vue 3 문서에서는 이 비교를 찾을 수 없었습니다.)
최근 몇 년 동안 React의 자바스크립트 중심 접근 방식과 이를 사용하는 프레임워크(예: Next.js)에 대한 반발이 많았고, Vue, Svelte, Lit와 같은 프레임워크가 제공하는 "고전적인 웹 기술" 위에 구축하려는 움직임이 있었습니다.
이러한 맥락에서 이번 달(2023년 2월 16일 기준) 암스테르담에서 열린 JSworld 컨퍼런스에서 오프라인 및 온라인으로 진행된 연례 "State of the Vuenion"(역자 주: Evan You가 매년 Vue 생태계에 대한 개요 및 새로운 업데이트, 개발 현황을 발표하는 컨퍼런스) 발표에서 Vue 제작자 Evan You가 어떤 말을 했는지 궁금했습니다.
Evan You는 팬데믹으로 인해 3년 전을 마지막으로 JSworld에 직접 참석하지 못했다는 점을 언급하며 기조연설을 시작했습니다. 그래서 그는 3년 전에는 Vue 생태계에 존재하지 않았거나 아직 안정적이지 않았던 것들을 나열했습니다: Vue 3는 "안정적이지 않았고", Vite(빌드 도구), Volar("임베디드 프로그래밍 언어 도구 구축을 위한 프레임워크"), Pinia("Vue 생태계를 위한 상태 관리 라이브러리")가 존재하지 않았습니다.
그는 "우리는 본질적으로 Vite를 중심으로 완전히 새로운 생태계를 만들었습니다."라고 말하며, "이와 함께 Vue 생태계 내에서뿐만 아니라 다른 모든 프레임워크와도 연결되는 새롭고 흥미로운 모든 것들을 그 위에 구축하였습니다."라고 덧붙였습니다.
Vue 생태계
Evan You는 Vue 애플리케이션을 구축하기 위한 기본 프레임워크인 Nuxt를 필두로 현재 Vue 도구 생태계에 찬사를 보냈습니다. 그러나 계속해서 Vue 3를 안정적으로 만드는 것이 2023년의 주된 관심사라고 말했습니다. 1년 전인 지난 2월에 Vue 3가 새로운 기본 버전이 되었지만, "레거시 프로젝트"라고 불리는 프로젝트에서는 여전히 Vue 2를 사용하고 있습니다. 그는 Vue 3 채택의 대부분이 "신규 프로젝트"에서 이루어졌다고 언급했습니다.
Evan You는 "우리는 아직 Vue 2에서 Vue 3로 전환하는 단계에 있습니다."라고 말하며 많은 대형 프로젝트가 여전히 Vue 2를 사용 중이거나 Vue 3로 전환할 계획을 세우고 있다고 지적했습니다.
올해 Vue 3에서 계획된 다양한 관리상의 변경에 대해 논의한 후, Evan You는 Vue 2와 비교하여 Vue 3가 "렌더링"하는 방식의 차이점에 대해 설명하는 시간을 가졌습니다. "렌더링 전략은 시간이 지남에 따라 변화하고 있습니다."라고 말하며 특히 가상 DOM(VDOM)을 처리하는 방식에 대해 언급했습니다.
그 얘기를 하기 전에 Vue 3를 이해하는 데 도움이 될 만한 VDOM에 대한 간략한 소개를 하겠습니다. 이 날 JSworld의 다른 세션에서 Marc Backes가 "가상 DOM을 만들어 봅시다."라는 제목의 세션을 진행했습니다. 다음 세 개의 슬라이드는 VDOM이 무엇이며 Vue와 같은 프레임워크 내에서 그 목적이 무엇인지 잘 요약해 줍니다. (VDOM은 React에 의해 대중화되었지만, Vue를 포함한 다른 많은 프레임워크에서도 이 개념을 채택하고 있습니다).
가상 DOM이란 무엇인가
왜 가상 DOM을 사용하는가
가상 DOM을 만들어 보기
Backes는 또한 Vue에서 사용하는 렌더링 파이프라인을 다음과 같이 시각적으로 표현했습니다(Vue 문서에 있는 동일한 다이어그램을 다양한 색깔로 표현한 버전입니다).
Vue 렌더링 파이프라인
다시 Evan You의 발표 내용으로 돌아가보겠습니다. 그는 "Vue 2에서는 순수 가상 DOM을 사용했는데, 이는 [...] React가 사용하는 것과 유사하며 컴파일 타임 최적화를 수행하지 않는다는 것을 의미합니다. 전혀 최적화하지 않는 건 아니지만 거의 하지 않습니다."라고 말했습니다.
Vue 2 렌더링
"따라서 컴포넌트 트리 또는 앱 수준에서는 각 컴포넌트가 자체 종속성을 추적하도록 하여 세분화된 업데이트를 수행할 수 있습니다."라고 그는 Vue 2에 관해 설명합니다.
단점은 가상 DOM 오버헤드인데, 그는 이를 "가상 DOM 노드를 다시 생성한 다음 해당 트리를 통해 차이를 확인하는 데 드는 비용"이라고 설명했습니다. 그는 "Vue 2는 이 오버헤드를 지속적으로 지불하고 있습니다."라고 덧붙였습니다.
이 문제를 해결하기 위해 Vue 3에서는 다른 접근 방식을 취했습니다. 그는 "컴파일러 정보에 기반한 가상 DOM"이라고 설명했는데, 이는 "컴파일 타임에 훨씬 더 많은 최적화를 수행"한다는 의미입니다.
Vue 3 렌더링
VDOM의 복잡성은 차치하고서라도, Vue의 인기 상승에는 "단일 파일 컴포넌트(SFC)" 접근 방식이 큰 부분을 차지합니다. Vue는 SFC를 "Vue 컴포넌트의 템플릿, 로직, 및 스타일링을 단일 파일에 캡슐화할 수 있는 특수 파일 형식"으로 정의합니다. 다른 곳에서 Vue는 SFC를 "HTML과 유사한 파일 형식"이라고 부릅니다.
Vue 핵심 팀원인 Damian Dulisz와의 2017년 인터뷰에서 그는 SFC 형식을 통해 "코드를 이해하고 추론하기가 훨씬 더 쉬워졌다"라고 말했습니다.
The New Stack의 엔지니어링 디렉터인 Aaron Ban은 SFC 접근 방식으로 인해 Vue의 팬이 되었습니다. 그는 SFC 접근 방식이 제공하는 "깔끔한 조직"을 좋아하며, 또한 SFC 접근 방식이 모듈화의 훌륭한 예라고 생각합니다. "사실 SFC를 올바르게 수행하는 데 필요한 엄격한 커트라인을 스스로에게 강요하기는 어려운 훈련입니다."라고 그는 말했습니다. 하지만 그는 이것이 지난 10여 년 동안 많은 개발자가 배워온 '빨리빨리'라는 사고방식에 대한 해독제라고 생각합니다. 그는 이러한 사고방식은 개발자들이 "적절한 경계선을 그리는 데 신경 쓰지 않고 '나중에 고치면 된다'는 생각으로 '일단 작동만 시키면 된다'는 식의 나쁜 습관을 조장해 왔다"라고 말합니다.
Ban은 단일 파일 컴포넌트를 제공하는 다른 두 가지 프레임워크인 Svelte와 Lit의 디자인도 마음에 들어 합니다.
SFC가 개발자들에게 보편적으로 사랑받는 것은 아닙니다. Vue 문서에서도 이를 인정하고 있습니다. "전통적인 웹 개발 배경을 가진 일부 사용자는 SFC가 HTML/CSS/JS가 분리해야 할 서로 다른 관심사를 한 곳에 섞어 놓았다는 우려를 할 수 있습니다!"
이러한 반대 의견에 대해 Vue는 SFC 접근 방식이 "실제로 컴포넌트를 더 응집력 있고 유지 관리하기 쉽게 만든다"라고 주장합니다.
Evan You의 JSworld 기조연설에 따르면 2023년에 Vue 개발자에게 큰 변화가 예상되지는 않을 것입니다. Vue 2에서 Vue 3로 업그레이드하도록 개발자를 계속 유도하는 것과 함께, 계속해서 확장되는 생태계에 대한 추가적인 개선이 이어질 것입니다.
Vue는 저희와 같은 기술 전문 매체에서는 그다지 주목 받지 못할 수도 있지만, 매년 이렇게 웹 표준을 준수하는 자바스크립트 프레임워크는 살펴 볼 가치가 있습니다. 우리는 확실히 Vue의 계속적인 발전을 즐기고 있습니다.
Composition API 제안에 반대하는 유저의 글에 대한 Evan You의 답변 번역
저는 당신의 의견을 존중하므로 다음 내용을 어느 것도 개인적인 것으로 받아들이지 마세요.
결국 정말 중요한 문제들은 전혀 해결되지 않기때문에 이 급진적인 변화는 정당화할 수 없습니다. 본질적으로 이 제안은 그저 겉만 번지르르한 새로운 것을 쫓는 것과 같습니다.
저는 이 말에 동의할 수 없습니다. Logic Composition은 아마도 프로젝트 확장 측면에서 가장 중요한 문제 중 하나일 것입니다. 다른 스레드에서 제가 썼던 말을 다시 인용합니다:
Vue는 작게 시작했지만 오늘날에는 다양한 수준의 복잡성과 비즈니스 영역을 포함하는 매우 광범위한 프로젝트에서 사용되고 있습니다. 다양한 유형의 프로젝트를 처리하는 개발자는 다양한 요구 사항에 직면하게 되며, 일부는 object-based syntax API를 사용하여 쉽게 처리할 수 있지만 일부는 그렇지 않습니다. 주요 예시들로
(1) 에 해당하는 상황에서는 로직들이 강제로 각 옵션 유형들에 나눠져 할당됩니다. 예를 들어, 하나의 data fetching 작업이 prop
, data
, computed property
, mounted hook
그리고 watcher
까지 필요할 수도 있습니다. 즉, 컴포넌트에서 하나의 data fetching 과정을 이해하려고 할 때 옵션 목록에서 계속 위아래로 점프하게 됩니다. 동시에 속성을 훑어볼 때 속성이 어떤 유형 인지 알고 있지만 처리해야하는 로직 을 말하기는 상당히 어렵습니다. 컴포넌트에 더 많은 로직들이 추가되면 상황이 악화됩니다. 이에 비해 Composition API를 사용하면 한 data fetching을 위한 모든 관련 로직을 그룹화할 수 있으며 더 중요한 것은 별도의 함수 또는 별도의 파일로 깔끔하게 추출할 수 있다는 점입니다.
이 문제는 프로젝트의 파일 구성으로 비유할 수 있습니다. 우리 중 많은 사람들이 파일 유형별로 파일을 구성하는 것(예: 모든 것을 html
, js
및 css
폴더로 분할)이 확장성이 없다는 데 동의합니다. 한가지 기능과 관련된 코드들이 잘못 이해한 "관심사 분리(seperation of concerns)"를 위해 세 개의 폴더로 강제로 분할됩니다. 여기서 핵심은 "관심사"가 파일 형식으로 정의되지 않는다는 것입니다. 대신 우리 대부분은 기능이나 책임(responsibility)별로 파일을 구성합니다. 이것이 바로 사람들이 Vue 단일 파일 구성 요소(SFC)를 좋아하는 이유입니다. SFC는 기능별로 코드를 구성하는 방법입니다. 아이러니하게도 SFC가 처음 도입되었을 때 많은 사람들이 SFC가 관심사 분리에 위배된다고 생각하여 반대했지만 나중에 SFC가 실제로 관심사를 분리하는 더 합리적인 방법이라는 것을 인정했습니다.
(2)는 RFC의 ‘동기 (Motivation)’ 섹션에서 중요하게 설명했는데, mixins/HOCs/scoped slots이 할 수 있는 것들을 단점없이 똑같이 해낼 수 있다는 것을 보여줍니다.
React Hook을 통해 우리는 Hook의 특성 중 일부가 위에서 언급한 문제들을 해결하는 데 도움이 될 수 있음을 발견했습니다. 이것이 우리가 이 제안(Composition API)을 하게 된 근본적인 이유입니다. 그야말로 "새로운 것"이지만, 우리는 그것이 "새롭다"는 이유가 아니라 객관적으로 존재하는 문제에 대한 해결책을 제시하기 때문에 새로운 것을 채택하고 있습니다. 장기적으로 이 새로운 API의 가능성이 위에서 언급한 문제들을 다루는 개발자들의 시간을 절약해 막대한 이익을 가져다 줄 것입니다.
Type Safety도 중요한 고려 사항입니다. 다시 말하지만, 이 사항 또한 많은 사용자들이 간절히 원했지만 TypeScript를 사용하지 않는 사람들에게는 가치가 없어 보일 수 있습니다. 이해할 수 있습니다. 그러나 해결되는 문제가 당신에게 영향을 미치지 않기 때문에 어떤 문제도 해결되지 않는다고 주장하는 것은 약간 이기적인 것이라고 생각합니다.
모든 종류의 프로젝트에 급진적인 API 변경 사항을 도입하는 것은 급격한 변화(Breaking Changes)이며, 이전 API와의 역호환성을 관대하게 제공해도 이 문제가 해결되지 않습니다.
"Breaking"은 ‘사용자가 강제로 코드를 변경해야함’으로 정의됩니다. 사용자는 기존 코드를 변경할 필요가 없으므로 Breaking이 아닙니다. 이 부분에 대해서는 더 이상 반박할 여지가 없다고 생각합니다.
이전 버전과의 호환성으로도 충분하지 않다면, 본질적으로 프로젝트가 급진적인 새로운 아이디어를 도입해서는 안 된다고 말하는 것입니다. 저는 이것이 프로젝트 정책 수준의 논쟁이라고 생각합니다. 만약 제가 투표를 한다면, 저는 단호하게 반대할 것입니다. 우리는 사용자의 최선의 이익을 염두에 두고 최선을 다할 것이지만 프로젝트는 발전해야하고 발전할 것입니다.
이런 식으로 일을 하는 것은 불가사의하고 비잔틴이나 미로 같은 "스파게티 코드"로 이어질 가능성이 더 큽니다. Vue의 가장 큰 장점 중 하나는 단순함과 접근성입니다. Vue 주요 [변덕스럽고 종잡을 수 없는 API 변경과 아키텍처 문제로 인해 다른 많은 JavaScript 관련 약속이 그러하듯이 Vue에 대한 주요 조직의 약속은 손에서 증발하기보다는 유통 기한과 내구성을 가질 만큼 충분히 정적입니다.]
반대로, 이 제안의 동기는 장기적으로 Vue 프로젝트의 유지보수성을 향상시키는 것이었습니다.
JavaScript 프로젝트를 살펴보면 모든 코드는 한 시작지점 파일에서 시작하며, 본질적으로 암시적으로 "main" 함수가 호출되면서 시작합니다. 단일 함수 시작점이 스파게티 코드로 이어지는 것이라면 모든 JavaScript 프로젝트는 스파게티 코드여야 합니다. 이는 분명히 사실이 아닙니다. 왜냐구요? 개발자로서 우리는 코드를 모듈 또는 더 작은 기능으로 분할하여 구성하는 방법을 배웠기 때문입니다.
함수 기반 API 디자인의 핵심 특징은 setup()
내 코드를 이해한다는 것이 관용적인 JavaScript 코드를 이해하는 것과 다르지 않으며, 일반 JavaScript 코드를 구성하는 데 사용할 수 있는 모든 기술을 사용해 setup()
함수를 구성할 수 있다는 것입니다. 팀에서 일반적인 JavaScript 코드에 사용하는 모든 지식/스타일 가이드/코드 검토 프로세스를 Vue setup()
함수의 코드에 적용할 수 있습니다.
저는 새로운 API가 이론적으로 코드 품질에 대한 임계값이 더 낮을 수 있음에 동의합니다. 그러나 언급한 바와 같이 Vue가 아닌 코드베이스에서 스파게티 코드를 방지하기 위해 이미 수행하고 있는 모든 작업들을 적용할 수 있으므로 완화될 수 있습니다. 반면에 새로운 API로 작성된 코드는 코드 품질의 상한선도 상당히 높습니다. 새로운 API로 작성된 모든 코드는 옵션 기반 API보다 훨씬 더 높은 품질의 코드로 리팩토링될 수 있지만 옵션 기반 API를 사용하면 믹스인에 의존해야하고 그 단점들도 처리해야 합니다.
저는 또한 이 RFC가 유지 보수성을 위해 단순성을 거래하는 것에 관한 것이 아니라는 점을 지적하고 싶습니다. 알아야할 것은 지금 몇 년 동안 사용했을 수도 있는 API와 처음 본 API간의 느낌을 비교하고 있다는 사실입니다. 기본적으로 아래가 컴포넌트에 관한 관점의 전환입니다.
많은 사용자가 "단순함을 잃는다"고 말할 때 한탄하는 것은 사실 옵션 유형별로 컴포넌트를 살필 수 있는 능력을 잃는 것에 대해 말하는 것입니다. 그러나 새 API를 사용하면 컴포넌트를 옵션 유형별로 살필 수 있는 능력을 제공하는 분석기를 구현하는 것이 매우 간단합니다. 즉, 새 API에서는 두 가지 관점 모두에서 컴포넌트를 살필 수 있지만 옵션 기반 API를 사용하면 하나로 제한됩니다 (옵션 간에 분할할 때 논리적 주제에 대한 의도가 손실되기 때문에).
Vue를 좋게 만드는 것들을 버릴 가치가 없습니다.
"아무것도 버리지 않는다"는 말을 되풀이하는 것도 지겹습니다. 그러나 "Vue를 좋게 만드는 것"이 실제로 무엇인지 정의하려고 합니다. 이 RFC에 반대하는 많은 사용자는 그것을 object-based syntax로 정의하고 object-base syntax를 제거하면 Vue를 Vue스럽게 만드는 모든 것을 제거하는 것처럼 보인다고 말합니다. 그러나 그대로 남아 있는 것을 살펴보겠습니다.
Vue의 object-based syntax는 처음부터 존재해왔습니다. 위의 많은 것들은 나중에 추가되었으며 각각 Vue의 성장에 기여했습니다. object-based syntax이 당신에게 중요한 전부라고 생각하신다면 한 걸음 물러서서 Vue를 실제로 만드는 것이 무엇인지 다시 생각해 보시기 바랍니다. 결국 이 RFC는 보이는 것처럼 급진적인 변화가 아닙니다.
중단
컴퓨터 과학의 핵심 아이디어에서 시작하여 알고리즘과 신경망으로 진행합니다.
사서는 책을 저자, 제목, 주제별로 찾을 수 있는 방법이 필요했습니다. 하지만 책장에서 책은 한 가지 방법으로만 정렬할 수 있습니다. 사서들은 이 문제를 해결하기 위해 수세기 전에 한 방법을 만들어 냈습니다. 바로 카드 카탈로그를 이용하는 것입니다.
카드 카탈로그의 색인 카드는 해당 책을 빠르게 찾을 수 있는 번호를 포함해 책에 대한 모든 주요 정보를 포함하고 있습니다. 만약 카드를 저자별로 묶어놓는다면 우리가 톨스토이의 책을 찾으려고 할 때 빠르게 찾을 수 있습니다. 저자에 따른 정렬만이 아니라 제목, 출판일 등등 도서관을 이용객에게 중요한 정보별로 어떤 것이든 이용할 수 있습니다.
일반적으로 컴퓨터를 이용해 아주 많은 양의 데이터를 검색해야할 때, 아래 두 가지 방법 중 하나를 수행하게 됩니다.
또 다른 문제
만약 책장에 책이 꽉 차있는데, 중간에 다른 책을 추가해야한다면? 많은 책을 움직여야 합니다.
이 문제를 해결하기 위해 사서들은 책장에 추가적인 공간을 남겨두는 방식을 사용합니다.
하지면 여전히 문제는 존재합니다. 남겨둔 공간이 낭비되는 것이죠.
공간을 절약할 수 있는 또 다른 현대적인 방법이 있습니다.
책을 아무곳에나 두는 겁니다. 컴퓨터 시스템만이 책의 장소를 기억하는 거죠.
이 것이 우리 시스템의 주요 문제점입니다. 이름을 알기 위해서는 이름을 알아야합니다.
Beemesh 시스템은 모든 디바이스가 생산될 때부터 central authority의 주소를 알도록 했습니다. 컴퓨터가 제일 처음 Beemesh에 연결될 때 이미 TOWN-HALL
의 주소를 알고 있게 되는 것이죠.
사실, 이건 인터넷이 작동하는 방식과 매우 흡사합니다. 우리의 컴퓨터는 인터넷에 연결되기 전부터 central naming authority의 주소를 알고 있습니다.
시청의 컴퓨터를 작동시키는 비용은 1시간에 2센트입니다. 이 계산에 따르면 Sophia의 느린 Python 프로그램을 900번 돌리는 비용은 35센트입니다.
Sophia의 시급은 50달러입니다. 그리고 Sophia가 더 빠른 알고리즘으로 프로그램을 개선하는데는 2시간이 걸립니다.
프로그램 개선이 더 저렴한 방법이 되기 위해서는 프로그램을 몇번이나 돌려야할까요?
Jing 시장의 요청을 수행하기 위한 3가지 다른 방법을 알아봤습니다. 하지만 Jing 시장의 입장에서는 이 셋이 모두 같은 Interface를 가지고 있었습니다. 그녀는 항상 Records Office를 통해 Fire Department 메모들을 요청했을 뿐이었습니다.
Jing 시장에게서 감춰진 영역이 있어서 신경쓰이게 하지 않고 다른 방법을 사용하도록 바꿀 수 있었습니다. 인터페이스에서 중요한 부분 중 하나입니다.
Selection Sort는 정렬되지 않은 영역을 반복적으로 스캔해 swap을 최소화 합니다.
Insertion Sort는 필요하지 않은 스캔을 줄이고 대신 swap 횟수를 늘립니다
3의 법칙
- 처음에는 그냥 한다.
- 비슷한 일을 두 번째로 하게 되면 일단 계속한다.
- 비슷한 일을 세 번째 하게 되면 리팩터링한다.
보기 싫은 코드를 발견하면 리팩터링하자. 그런데 잘 작성된 코드 역시 수많은 리팩터링을 거쳐야한다.
무언가 수정하려 할 때는 먼저 수정하기 쉽게 정돈하고(단, 만만치 않을 수 있다)
그런 다음 쉽게 수정하자. - 켄트 벡
리팩터링이라는 용어에 대해 정확히 이해하지 못하고 있었던 것 같다.
누군가 "리팩터링하다가 코드가 깨져서 며칠이나 고생했다"라고 한다면, 십중팔구 리팩터링한 것이 아니다. 나는 코드베이스를 정리하거나 구조를 바꾸는 모든 작업을 재구성(restructuring)이라는 포괄적인 용어로 표현하고, 리팩터링은 재구성 중 특수한 한 형태로 본다.
실제 리팩터링을 활용해볼 수 있지 않을까?
리팩터링한다고 말하지 말았어야 했던 것 같다.
언제 리팩터링 해야할까 소챕터의 내용은 여러번 더 읽어봐야겠다.
지속적인 통합에 대한 다른 사람들의 의견이 궁금하다
레거시 코드를 부분적으로 리팩터링한다면?
현재까지 파악한 요구사항만을 해결하는 소프트웨어를 구축하는 것은 아키텍처가 아니라 코드레벨에서도 좋은 것 같다.
성능에 대한 신비로운 사실. 전체 코드 중 극히 일부에서 대부분의 시간을 소비한다.
IDE에서 지원하는 리팩터링을 활용해보고 싶다.
리팩터링을 언제 시작하고 언제 그만할지를 판단하는 일은 리팩터링의 작동 원리를 아는 것 못지않게 중요하다.
인스턴스 변수를 삭제하거나 상속 계층을 만드는 방법을 설명하기는 쉽다. 이런 일들은 간단한 문제에 속한다. 하지만 이런 일들을 '언제' 해야 하는지에 대해서는 명확하게 정립된 규칙이 없다.
리팩터링을 언제 멈춰야 하는지를 판단하는 정확한 기준을 제시하지는 않을 것이다. 경험에 따르면 숙련된 사람의 직관만큼 정확한 기준은 없다. 종료 기준보다는 리팩터링하면 해결할 수 있는 문제의 징후를 제시하겠다.
뒤엉킨 변경 | 산탄총 수술 | |
원인 | 맥락을 잘 구분하지 못함 | |
해법(원리) | 맥락을 명확히 구분 | |
발생 과정(현상) | 한 코드에 섞여 들어감 | 여러 코드에 흩뿌려짐 |
해법(실제 행동) | 맥락별로 분리 | 맥락별로 모음 |
if (a < upper && a > lower)
처럼 처리하는 코드를 수없이 봤다.결론적으로, React와 Vue는 모두 테스트하기 용이하며 강력한 테스팅 도구와 유틸리티를 제공합니다. 선택하는 것은 주로 개인의 선호나 프로젝트의 요구 사항에 따라 달라질 수 있습니다.
by GPT옛날 옛적에 한 컨설턴트가 개발 프로젝트를 점검하러 파견을 나갔다. 작성된 코드를 보니 클래스 상속 구조가 시스템의 주축을 이루고 있었고, 전반적으로 아주 엉망이었다.
컨설턴트는 프로젝트 팀장에게 코드를 살펴보면서 정리하라고 권했지만 팀장은 콧방귀를 뀌는 듯한 태도였다. 어쨌든 그 코드는 문제없이 돌아가는 데다 중요한 일정들이 코앞이었으니 그럴 만도 했다. 팀장은 나중에 여유가 생기면 하겠다고 했다.
6개월 후 그 프로젝트는 완전히 망했다. 코드가 너무 복잡해서 디버깅도 할 수 없었고 최소한의 성능 요건을 맞추는 것도 불가능했다.
켄트 벡이 그 프로젝트를 새로 시작하기 위한 컨설팅을 맡았다. 시스템의 거의 모든 부분을 처음부터 새로 작성해야 했다. 켄트는 일하는 방식에 여러모로 변화를 줬는데, 그중 가장 핵심은 리팩터링을 활용해 코드를 꾸준히 정리하게 했다는 점이다. 결국 두 번쨰 시도는 성공했고, 전적으로 리팩터링 덕이었다.
리팩터링은 겉으로 드러나는 코드의 기능(겉보기 동작)은 바꾸지 않으면서 내부 구조를 개선하는 방식으로 소프트웨어 시스템을 수정하는 과정이다. 버그가 생길 가능성을 최소로 줄이면서 코드를 정리하는 정제된 방법이다. 요컨대, 리팩터링한다는 것은 코드를 작성하고 난 뒤에 설계를 개선하는 일이다.
리팩터링의 각 단계는 간단하다 못해 지나칠 정도로 단순하다. 한 클래스의 필드를 다른 클래스로 옮기고, 일부 코드를 메서드 밖으로 빼서 별도의 메서드로 만들고, 코드 일부를 상속 구조의 위/아래로 올리거나 내리는 등의 작업이다. 이런 사소한 수정도 누적되면 설계가 놀랍도록 개선된다. 소프트웨어가 부식된다는 개념의 정반대가 바로 리팩터링이다.
리팩터링을 하면 일의 균형이 바뀐다. 처음부터 완벽한 설계를 갖추기보다는 개발을 진행하면서 지속적으로 설계한다. 시스템을 구축하는 과정에서 더 나은 설계가 무엇인지 배우게 된다. 그 결과, 개발의 시작부터 끝날 때까지 프로그램은 줄곧 우수한 설계를 유지한다.
이 책은 소프트웨어 개발을 직업으로 하는 전문 프로그래머를 위해 쓰였다.
리팩터링은 코드에 집중하지만, 사실 시스템 설계에 미치는 영향이 상당히 크다. 그래서 선임 개발자나 아키텍트라면 반드시 리팩터링의 원리를 이해하고 프로젝트에 활용해야 한다.
책 전부를 읽지 않고도 내용 대부분을 습득하려면 다음과 같이 하자.
내가 정말 잘할 수 있을까? 아니, 우리가 정말 자랄 수 있을까?"
그런데 소프트웨어 기술자의 등급이라는 것이, 겉으로는 기술자격이나 학력에 경험을 함께 고려해 결정되는 것 같아 보이지만 사실상 '경험'이라는 요소가 가장 결정적 역할을 합니다. ... 이런 제도 때문에 사람들은 더더욱 경력의 틀(심리학적 프레임) 안에서 생각하게 됩니다. ... 저는 이 글을 통해,
이라고 이야기하려고 합니다.
...는 채용 시 가장 효과적인 예측변수가 무엇이냐에 대해 연구했습니다. 0에 가까우면 상관성이 없다고 말하고, 1이나 -1에 가까우면 상관성이 높다고 합니다. 통상 0.5를 넘으면 강한 효과가 있다고 하고 0.2에서 0.5 사이는 중간정도라고 하며, 0.2 이하는 약한 효과라고 합니다.
경력 연차의 상관성은 0.18, 학력의 상관성은 0.10입니다. 관심사조차도 직무 성과와 상관성이 0.10이 되는 수준입니다.
그렇다면 어떤 것들이 상관성이 높았을까요? 작업 샘플 테스트(실제로 채용 후 해야 할 작업의 일부를 해보는 테스트)가 0.54, 아이큐가 0.51이었습니다. 성실성이나 꼼꼼한 같은 성격 테스트도 0.41이나 0.31 정도의 상관성이 있었습니다. 레퍼런스 체크도 0.26으로 연차들의 상관성보다 높았습니다.
그렇다고 연차가 완전히 의미가 없는 것은 아니었습니다. 경력이 얼마 되지 않았을 떄 몇 년간은 연차의 상관성이 꽤 높은 편입니다.
예를 들면 경력을 지나치게 중요하게 여기는 회사가 많습니다. 동시에 협력 능력을 지나치게 등한시하는 회사가 많았습니다.
최소한도의 경력 수준만 넘겼으면 오히려 몇 년 일했는지는 모르는 것이 더 낫다고 생각하고요. 실제 작업을 해보도록 하는 작업 샘플 테스트, 실제 업무를 주고 시험적으로 짧은 기간 동안 일을 해보게 하는 것 등을 권합니다.
"조직에는 세 가지 차원의 작업이 있다"고 컴퓨터 선구자이자 마우스 발명가인 더글라스 엥겔바트가 말했다.
A 작업은 겉으로 가장 잘 드러나는 수준으로, 한 회사의 사람과 자원의 대부분은 이 수준에 초점이 맞춰져 있다. 그 회사의 사람고 자원의 대부분은 이 수준에 초점이 맞춰져 있다.
하지만 다음 수준인 B 작업 없이는 효과적인 A 작업은 불가능할 것이다. B 작업은 회사가 자신의 제품과 서비스를 개발, 생산, 판매하는 걸 가능케 해주는 시스템과 프로세스를 설계하는 것과 관련이 있다.
하지만 가장 미묘하고 또 잠재적으로 가장 영향력이 큰 것은 C 작업으로, 이는 우리의 사고방식과 상호 작용 방식을 개선한다. 궁극적으로는 C 작업의 품질이 우리가 설계하는 시스템과 프로세스의 품질을 결정짓고, 나아가 우리가 제공하는 제품과 서비스의 품질을 결정짓는다.
보통 경영학에서는 더하는 조직을 작업 그룹이라고 하고 곱하는 조직을 팀이라고 구분합니다. 작업 그룹은 주어진 일을 사람 숫자에 맞게 나눠주고 각자 정해진 일을 하는 형태를 말합니다. 서로 교류할 필요가 없습니다. 반면에 팀은 일을 상호 협력적으로 진행합니다.
잠자는 시간을 줄이는 것이 더하기적 사고라면, 집단의 지능을 높이는 것은 곱하기적 사고입니다.
그냥 일하는 시간을 늘리는 것은 작업량을 늘리는 것에 지나지 않습니다.
A 작업을 개선하려면 두 가지 질문을 해 봐야 합니다. 첫 번째는 어떻게 하면 더하기보다 곱하기를 할 수 있을 것인가입니다. 두 번째는 어떻게 해야 곱하는 비율(이자율)을 높일 수 있는가 혹은 이자 적용 주기(1년에 한 번 대신에 1달에 한번)를 짧게 할 수 있는가입니다.
한 그룹의 아이들에게는 실행 프레임을 갖게 합니다. "여러분이 얼마나 그림을 잘 그리는지 보고자 하는 겁니다. 여러분의 창의성을 측정해 보려고 합니다. 점수를 매길 거에요. ..." 다른 그룹 아이들에게는 학습 프레임을 갖게 합니다. "내가 안 그려 보았던 방식들을 실험해 보는 시간이에요. 여러 가지 방식으로 실험해 보세요." ... 실행 프레임에서는 '잘하기'에 초점을 맞추게 하고, 학습 프레임에서는 '자라기'에 초점을 맞추게 합니다.
여기에서 말하는 실행 프레임은 사람들이 현재 주어진 과업이 뭔가 좋은 성과를 내는 걸로 생각하는 틀을 말합니다. 학습 프레임은 현재 주어진 과업이 내가 얼마나 배우느냐로 여기게 되는 틀을 말합니다.
현재 상황 자체가 어렵지 않냐. 업무하면서 학습이 중요하다는 생각을 갖기가 어렵지 않냐.
지금 자신의 상황 '때문에' 학습 프레임을 갖는 것이 힘들다는 생각이 든다면, 이 우주 어딘가의 누구는 비슷한 상황 '덕분에' 학습 프레임을 가질 수 있었다고 생각하고 있다고 상상해 보면 어떨까요?
테트리스의 핵심은 살아있으면서도 간단한, 아기 버전의 테트리스를 만드는 것입니다.
일반적으로 제가 새로운 기술을 코칭에 적용할 경우 이 난이도 조절을 적극적으로, 점진적으로 하는 것 같습니다.
처음에는 현재 제 자신에게 적용해 홉니다. ... 그 다음에는 과거의 힘들거나 어려웠던 상황을 떠올려서 그 때의 자신을 코칭해 봅니다. ... 이게 되면 실제로 그 사람과 코칭을 해봅니다. 이 때에는 미리 언급을 합니다.
'인간' 역엔지니어링 방법을 사용하고, 또 가르치고 있습니다.
S 님의 어떤 전문성을 끌어낼까 하다가 '프로그래밍 언어를 배우는 전문성'을 하기로 했습니다.
적극적 읽기
첫 번째 목표로 주로 삼는 프로그램은 단어 개수 세기 프로그램이라고 합니다.
자연 언어 교육과는 다르게 프로그래밍 언어 교육에서는 읽기보다 쓰기를 더 강조하는 경향이 있습니다. 프로그래밍 언어를 가르칠 때 읽기를 교육하는 경우는 극히 드물죠. 하지만 프로그래머가 실제로 업무를 할 때에는 코드를 읽는 시간이 쓰는 시간을 압도합니다. 좋은 코드를 읽어봐야 좋은 코드를 쓸 수 있기도 하고요.
S 님은 튜토리얼을 읽어 나가면서 틈틈이 해당 언어의 표준 라이브러리를 찾아 읽었습니다.
Java로 작성된 프로그램이냐 C로 작성된 프로그램이냐를 가르는 진짜 기준은 어떤 언어의 키워드를 썼느냐가 아니라 어떤 스타일을 따르고 어떤 숙어를 사용했는가입니다.
한 가지 비결은 전문가가 구체적인 사건에 대해 말하도록 유도하는 겁니다.
S 님의 경우에는, 가장 최근에 익힌 언어가 Go라고 하더군요. 그 언어를 익힌 과정을 시간대별로 짚어가며 어떤 행동을 했는지, 그리고 암묵적인 의사결정과 상황판단이 무엇이었는지를 추출했습니다.
미국 산림청의 산불 정책이 수십년 전에 바뀐 것을 아십니까? 예전에는 산불 예방을 강조했습니다.
이제는 불 예방에서 불 관리 쪽으로 초점이 바뀌었습니다.
흥미로운 부분은 가장 사망률이 높은 병원과 가장 낮은 병원 집단 사이에 수술 후 합병증 발생 확률이 통계적으로 차이가 있었다는 점입니다. 그럼 무엇이 사망률의 차이를 만들었을까요? 합병증을 발견하고 적절한 조치를 취하는 부분에서 차이가 났습니다. ... 사망률이 낮은 병원은 심각한 합병증이 벌어지는 것을 잘 알아챘고, 또 합병증이 생긴 후 적절한 조치를 했던 것이죠.
실수 예방 문화에서는 실수를 한 사람을 비난하고, 처벌하고, 따라서 실수를 감추고 그에 대해 논의하기 꺼리며 문제가 생겼을 때 협력도 덜 하게 됩니다. 반대로 실수 관리 문화에서는 실수가 나쁜 결과를 내기 전에 빨리 회복하도록 돕고, 실수를 공개하고, 실수에 대해 서로 이야기하고 거기에서 배우는 분위기가 생깁니다.
실수 연구의 역사를 보면, 초기에는 기술적인 부분만 보다가 그 다음에는 인간적인 부분을 보다가, 이제는 문화적인 부분을 이야기합니다.
실수가 없으면 학습하지 못합니다. 이는 학습이론의 기본입니다.
다양한 실수를 경험하는 걸 격려하고, 실수 사례를 배우고, 실수 시에 어떻게 대처하는가를 가르치는 교육이 더 효과적이라는 연구 결과가 많습니다.
흥미롭게도 많은 조직에서 교육은 투입으로 성과를 측정하는 대표적 분야입니다.
기업에서의 교육, 훈련 효과에 대한 메타분석 연구에 따르면 대부분의 훈련은 6개월 정도만 지나도 효과가 거의 사라집니다.
존 해티의 연구에 따르면 교사가 가진 주제에 대한 지식수준은 효과 크기가 0.09에 지나지 않으며 ... 교사가 지식이 얼마나 많은지는 큰 영향을 미치는 요소가 아니라는 말이지요.
왜 그럴까요? ... 여기에서는 특히 '아는 것을 온전히 가르칠 수 있는가'하는 면에 초접을 맞춰보죠.
의료계의 연구를 보면, 전문가가 특정 수술법을 학생에게 가르칠 때, ... 70%는 가르치지 않는다는 분석이 거듭해 나왔습니다. 가르치는 능력을 인정받고 한 번 이상의 '탁월한 교사상'을 받은 사람임에도 그랬고, .. 그 기술을 성공적으로 해내기 위해 필요한 것의 30%만 가르쳐 놓고 자신은 다 가르쳤다고 생각하는 겁니다.
이런 현상이 벌어지는 이유에는 ... 대표적인 것이 자동화입니다. 전문가가 되면 자신이 하는 일이 반복적으로 몸에 익고 자동화가 되어서 결국 암묵적이 되어 버립니다.
이걸 극복하는 방법이 있을까요? 네. 있습니다. ... 한 가지 힌트를 드리자면, 앞에서 <프로그래밍 언어 배우기의 달인>의 인지적 작업 분석 같은 방법을 선생과 학생이 쓰는 겁니다. ... 메타분석에 따르면 선생이 인지적 작업 분석에 능숙한가 하는 것이 학생들의 학업성취도에 미치는 여향의 효과 크기가 자그만치 1.29나 됩니다. 이런 분석 능력이 뛰어난 선생이 잘 가르치는 사람이라는 이야기입니다.
또 선생의 메타인지를 돕기 위해 자기가 어떻게 생각하면서 이 문제를 풀었는지 그 인지적 과정을 선생에게 알려주는 것도 매우 효과적입니다.
보통은 어떤 사람이 전문가라고 하면 그 사람의 뇌 안에서 무슨 일이 벌어질까에만 주목하는 면이 있습니다. '고독한 천재'같은 ... 이미지로 떠올리기도 하죠. 그런데 과연 현실에서의 전문가가 정말 그런 사람일까요?
뭘 하든지 나 혼자가 아니라 항상 누군가가 등장하고, 일의 성패에 다른 사람이 관련되어 있기 때문입니다. 정리하면 다음과 같습니다.
1) 아무리 기술적인 실천법이라고 해도 2) 그 기술은 사회적 맥락 속에서 실천되어야 하며 3) 그 기술의 성공을 위해서는 사회적 자본과 사회적 기술이 함께 필요하다.
신뢰가 깨어져 있는 상태에서는 어떤 행동을 해도 악의적으로 보인다는 것입니다.
이 신뢰를 사회적 자본의 일종이라고 합니다.
전문가가 해당 도메인 지식만 뛰어난 사람이라는 것은 대표적인 미신입니다. 전문가는 사회적 자본과 사회적 기술 또한 뛰어납니다.
이제는 프로그래밍을 잘한다는 정의 안에 의사소통 능력을 그 일부로 보게 된 겁니다.
희망적인 소식은 이런 사회적 기술을 훈련으로 개선할 수 있다는 겁니다.
간단한 방법은 주변 사람들과 주고받는 마이크로 인터랙션에 신경을 쓰는 겁니다. 그걸 기록하고, 복기하고, 다르게 인터랙션한다고 하면 어떻게 했으면 좋았을까를 생각해보는 것만으로도 훈련이 될 수 있습니다.
저는 ... TDD를 사람들에게 교육하고 컨설팅해주었습니다. 제 경험에 한해서는 TDD 도입에 실패하는 경우, ... 필요한 사회적 자본과 사회적 기술이 없어서가 훨씬 더 많았습니다.
어떤 기술적 지식을 전달한다고 해도 그것을 사회적 맥락 속에서 가르치고 경험하게 하려고 노력하고 있습니다.
제가 중요하게 다루는 사회적 기술은 도움받기, 피드백 주고받기, 영향력 미치기, 가르치고 배우기, 위임하기 등이 있습니다.
사람들은 협력이 중요하다고 합니다. 그래서 프로젝트를 할 때 협력적으로 하자고 합니다. 그러나 실제 모습을 들여다보면 초반에 일을 세밀하게 나누고 선을 긋습니다. 그리고 안녕이죠.
우리는 협력을 제대로 배워본 적이 거의 업시 때문입니다.
그래서 지금부터라도 협력 방법을 배우고 수련해야 합니다.
조엘 테스트라는 것이 있습니다.
그러나 여기에 가장 큰 위험이 존재합니다. 선의의 관리자나 경영진이 각 질문의 맥락을 이해하지 못한 채 단순히 12가지 질문에 예라고 답하는 것을 목표로 노력하는 경우를 말하는 겁니다.
제가 아는 뛰어난 팀들은 툴을 고를 때 단순히 비싼 게 뭐냐를 기준으로 고르지 않습니다. 이 항목을 보고 '비싼 툴을 쓰면 잘하겠지'하고 생각하는 건 기술을 이해하지 못하는 경영자 마인드에 가깝습니다.
품질 전문가 제럴드 와인버그가 한 말을 살펴봅시다. 이분은 소프트웨어 개발을 잘 관리하려면 세 가지 근본적 능력이 필요하다고 했습니다.
이 세 가지 능력을 활용해 실제 조직과 개인(관리자 자신을 포함-와인버그는 자신을 바꾸지 못하는 사람은 다른 사람을 바꾸는 일도 할 수 없다고 합니다)
QSM 4권에 소프트웨어 개발 비용에 대한 내용이 있습니다. 다음 네 가지 요소의 분류에서 가장 중요한 것부터 나열해 보세요.
비슷한 크기의 소프트웨어를 개발한다고 할 때, 각 분류별로 비용 면에서 가장 적게 드는 회사부터 그렇지 않은 회사까지 100등까지 순위를 매깁니다. 85등이던 회사가 10등하는 회사로 '개선'을 했다면 개발 비용이 얼마나 줄어들까요? 개선효과가 높은 것은 무엇일까요?
...
관리, 시스템, 사람, 도구 순서였습니다. ... 하지만 각 분류별로 실제로 개선 시도가 얼마나 있었는지 확인해 보니 가장 많은 개선 노력이 있었던 분류를 바로 '도구'였습니다
다시 조엘 테스트로 돌아갑시다. 조엘 테스트는 가장 만만하고 쉬운 것부터 시작하는 관리자의 성향과 충돌하지 않습니다.
저는 관리자가 눈에 잘 보이고 갈아치우기 쉬운 '도구'들에 신경을 쓰는 것이 위험하다고 생각합니다.
일반적으로, 실력이 뛰어난 프로그래머는 보통 정도의 실력을 가진 프로그래머에 비해 커뮤니케이션, 협력 능력이 더 뛰어납니다.
둘이서 함께 작업한 경우 58%나 추상화 규칙을 찾아냈습니다. 4배가 넘습니다. 만약 두 사람이 한 팀으로 작업하되 서로 이너랙션하지 않았고, 그들의 결과물 중 더 나은 것을 택하는 방식(명목 집단(nominal group)이라고 함)이라면? 이 경우는 확률적으로 계산할 수 있는데, 26%가 됩니다.
그러면서 맞은편의 사람과 이야기를 하는데, ... 이런 혼동을 해결하기 위해 추상적 개념을 도입합니다. 예컨대 바퀴에 식별 번호를 붙인다든지 하는 것이지요.
둘이서 협력하면서 작업하면 서로 시각이 다르기 때문에 두 사람의 다른 시각을 연결해 줄 다리가 필요하고, 그 다리에는 필연적으로 추상화의 요소가 있게 됩니다. 서로 다른 것들을 하나로 묶어야 하기 때문입니다.
만약 코드가 비지니스 로직이 들어가고 그 로직이 domain-rich 하다면 되도록 가독성을 추구하겠지만, 저는 때로 가독성을 손해보면서까지 중복을 줄이기도 합니다. ... 흥미로운 객체들을 발견합니다. ... 내가 전에 모르던 것을 배우게 됩니다.
'흥미로운 무엇'이 바로 추상화입니다.
인용문 대로 소프트웨어 공학의 역사는 정말 추상화를 높이기 위한 여정이었습니다. ... 그런데 우리는 조금 전 추상화를 높일 수 있는 방법을 하나 찾아냈습니다.
익스트림 프로그래머는 작업하면서 프로그래밍 각 단계에 대해 함께 이야기한다.
자신이 작성하는 코드의 추상성을 높이고 싶다면 혼자서 고민하지 말고 다른 사람들과 협동하고, 대화하세요. 같이 그림도 그려보고 함께 소스코드를 편집하세요. 인간에게는 다른 인간과 소통하고 협력할 수 있는 놀라운 능력이 있습니다. 대화는 기적입니다.
조금 충격적인 이야기를 해드리겠습니다. 두 경우 모두 공유 후에 신뢰감이 더 떨어졌습니다. 특히 첫 번째, 즉 디자인 하나만 작업하고 그걸 공유한 경우가 더 많이 떨어졌습니다만, 두 조건 모두 신뢰감이 통계적으로 유의미하게 떨어졌습니다. 공유를 해서 신뢰가 더 떨어지는 상황이 벌어진 것이죠.
각자 여러 개의 디자인을 만들고 그걸 모두 공유한 경우였습니다. 이때는 신뢰가 유의미하게 증가했습니다.
하나 공유나 최고 공유의 경우 우리는 공유 자리에 기대감보다 불안감을 갖고 갈 겁니다.
복수 공유는 그런 불안감이 상대적으로 덜합니다. 여러 개를 준비했으니 그중 하나를 두고 뭐라고 해도 나에 대한 공격은 아닌 겁니다.
마지막으로 가장 놀라운 부분 ... 클릭률이 더 높았습니다. 복수 공유는 (같은 시간을 투자했을 때) 신뢰도 높아지고 성과도 더 좋았다는 말입니다.
여러분의 공유는 어떻습니까? 신뢰를 깎아먹는 공유를 하고 계신가요, 신뢰를 쌓아가는 공유를 하고 계신가요?
새로운 개념을 주변에 설득하기 위해 노력하는 분들을 많이 봅니다.
그런 분들을 만나면 저는 다음과 같은 질문을 던집니다. "상대방에 대해 얼마나 이해를 하고 계신가요? 얼마나 대화를 해보셨나요?"
강사는 자신이 좋은 예를 들었다고 생각합니다. 하지만 질문자는 그렇게 생각하지 않습니다. '예'의 정이가 주관적이라 벌어진 일이죠.
품질 전문가 제럴드 와인버그는 품질을 다음과 같이 정의합니다.
품질이란 누군가에게 가치가 되는 것이다.
우리가 일반적으로 듣는 품질의 정이와 다르죠? ... 그런 정의들은 매우 플라톤적입니다. 뭔가 고상하고 완벽한 품질이라는 것이 하늘 어딘가에 있는 것처럼 들립니다. 하지만 와인버그의 정의는 상대주의적이며 동시에 무척 실용적입니다.
우리가 품질을 이야기할 때에는 '누구'를 놓고 하는 말이냐는 걸 생각해 봐야 한다 이겁니다.
결국 결정하는 것은 사람입니다.
그리고 논리랑 감정적 판단을 분리할 수가 없습니다.
의사결정을 하는 과정에 감정적이고 직관적인 부분이 큰 역할을 하고 있으며, 그런 감정적 부분이 배제된다면 의사결정을 제대로 할 수 없다는 것을 알 수 있습니다.
남을 설득하려면 논리성과 객관성에 대한 환상을 버려야 합니다. 그래야 현실적으로 설득이 가능합니다. 내가 설득하고 싶은 상대를 자주 만나서 신뢰를 쌓고, 그 사람이 무엇을 중요하게 여기는지, 어떤 설명 방식을 선호하는지 이해해야 합니다.
결론은, 객관성이라고 하는 것은 상대적이며, 내가 생각하는 객관이 상대의 객관이 아닐 수 있고, 그렇기 때문에 설득에 성공하려면 우선 그 사람을 이해하는 것에서 출발해야 한다는 말입니다.
이런 과정을 거치면 홍춘이의 머릿속에는 어떤 그림이 떠오를까요? ... 술퍼맨의 머릿속 지도와 사고 흐름을 엿보게 되는 것이죠.
그 사람이 이 상황에서 왜 이런 접근을 할 수밖에 없었는지 알기 때문에 좀 더 정확하고 효과적인 제안을 해줄 수 있습니다. ... 또, 소위 암묵지라고 부르는 것들을 전달해줄 수도 있습니다.
술퍼맨 : 네, 그러고 싶어요. 그런데 언젠가 한번 마음먹고 제대로 공부해야지, 해야지 하고 생각하면서 몇 달째 미루고 있는 것 같아요.
홍춘이 : 정규식을 배워서 해보고 싶은 것들이 있나봐요. ...
참고로 코칭의 흥미로운 점은 코치 자신(홍춘이)이 해당 영역(정규식)에 대한 전문지식이 없어도 코칭을 할 수 있다는 점입니다.
대부분의 기업에서 직원 숫자가 늘어나기 시작하면 추상 층위에 따라 팀을 나눕니다. 각 층위의 전문가 팀이 존재합니다. 기획팀, 구현팀, QA팀 등, 그리고 일이 진행됨에 따라 팀 간의 바통 터치가 이루어집니다. 위에서 아래 방향으로요.
그럼 모든 문제를 탑다운 식으로 푸는 것이 우리의 지향점일까요? 인공지능 연구에선 이 세상의 문제를 두 종류로 나눕니다. 잘 정의된 문제와 잘 정의되지 않은 문제 ... 오목이나 체스 ... 여기에 속합니다.
하지만 우리가 실생활에서 만나는 대다순의 문제는 잘 정의되지 않은 문제입니다.
앞서의 전문가들은 ... 잘 정의되지 않은 문제를 접하면 접근법을 바꿉니다. 탑다운과 바텀업을 섞어 씁니다. 뛰어난 전문가일수록 더욱 그러합니다.
특히 탑다운과 바텀업의 방향이 전환되는 시점들에서 '아하 순간'이 찾아왔습니다.
"이번 일은 복잡하고 불확실하니까 철저하게 계획하고 단계적으로 접근하자!" 이 말은 곧, 이번 일은 불확실하니까 초보처럼 일하자는 말과 똑같습니다.
오히려 전문가일수록 자신의 계획을 수정한 횟수가 많았습니다.
연구에 따르면, 프로그램을 이해할 때 고수는 상호 참조 전략을 쓰는 반면 하수는 그렇지 않았습니다.
고수는 ... 프로그램에서 이해한 것을 도메인 어휘로 번역합니다. 그러고는 도메인 어휘를 프로그램상의 어휘로 다시 바꿔서 검증합니다. 이를 상호 참조 전략이라고 합니다.
삼투압적 의사소통
사람들이 물리적으로 가까운 거리에 있어야 유리하겠죠.
그리고 한번에 처리되는 일의 양(batch size)을 줄여야 합니다. 배치 사이즈를 줄여서 지속적 흐름을 만들고 짧은 시간 내에 탑, 바텀을 오가게 합니다. 예를 들어 전에는 디자이너가 100개의 일자리를 다 처리한 후에 한꺼번에 모아 결과를 전달했다면 점차 50개로, 10개로, 1개로 낮추어야 합니다.
어느 한 단계를 한번에 완료하는 것은 더 낮은 품질로 가는 지름길입니다.
흔히들 말하는 개발의 5단계도 비슷합니다. ... 어떻게 해야 첫 달부터, 아니 첫 주부터 분석, 설계, 구현, 테스트, 전개를 모두 왔다갔다할 수 있을까를 고민해야 할 것입니다.
회사에서의 올스타는 어떨까요? ... 스타들이 한 명씩 팀에 추가될 떄마다 팀의 추가적 성과 향상은 한계효용을 보이며 어느 수준을 지나면 음의 방향으로 작용한다고 합니다.
전문가가 추가되는게 도움이 안 되거나 오히려 성과를 깎아먹는 경향은 특히나 전문가들의 전문성이 서로 유사할 떄 도드라졌습니다.
자기들이 알아서 하게 놔둔 전문가팀은 비전문가로만 구성된 팀보다도 훨씬 못한 결과가 나왔습니다.
팀 내에 개인 내 다양성이 높은 멤버가 없다면 전문가로 구성된 팀은 정보 공유가 잘 안 되어서 성과가 떨어질 수 있다는 분석을 했습니다.
제가 봤을 떄 중요한 부분은 세 군데입니다.
팀에 누가 있는지(전문가, 내향/외향, 지능 등)보다 팀원들이 서로 어떻게 상호작용하고 자신의 일을 어떻게 바라보는지가 훨씬 중요했다.
5가지 성공적 팀의 특징을 찾았는데, 그중 압도적으로 높은 예측력을 보인 변수는 팀의 심리적 안전감이었다.
팀 토론 등 특별히 고안된 활동을 통해 심리적 안전감을 개선할 수 있었다.
여기에서 말하는 심리적 안전감이란, 내 생각이나 의견, 질문, 걱정, 혹은 실수가 드러났을 때 처벌받거나 놀림받지 않을 거라는 믿음을 말합니다.
에드몬드슨은 이런 도구를 사용해 병원의 중환자실의 심리적 안전감을 측정해 보았습니다. ... 예상과 비슷하게, 직위에 따라 느끼는 심리적 안전감에 통계적으로 유의미한 차이가 있었습니다.
심리적 안전감이 높은 병실에서는 ... 18%나 낮은 사망률을 보였습니다.
팀원이 불편한 문제를 제기하거나, 어리석어 보이는 질문을 하거나, 부족한 의견을 얘기하거나, 어처구니없는 실수를 저지를 때 여러분은 어떤 마이크로 인터랙션을 보여주고 계신가요?
논문 제목은 <팀 학습의 속도 높이기>입니다. 최소 침습 심장 수술법을 어떤 팀이 빨리 익히는가 하는 것이 주제입니다.
하지만 놀라운 점은 수술 시간 감소율이 팀마다 천차만별이었다는 겁입니다.
단순히 기술적 탁월함만을 갖춘 사람보다는 학습 환경을 만들 수 있는 리더가 필요하다는 것입니다.
선발 자체가 매우 협동적
속도가 빠른 팀은 새로운 수술 도입을 기술적 도전이라기보다 조직적 도전으로 받아들였습니다. 개개인이 새로운 기술을 획득해야 한다고 보지 않고, 함께 일하는 새로운 방법을 만들어야 한다고 생각했습니다.
마지막으로, 속도가 빠른 팀은 심리적으로 보호가 되고 있었습니다.
속도가 빠른 팀은 도전 자체를 팀의 학습 능력에 대한 도전으로 받아들였고, 같이 학습해야 한다고 생각했습니다.
속도가 느리거나 낙오된 팀은 학습을 개인의 과제로 치부했습니다. 학습보다는 단기 퍼포먼스를 중요시했습니다.
다시 현실에서 돌아와서, 나는 팀장도 아니고, 정치적인 힘도 없습니다. 그렇다면 이 상황에서 내가 무엇을 할 수 있을까요? 팀원과 팀장에게 이 책을 권할 수 있는 분위기도 아니라면?
우선 자신의 학습 환경을 만드세요. 거기서부터가 출발입니다. 개별 기술 이상으로 일하는 방식에 대해 실험을 해 보세요.
소프트웨어 공학 쪽의 연구에 따르면 사람들이 통상적으로 추정하는 소요시간에 적어도 2~3배를 해야 80% 정도의 확률로 마칠 수 있는 시간이 나온다고 합니다.
게다가 일반적으로 일의 소요 시간을 추정할 때 사람들이 낙관적으로 추정한다는 편향에 대한 연구 결과가 많다는 점까지 고려하면 상황은 더 심각해집니다.
또 다른 연구에 따르면, 사람들에게 가장 그럴싸한 추정(best guess)을 부탁했을 때와 자신이 기대하는 최선의 상황(best case scenario)을 상상해서 추정해보라고 부탁했을 때 그 추정치는 큰 차이가 없었습니다.
제가 선호하는 접근법은 관리자가 12명 모두에게 단지 3가지 일만 주고 서로 협동해서 그 일을 하도록 요청하는 것입니다.
이 방식이 잘 돌아가는 이유는 사람들이 '관심사의 섞임'을 통해 서로에 대해 엄청나게 많은 것을 매우 빨리 배울 수 있기 때문입니다.
애자일은 앞서의 고전적 방법과 달리 일을 공유합니다. 각자 일을 얼마나 진행했는지 매일 공유할 뿐 아니라 내 일, 네 일의 구분선이 뚜렷하지 않습니다. 애자일에서는 되도록 사람들이 섞이도록 합니다.
애자일은 마치 프랙털 구조처럼 부분 속에 전체가 들어가게 합니다. 그렇게 하면 과거에서 미래를 접쳐 보기가 훨씬 쉽습니다. 일이 진행될수록 점점 추정 정확도가 높아집니다.
한 사람만이라도 중요한 통찰이 있었다면 이걸 공유해서 '또는' 확률로 만들고, 버그 같이 나쁜 일에 대해서는 여러 사람이 중복 검토를 해서 모두가 실수해야지만 구멍이 나게 '그리고' 확률로 바꾸는 것입니다.
당시 주도적인 소프트웨어 개발 방식은 계획주도의 방식이었습니다. 계획주도 방식에서는 초반에 계획을 정교하고 꼼꼼하게 만들려고 엄청난 노력을 합니다. 그러면 실행단계는 간단해지고 예측 가능해진다고 생각하기 때문입니다. 하지만 애자일은, 불확실성이 높은 일에 대해서는 애초에 이것이 불가능하다고 봅니다. 불확실성 크기 때문에 미리 분석하고 설계하는 데 한계가 있다는 것이지요.
이번에는 과의의 애자일을 얘기해 보겠습니다. 애자일을 단순히 소프트웨어 개발 방법론이라는 울타리에 가두어 보지 않고, 일하는 한 가지 스타일, 혹은 더 넘어서서 삶을 사는 방식으로까지 확장해 보는 것이지요.
학습과 협력은 불확실성이 큰 상황에서 좋은 대응전략이 됩니다. 우리의 삶도 불확실하기 때문에 학습과 협력은 현명한 전략이 될 것이고요.
씨앗이 될만한 것을 줘야합니다.
고객에게 매일 가치를 전하라.
두려워도 중요하다면 시도해봐야 하지 않겠는가
결과들을 보면 상담에서 어떤 기법을 쓰느냐보다 치료자가 누구인가가 상담 효과에 더 큰 영향을 준다는 게 거듭 밝혀졌습니다.
매뉴얼이 말하고 있는 것보다 훨씬 더 많은 것을 상담사들이 할 수 있다는 말이 될 것입니다.
사실 더 나아가서 모든 지식이 근본적으로는 암묵지라고 역설했습니다.
맥락을 가로지르는 보편적 규칙들이 별로 없다고 생각이 든다면, 결과를 에측하기 어렵고 불확실성이 높다면, 해당 분야는 '복잡한 도메인'이 됩니다. 상담이 그렇죠. 이런 복잡한 분야일수록 어떤 특정 기법의 효과보다도 치료자 효과가 더 큰 영향을 미칠 것입니다.
내가 어떤 팀장인지가 전혀 바뀌지 않으면서 새 방법론만 도입한다고 무슨 효과가 있을까요.
칸반 같은 개별 실천법은 상시 변화하고 발전하는 도요타의 특정 시점의 스냅샷 같은 것이 아닐까 생각합니다. 우리가 배워야 할 것은 칸반 이면의, 칸반이 나올 수 있었던 구조의 문화입니다.
"... 애자일을 도입할 때 확실성 위에서 진행하려고 한다면 문제가 된다"
이것은 거의 모든 종류의 방법론 도입에 적용됩니다. 왜냐하면 방법론 도입은 태생적으로 불확실성이 높기 때문입니다. ... 수순을 따르는 것이 아니라 곁에 있는 사람들과 함께 주변을 탐색하고 조금 나아가고 확인하고를 반복하면서 우리의 현 맥락에 맞는 좋은 전략들을 스스로 만들어 나가는 것이 아닐까 합니다