웹은 MPA, PEMPA, SPA를 거쳐 PESPAs로 이동 중입니다. 각 아키텍처의 장단점과 코드가 어디에서 실행되는지의 변화, 그리고 Remix가 구현하는 차세대 웹 앱 아키텍처를 살펴봅니다.
웹은 25년이 넘는 세월 전에 시작된 기술들로 이루어져 있습니다. HTTP, HTML, CSS, 그리고 JS는 모두 90년대 중반(제가 여덟 살이던 때)에 처음 표준화되었습니다. 그 이후로 웹은 어디서나 사용하는 애플리케이션 플랫폼으로 진화했습니다. 웹이 발전함에 따라 이러한 애플리케이션을 개발하는 아키텍처도 함께 발전했습니다. 오늘날 웹 애플리케이션을 만드는 데에는 여러 핵심 아키텍처가 존재합니다. 현재 웹 개발자들이 가장 많이 사용하는 아키텍처는 단일 페이지 앱(SPA)이지만, 우리는 지금 웹 애플리케이션을 만들기 위한 새롭고 개선된 아키텍처로 전환하고 있습니다.
<a>와 <form> 요소는 아주 초창기부터 존재했습니다. 링크는 브라우저가 서버에서 무언가를 가져오기 위한 것이고, 폼은 브라우저가 서버로 무언가를 보내고(그리고 그 대가로 무언가를 받기 위한) 것입니다. 명세의 시작부터 이런 양방향 통신이 확립되어 있었기 때문에, 웹에서는 언제나 강력한 애플리케이션을 만들 수 있었습니다.
아래는 주요 아키텍처(대중적 사용의 연대기 순)입니다:
각 웹 개발 아키텍처는 장점과 고충이 있습니다. 결국 고충이 충분히 커지면 다음 아키텍처로 이동할 동기가 생기고, 그 역시 새로운 트레이드오프를 동반합니다.
우리가 애플리케이션을 어떻게 만들든, 거의 항상 서버에서 실행되는 코드가 필요합니다(주목할 만한 예외로는 Wordle 같은 게임이 있는데, 이는 ([한때는]) 로컬 스토리지에 게임 상태를 저장했습니다). 이러한 아키텍처들을 구분하는 요소 중 하나는 코드가 어디에 존재하느냐 입니다. 각 아키텍처를 차례로 살펴보며 시간이 지나면서 코드의 위치가 어떻게 변했는지 확인해봅시다. 각 아키텍처를 다루면서 특히 다음과 같은 코드 용례를 살펴보겠습니다:
물론 웹 애플리케이션은 이 외에도 더 많은 부분으로 이루어져 있지만, 이 항목들은 가장 자주 옮겨 다니는 부분이며 우리가 웹 개발자로서 대부분의 시간을 보내는 영역입니다. 프로젝트 규모와 팀 구조에 따라 이 모든 범주의 코드를 다루기도 하고, 그중 일부분만 다루기도 합니다.
초기에는 당시 웹 브라우저의 역량에 비추어 볼 때, 실제로 동작 가능한 유일한 아키텍처가 바로 이것이었습니다.
멀티 페이지 앱에서는 우리가 작성하는 모든 코드가 서버에 존재합니다. 클라이언트의 UI 피드백 코드는 사용자의 브라우저가 처리했습니다.
문서 요청(Document Request): 사용자가 주소창에 URL을 입력하면 브라우저는 서버로 요청을 보냅니다. 라우팅 로직은 영속성 코드와 통신하는 데이터 가져오기 함수를 호출하여 데이터를 조회합니다. 이 데이터는 렌더링 로직에 의해 HTML을 결정하는 데 사용되고, 그 HTML이 클라이언트에 대한 응답으로 전송됩니다. 그동안 브라우저는 파비콘 위치에 보통 표시되는 보류(pending) 상태 등으로 사용자에게 피드백을 제공합니다.
변경 요청(Mutation Request): 사용자가 폼을 제출하면 브라우저는 폼을 직렬화하여 서버로 요청을 보냅니다. 라우팅 로직은 영속성 코드와 통신하는 데이터 변경 함수를 호출해 데이터베이스를 업데이트합니다. 그런 다음 브라우저가 새로운 UI를 가져오기 위해 GET 요청을 트리거하도록 리다이렉트 응답을 보냅니다(이는 사용자가 처음 URL을 입력했을 때와 같은 과정을 다시 트리거합니다). 이때도 브라우저는 보류 UI로 사용자에게 피드백을 제공합니다.
참고: 성공적인 변경 요청에는 단순히 새로운 HTML을 반환하는 대신 리다이렉트 응답을 보내는 것이 중요합니다. 그렇지 않으면 히스토리 스택에 POST 요청이 남아 뒤로 가기 버튼을 누를 때 POST 요청이 다시 트리거됩니다(가끔 앱이 “뒤로 가기 버튼을 누르지 마세요!!”라고 하는 이유가 궁금하셨나요? 그게 바로 이유입니다. 리다이렉트로 응답했어야 했습니다).
MPA의 멘탈 모델은 단순합니다. 우리는 그때 그 가치를 충분히 알지 못했습니다. 쿠키를 통한 일부 상태와 복잡한 흐름이 있긴 했지만, 대체로 모든 것이 요청/응답 사이클 내에서 일어났습니다.
이 아키텍처가 부족했던 점:
웹 플랫폼은 다가오는 페이지 전환 API와 함께 지속적으로 개선되고 있어 MPA가 더 많은 사용 사례를 처리할 수 있는 현실적인 옵션이 되어가고 있습니다. 하지만 대부분의 웹 애플리케이션에는 여전히 충분치 않습니다. 어쨌든, 당시에는 이 문제는 표준화 위원회의 관심사에서 한참 벗어나 있었고, 사용자들은 지금 더 많은 것을 원했습니다!
프로그레시브 인핸스먼트(점진적 향상)는 우리 웹 애플리케이션이 모든 웹 브라우저에서 기능적으로 접근 가능해야 하며, 그 다음에 브라우저가 가진 추가 기능을 활용해 경험을 향상시키자는 아이디어입니다. 이 용어는 2003년 Nick Finck와 Steve Champeon이 만들었습니다. 브라우저의 역량 이야기가 나왔으니…
XMLHttpRequest는 1998년 Microsoft의 Outlook Web Access 팀에 의해 처음 개발되었지만 표준화된 것은 2016년이었습니다(믿기시나요!?). 물론 이것이 브라우저 벤더와 웹 개발자들을 막지는 못했습니다. AJAX는 2005년에 용어로 널리 알려졌고 많은 사람들이 브라우저에서 HTTP 요청을 만들기 시작했습니다. UI를 제자리에서 업데이트하기 위해 서버에 전체를 다시 가지 않고도 조금의 데이터만 가져와도 된다는 아이디어 위에 비즈니스가 만들어졌습니다. 그리하여 점진적 향상의 멀티 페이지 앱을 만들 수 있게 되었습니다:
“와!” 하고 생각하실 수도 있겠죠. “잠깐만… 이 모든 코드는 어디서 온 거지?” 이제 우리는 브라우저에게서 UI 피드백의 책임을 가져왔을 뿐만 아니라, 라우팅, 데이터 가져오기, 데이터 변경, 렌더링 로직까지 클라이언트로 가져왔습니다. 서버에 있던 것에 더해서 말이죠. “대체 왜?”
사실은 이렇습니다. 점진적 향상의 아이디어는 우리의 베이스라인이 기능하는 앱이어야 한다는 것입니다. 특히 2000년대 초반에는 사용자가 우리의 멋진 새 AJAX를 실행할 수 있는 브라우저를 사용한다고 보장할 수 없었고, 앱과 상호작용하기 전에 우리의 JavaScript를 다운로드할 만큼 빠른 네트워크에 있다고 보장할 수도 없었습니다. 그래서 기존 MPA 아키텍처를 유지하고 JavaScript는 경험을 _향상_시키는 데만 사용해야 했습니다.
그렇다 보니, 우리가 이야기하는 향상의 수준에 따라 영속성을 제외한(오프라인 모드를 지원하려면 영속성도 필요하지만, 정말 멋진 기능이긴 해도 업계 표준 관행은 아니므로 도표에서는 제외했습니다) 거의 모든 범주의 코드를 작성해야 할 수도 있었습니다.
게다가, 클라이언트가 만들 AJAX 요청을 지원하기 위해 백엔드에 더 많은 코드를 추가해야 했습니다. 즉, 네트워크 양쪽 모두에 코드가 더 많아졌습니다.
이 시기가 jQuery, MooTools 등의 전성기입니다.
문서 요청(Document Request): 사용자가 문서를 처음 요청할 때는 MPA 사례와 동일한 일이 벌어집니다. 다만 PEMPA는 향상 기능에 사용할 클라이언트 측 JavaScript를 로드하기 위해 <script> 태그도 포함합니다.
클라이언트 측 내비게이션: 사용자가 앱 내부의 href를 가진 앵커 요소를 클릭하면, 클라이언트 측 데이터 가져오기 코드는 기본 전체 페이지 새로고침 동작을 막고 JavaScript로 URL을 업데이트합니다. 그런 다음 클라이언트 라우팅 로직이 UI에 어떤 업데이트가 필요한지 판단하고, 데이터 가져오기 라이브러리가 서버 엔드포인트로 네트워크 요청을 보내는 동안(보류 상태 같은 UI 피드백을 표시하는 것을 포함해) 수동으로 해당 업데이트를 수행합니다. 서버 라우팅 로직은 영속성 코드에서 데이터를 가져오는 데이터 가져오기 코드를 호출하고, 그 데이터를 응답으로 보냅니다(XML 또는 JSON 중에서 우리가 선택할 수 있었죠 😂). 클라이언트는 그 데이터를 사용해 렌더링 로직으로 최종 UI 업데이트를 수행합니다.
변경 요청(Mutation Requests): 사용자가 폼을 제출하면, 클라이언트 측 데이터 변경 로직이 기본 전체 페이지 새로고침과 POST 동작을 막고, JavaScript로 폼을 직렬화해 서버 엔드포인트로 데이터를 보냅니다. 서버 라우팅 로직은 데이터 변경 함수를 호출하여 영속성 코드와 상호작용해 변경을 수행하고, 업데이트된 데이터를 클라이언트에 응답합니다. 클라이언트 렌더링 로직은 그 업데이트된 데이터를 사용해 필요한 방식으로 UI를 업데이트합니다. 경우에 따라 클라이언트 측 라우팅 로직이 사용자를 다른 곳으로 보낼 수 있으며, 이는 클라이언트 측 내비게이션 흐름과 유사한 흐름을 트리거합니다.
클라이언트 측 코드를 도입하고 UI 피드백 책임을 우리가 떠맡음으로써 MPA의 문제들은 확실히 해결했습니다. 훨씬 더 많은 제어권을 가지게 되었고, 사용자에게 더 맞춤화된 앱 같은 느낌을 줄 수 있게 되었죠.
하지만 사용자가 원하는 최고의 경험을 제공하려면 라우팅, 데이터 가져오기, 변경, 렌더링 로직에 대한 책임도 져야 합니다. 여기에 몇 가지 문제가 있습니다:
개인적으로 이 즈음에 제가 웹 개발 세계에 들어왔습니다. 그 시절을 그리운 향수와 오싹한 공포가 뒤섞여 떠올립니다 🍝.
중복 문제를 제거할 수 있는 방법이 백엔드의 UI 코드를 그냥 지워버리는 것임을 깨닫는 데 오래 걸리지 않았습니다. 그래서 정말로 그렇게 했습니다:
이 그림은 PEMPA와 거의 동일합니다. 유일한 차이점은 렌더링 로직이 사라졌다는 것입니다. 또한 UI를 위한 라우트가 더 이상 필요 없으므로 일부 라우팅 코드도 없어졌습니다. 남는 것은 API 라우트뿐입니다. 이 시기는 Backbone, Knockout, Angular, Ember, React, Vue, Svelte 등이 주도했습니다. 오늘날 대부분의 업계가 사용하는 전략이기도 합니다.
백엔드에 더 이상 렌더링 로직이 없기 때문에, 모든 문서 요청(사용자가 URL을 처음 입력할 때 하는 요청)은 정적 파일 서버(보통 CDN)가 제공합니다. SPA 초기에는 그 HTML 문서가 <body> 안에 <div id="root"></div> 하나만 있는 사실상 비어 있는 HTML 파일인 경우가 많았고, 여기에 애플리케이션을 “마운트”했습니다. 오늘날에는 프레임워크가 “정적 사이트 생성(SSG)”이라는 기법을 사용해 빌드 타임에 알 수 있는 만큼 페이지를 사전 렌더링할 수 있도록 해줍니다.
이 전략의 다른 동작은 PEMPA와 동일합니다. 단지 이제는 대부분 XMLHttpRequest 대신 fetch를 사용합니다.
흥미로운 점은, 위의 아키텍처 동작에서 PEMPA와의 유일한 차이가 문서 요청이 더 나빠졌다는 것입니다! 그런데 왜 이렇게 했을까요!?
여기서 가장 큰 장점은 개발자 경험(DX) 입니다. 이것이 바로 PEMPA에서 SPA로 전환을 주도한 원동력이었습니다. 코드 중복이 없어졌다는 것은 엄청난 이점이었습니다. 우리는 이 변화를 다양한 방식으로 정당화했습니다(DX는 결국 UX의 입력이니까요). 하지만 불행히도 SPA가 실제로 우리에게 가져다준 건 DX 개선뿐이었습니다.
개인적으로 SPA 아키텍처가 체감 성능을 개선한다고 설득되었던 기억이 납니다. CDN이 서버가 HTML을 생성하는 것보다 더 빠르게 HTML 문서에 응답할 수 있으니까요. 하지만 실제 시나리오에서는 그게 큰 차이를 만들지 못했습니다(현대 인프라 덕분에 지금은 더더욱 그렇지 않습니다). 슬픈 현실은 SPA가 여전히 PEMPA와 동일한 문제들을 안고 있다는 것입니다. 다만 더 현대적인 도구 덕분에 처리하기가 조금 쉬워졌을 뿐입니다.
설상가상으로, SPA는 몇 가지 새로운 문제도 도입했습니다:
document → app.js → page.js → component.js → data.json → image.png 같은 치명적인 의존성 체인이 생깁니다. 좋지 않으며, 결국 사용자 경험을 훨씬 더 나쁘게 만듭니다. 정적 콘텐츠의 경우 이런 문제의 상당 부분을 피할 수 있지만, 그 역시 수많은 이슈와 한계를 동반하며 SSG 전략을 파는 이들은 이에 대한 벤더 종속적 해결책을 기꺼이 우리에게 판매하려 합니다.이 이슈를 다루고 영향을 줄이기 위한 라이브러리들이 만들어졌습니다. 이는 매우 도움이 되었지만, 어떤 이들은 이런 변화가 피로감을 준다고 말합니다. 2010년대 중반 이후로 이것이 웹 앱을 만드는 사실상의 표준이 되었습니다. 이제 2020년대에 접어들며, 지평선에 새로운 아이디어가 보입니다.
MPA는 멘탈 모델이 단순합니다. SPA는 더 강력한 기능을 제공합니다. MPA 시기를 거쳐 이제 SPA에서 일하는 사람들은 지난 10년 동안 잃어버린 단순함을 진심으로 아쉬워합니다. 흥미로운 점은 SPA 아키텍처의 동기가 주로 PEMPA 대비 개발자 경험을 개선하는 데 있었다는 사실입니다. 만약 SPA와 MPA를 하나의 아키텍처로 somehow 융합해 양쪽의 장점을 모두 얻을 수 있다면, 단순하면서도 더 강력한 무언가를 얻을 수 있을 것입니다. 그것이 바로 점진적 향상의 단일 페이지 앱(PESPA)입니다.
프로그레시브 인핸스먼트에서는 클라이언트 측 JavaScript가 없어도 앱이 기능하는 것이 베이스라인입니다. 만약 우리의 프레임워크가 프로그레시브 인핸스먼트를 핵심 원칙으로 가능하게 하고 장려한다면, 우리의 앱은 단순한 MPA의 멘탈 모델이라는 견고한 기반 위에 세워집니다. 특히 요청/응답 사이클의 컨텍스트에서 사물을 생각하는 멘탈 모델입니다. 이는 SPA의 문제들을 상당 부분 제거할 수 있게 해줍니다.
이 점은 강조할 가치가 있습니다: 프로그레시브 인핸스먼트의 주요 이점은 “앱이 JavaScript 없이도 동작한다”는 것이 아닙니다 (물론 이는 좋은 부가 이점입니다). 오히려 멘탈 모델이 극적으로 단순해진다는 점이 핵심입니다. 계속 읽어보세요…
이를 위해 PESPAs는 기본 동작을 취소할 때 브라우저를 “에뮬레이션”해야 합니다. 즉, 브라우저가 요청을 보내든 JavaScript 기반 fetch 요청을 하든 서버 코드는 동일하게 동작해야 합니다. 그래서 여전히 그 코드는 우리가 소유하지만, 나머지 코드에서는 단순한 멘탈 모델을 유지할 수 있습니다. 중요한 부분은, PESPA가 페이지의 데이터를 최신 상태로 유지하기 위해 변경이 발생했을 때 데이터를 재검증(revalidate)하는 브라우저의 동작을 에뮬레이션한다는 것입니다. MPA에서는 전체 페이지 새로고침이 있었죠. PESPA에서는 이 재검증이 fetch 요청으로 이루어집니다.
PEMPA에서 우리가 겪었던 큰 문제 하나를 기억하시나요? 코드 중복입니다. PESPA는 백엔드 UI 코드와 프론트엔드 UI 코드를 완전히 동일하게 만들어 이 문제를 해결합니다. 서버에서 렌더링할 수도 있고 클라이언트에서 상호작용/업데이트를 처리할 수도 있는 UI 라이브러리를 사용하면, 코드 중복 문제가 사라집니다.
데이터 가져오기, 변경, 렌더링에 대한 작은 박스들이 보일 것입니다. 이 부분은 향상을 위한 코드입니다. 예를 들어 보류 상태, 낙관적 UI 등은 서버에 둘 자리가 없으니, 클라이언트에서만 실행되는 코드가 일부 필요합니다. 하지만 그럼에도, 현대 UI 라이브러리의 공존(colocation) 덕분에 충분히 감당 가능합니다.
PESPA의 문서 요청은 사실상 PEMPA와 동일합니다. 앱에 필요한 초기 HTML이 서버에서 바로 전송되고, 사용자 상호작용에 대한 경험을 향상시키기 위해 JavaScript도 함께 로드됩니다.
클라이언트 측 내비게이션: 사용자가 링크를 클릭하면 기본 동작을 막습니다. 라우터는 새 라우트에 필요한 데이터와 UI를 결정하고, 그 라우트가 필요로 하는 데이터를 가져오도록 트리거하며, 해당 라우트가 렌더링하는 UI를 렌더링합니다.
변경 요청(Mutation Requests): 두 다이어그램이 동일한 것 보이셨나요? 네! 우연이 아닙니다! PESPA에서 변경은 폼 제출을 통해 이루어집니다. 더 이상 onClick + fetch 같은 난센스는 없습니다(다만, 사용자의 세션이 만료되었을 때 로그인 화면으로 리다이렉트하는 것 같은 점진적 향상을 위한 명령형 변경은 괜찮습니다). 사용자가 폼을 제출하면 기본 동작을 막습니다. 우리의 변경 코드는 폼을 직렬화하여 폼의 action(기본값은 현재 URL)과 연관된 라우트로 요청을 보냅니다. 백엔드의 라우팅 로직은 액션 코드를 호출해 영속성 코드와 통신하여 업데이트를 수행하고, 성공 응답(예: 트윗 좋아요) 또는 리다이렉트(예: 새 GitHub 리포지토리 생성)로 응답합니다. 리다이렉트인 경우, 라우터는 해당 라우트의 코드/데이터/에셋을(병렬로) 로드한 후 렌더링 로직을 트리거합니다. 리다이렉트가 아닌 경우, 라우터는 현재 UI에 대한 데이터를 재검증하고 렌더링 로직을 트리거하여 UI를 업데이트합니다. 흥미롭게도, 인라인 변경이든 리다이렉트든 라우터가 관여하므로 두 유형의 변경에 대해 동일한 멘탈 모델을 제공합니다.
PESPA는 이전 아키텍처의 수많은 문제를 제거합니다. 하나씩 살펴보겠습니다:
MPA의 이슈:
PEMPA의 이슈:
SPA의 이슈:
PESPA는 클라이언트 측 JavaScript 유무에 따라 완전히 동일하게 동작하지는 않는다는 점을 명확히 해야 합니다. 어차피 그것이 점진적 향상의 목표가 아닙니다. 단지 JavaScript 없이도 앱의 대부분이 동작하면 됩니다. 그리고 이는 JavaScript 없는 사용자 경험만을 염두에 두어서가 아닙니다. 점진적 향상을 목표로 하면 UI 코드가 극적으로 단순해지기 때문입니다. JavaScript 없이도 얼마나 멀리 갈 수 있는지 놀라실 겁니다. 하지만 어떤 애플리케이션에서는 클라이언트 측 JavaScript 없이 모든 것이 동작하도록 하는 것이 필요 없거나 실용적이지 않을 수도 있습니다. 그래도 일부 UI 요소가 동작에 JavaScript를 필요로 하더라도, 우리는 PESPA의 주요 이점을 충분히 누릴 수 있습니다.
PESPA를 구분 짓는 특징:
단점에 대해서는 아직 발견해가는 중입니다. 다만 몇 가지 생각과 초기 반응을 공유합니다:
SPA와 SSG에 익숙한 많은 이들은 이제 서버 측 코드가 앱을 실행한다는 사실을 아쉬워합니다. 하지만 현실 세계의 앱에서는 서버 측 코드를 피할 수 없습니다. 전체 사이트를 한 번 빌드해 CDN에 올려둘 수 있는 몇몇 사용 사례가 있기는 하지만, 우리가 일상에서 다루는 대부분의 앱은 여기에 해당하지 않습니다.
이에 관련된 우려로 서버 비용 문제가 있습니다. SSG를 사용하면 앱을 한 번 빌드해 거의 무한한 사용자에게 매우 낮은 비용으로 CDN을 통해 제공할 수 있다는 생각입니다. 그러나 이 비판에는 두 가지 결함이 있습니다. 1) 어차피 앱에서 API를 호출하고 있을 가능성이 높으므로, 사용자는 방문할 때마다 여전히 서버 측의 가장 비싼 코드를 충분히 트리거합니다. 2) CDN은 HTTP 캐싱 메커니즘을 지원하므로, 정말로 SSG를 사용할 수 있다면 렌더링 서버가 처리할 작업량을 제한하면서도 빠른 응답을 제공하기 위해 이를 확실히 활용할 수 있습니다.
SPA를 떠나면서 흔히 제기되는 또 다른 문제는 이제 서버에서 렌더링하는 과제를 다루어야 한다는 점입니다. 클라이언트에서만 코드를 실행하는 데 익숙한 이들에게는 확실히 다른 모델이지만, 이를 충분히 고려해 만든 도구를 사용한다면 큰 도전이 아닙니다. 그렇지 않다면 분명 도전이 될 수 있지만, 마이그레이션하는 동안 특정 코드를 클라이언트 측에서만 실행하도록 강제하는 합리적인 우회책도 있습니다.
앞서 말했듯, 점진적 향상의 단일 페이지 앱의 단점은 아직 발견해가는 중이지만, 지금까지 파악되는 트레이드오프를 감안하더라도 이점이 그만한 가치가 있다고 생각합니다.
또한 PESPA 아키텍처의 역량은 기존 도구로도 꽤 오랫동안 가능했지만, 프로그레시브 인핸스먼트에 초점을 두면서 렌더링 로직 코드를 공유하는 접근은 새로운 흐름입니다. 이 글은 주로 플랫폼의 가능성 자체보다는 사실상의 표준 아키텍처를 보여주는 데 관심이 있습니다.
PESPA를 선도하는 것은 Remix입니다. 웹의 기초와 현대적 사용자 경험에 레이저 초점을 맞춘 웹 프레임워크죠. Remix는 제가 PESPA가 제공한다고 설명한 모든 것을 기본으로 제공하는 첫 번째 웹 프레임워크입니다. 다른 프레임워크들도 Remix의 리드를 따라 이를 도입할 수 있고 실제로 도입 중입니다. 제가 알기로 SvelteKit과 SolidStart가 PESPA 원칙을 구현에 반영하고 있습니다. 더 많은 프레임워크가 뒤따를 것이라 생각합니다(다시 말해, 메타 프레임워크는 꽤 오랫동안 PESPA 아키텍처를 구현할 수 있었지만, Remix가 이 아키텍처를 전면에 내세웠고 다른 이들이 그 뒤를 따르고 있습니다). PESPA에 웹 프레임워크를 도입하면 상황은 다음과 같습니다:
이 경우 Remix는 네트워크를 가로지르는 다리 역할을 합니다. Remix가 없다면 완전한 PESPA를 갖추기 위해 이를 우리가 직접 구현해야 했을 것입니다. Remix는 관례 기반과 설정 기반 라우팅을 결합해 라우팅을 처리합니다. 또한 데이터 가져오기와 변경(예: 트위터의 좋아요 버튼)과 같은 점진적 향상 부분과 보류 상태, 낙관적 UI 같은 UI 피드백 구현도 도와줍니다.
Remix에 내장된 중첩 라우팅 덕분에 코드 조직화도 더 좋아집니다(Next.js도 이를 추구하고 있습니다). 중첩 라우팅이 PESPA 아키텍처 자체에 필수는 아니지만, 라우트 기반 코드 스플리팅은 중요한 요소입니다. 또한 중첩 라우팅으로 훨씬 더 세밀한 코드 스플리팅을 얻을 수 있으니 중요한 측면입니다.
Remix는 PESPA 아키텍처로 더 재미있게, 더 나은 경험을 더 빠르게 만들 수 있음을 보여주고 있습니다. 그리고 우리는 다음과 같은 상황을 얻게 됩니다:
시도도 안 했는데 Lighthouse 성능 만점? 저도 참여하겠습니다!
개인적으로 저는 이 전환을 전적으로 환영합니다. UX와 DX를 동시에 개선한다는 것은 확실한 승리입니다. 이는 중요한 변화이며, 우리에게 다가올 미래가 기대됩니다. 이 글을 끝까지 읽으신 여러분을 위해, TodoMVC 앱을 사용해 시대에 따라 코드가 어떻게 이동하는지 보여주는 리포지토리를 준비했습니다! 여기에서 확인하세요: kentcdodds/the-webs-next-transformation. 이 아이디어들을 더 구체적으로 이해하는 데 도움이 되길 바랍니다.
그리고 이것이 바로 제가 EpicWeb.dev에서 여러분께 가르쳐드리고 싶은 내용입니다. 여기서의 제 진행 상황을 계속 따라오고 싶다면 아래 폼에 이메일을 남겨주세요. 함께 더 나은 웹을 만들어봅시다 🎉
감사합니다!
웹을 위한 빌드의 역사에 대해 더 자세히 보려면 Frontend Mastery의 “The new wave of Javascript web frameworks”를 읽어보세요.
프로그레시브 인핸스먼트에 대해 더 알고 싶다면 Jenna Smith의 Progressively enhance for a more resilient web을 읽어보세요.