DEV Community 블로그 포스트 번역
2025-10-29
Vercel은 최근 플랫폼을 단순히 향상시키는 것을 넘어 JavaScript의 의미론 자체에 도전하고 프로그래밍의 새로운 시대를 엿볼 수 있게 해주는 기능들을 출시했습니다. 이러한 변화들이 논쟁을 불러일으켰지만, 더 광범위하고 야심 찬 비전을 암시하고 있습니다.
Vercel은 차세대 프로그래밍 언어가 이질적인 런타임, 투명한 네트워크, 다층 캐싱, 작업 내구성을 포함한 현대 애플리케이션의 복잡성을 기본적으로 관리해야 한다는 개념을 주장하고 있습니다.
이 글은 프로그래밍 언어가 로직뿐만 아니라 분산 시스템에서 데이터와 계산의 전체 생명주기를 관리하도록 진화하는 방식을 탐색합니다. 이러한 진화는 세 가지 핵심 언어 개념을 통해 조용히 프로토타입화되고 있습니다: 직렬화 가능한 클로저(serializable closures), 대수적 효과(algebraic effects), 그리고 증분 계산(incremental computation).
Vercel의 분산 세계를 위한 새로운 기본 요소
이 미래를 이해하기 위해 먼저 Vercel이 오늘날 해결하고 있는 문제들을 살펴봐야 합니다. 현대 웹 애플리케이션은 다음과 같은 특징을 가지며 점점 더 복잡해지고 있습니다:
- 다중 런타임: 코드는 클라이언트(브라우저), 서버(Node.js), 엣지(WebAssembly)에서 실행됩니다.
- 분산된 데이터: 상태는 메모리, CDN, 데이터베이스, 파일 스토리지에 걸쳐 존재합니다.
이러한 복잡성을 관리하기 위해 Vercel은 React 팀과 함께 라이브러리 추가보다는 새로운 언어 구성처럼 느껴지는 강력한 새로운 기능들을 도입했습니다.
Server Actions: 클라이언트와 서버 로직 통합
Server Actions를 사용하면 클라이언트 측 컴포넌트가 서버에서 실행되는 비동기 함수를 직접 호출할 수 있으므로, 클라이언트와 서버 코드 간의 경계를 효과적으로 제거합니다.
Server Actions가 없다면, 이는 API 엔드포인트를 수동으로 설정하고, fetch 요청을 작성하고, 데이터 직렬화 및 역직렬화를 처리해야 합니다. Server Actions는 이 모든 것을 추상화하여 원격 프로시저 호출(RPC)을 단순한 함수 호출처럼 느껴지게 합니다.
'use cache' 지시문: 언어 수준의 캐싱
'use cache' 지시문은 함수를 메모이제이션하고 그 결과를 캐싱하기 위한 강력한 도구입니다. 캐시 키는 함수의 인자와 그 클로저 값(주변 범위에서 "기억"하는 변수)으로부터 자동으로 생성됩니다.
이것은 진정한 언어 수준의 기능입니다. 함수의 클로저를 검사해야 하기 때문에, 개발자가 모든 의존성을 수동으로 선언하도록 강제하지 않고는 단순한 라이브러리 API로 구현할 수 없습니다.
'use workflow' 지시문: 내구성 있는 재개 가능한 함수
비동기 작업을 안정적으로 만드는 것은 일반적으로 메시지 큐, 재시도 로직, 지속성 계층의 복잡한 스택이 필요합니다. 'use workflow' 지시문은 내구성을 기본 언어 개념으로 만드는 것을 목표로 합니다.
워크플로우는 재시작, 실패 또는 긴 일시 중지 중에 실행 상태를 유지할 수 있는 함수입니다. 초 단위든 몇 개월이든 정확히 중단된 지점에서 재개할 수 있습니다.
'use workflow'를 통해 언어에 내구성을 내장함으로써 엄청난 인프라 복잡성을 추상화합니다.
프로그래밍 언어의 역사적 궤적
이러한 JavaScript 변화에 대해 불안감을 느낄 수 있습니다. 결국 이들은 언어의 의미론을 상당히 변경합니다.
그러나 프로그래밍 언어의 역사를 살펴보면, 증가하는 복잡성을 관리하기 위한 일관된 진화 패턴을 볼 수 있습니다.
프로그래밍 언어는 항상 새로운 추상화 계층과 복잡성을 관리하기 위해 진화해왔습니다:
- Assembly는 원시 CPU 명령어를 관리했습니다.
- Go는 멀티코어 프로세서를 위한 동시성을 단순화했습니다.
이 진화의 다음 논리적 단계는 데이터 관리의 복잡성을 관리하는 것입니다. 더 이상 메모리나 스레드 관리만이 아니라, 계산이 어디서 발생하는지, 데이터가 어떻게 이동하는지, 접근이 빠르고 지속적이며 안정적인지 확인하는 것이 문제입니다.
현재 이러한 문제들은 프레임워크, 라이브러리, 외부 시스템으로 해결됩니다. 개발자는 직렬화, RPC, 캐싱 전략, 메시지 큐에 대한 깊은 이해가 필요합니다. Vercel의 새로운 기능들은 이러한 것들이 언어 자체의 관심사가 되는 미래를 시사합니다.
이 비전을 구동하는 언어 기능
Vercel의 새로운 지시문들(Directives)은 JavaScript의 의미론을 변경하기 때문에 논쟁의 여지가 있습니다. 대신 다른 관점에서 보면, 새로운 종류의 프로그래밍 언어의 기초를 형성할 수 있는 Computer Science의 강력한 개념들 위에 구축될 수 있습니다.
직렬화 가능한 클로저
클로저는 생성된 환경을 "기억"하는 함수입니다. 직렬화 가능한 클로저는 패키징될 수 있는 것입니다. 즉, 코드와 기억된 환경을 네트워크를 통해 전송하거나, 데이터베이스에 저장하거나, 나중에 실행할 수 있습니다. 이는 효과적으로 데이터뿐만 아니라 계산을 시스템 경계를 넘어 이동할 수 있게 합니다.
- Server Actions는 주요 예입니다.
createNote 함수는 직렬화되어 클라이언트에 참조로 전송되고, 호출될 때 실행이 서버에서 트리거됩니다.
- 'use cache'는 직렬화에 의존하여 고유한 캐시 키를 생성합니다. 함수의 코드, 클로저 값, 인자가 함께 해시됩니다.
- 워크플로우는 각
await 지점에서 일시 중지되는 직렬화 가능한 클로저로 볼 수 있습니다. 함수의 상태와 그 연속(함수의 "나머지")이 직렬화되고 지속되어 나중에 재개될 준비가 됩니다.
예를 들어, aiAgentWorkflow 함수는 각 단계에서 직렬화된 클로저의 시리즈로 시각화될 수 있습니다:
대수적 효과
직렬화 가능한 클로저는 강력하지만, 중요한 문제를 야기합니다: 다른 환경에서 코드 조각을 안전하게 실행하려면 어떻게 해야 할까요? 서버에서 실행되도록 설계된 함수는 브라우저로 이동되면 데이터베이스에 접근할 수 없습니다.
여기서 대수적 효과가 등장합니다. 대수적 효과는 함수가 무엇을 하는지(데이터베이스 접근이나 난수 생성과 같은 부작용)를 그 효과가 어떻게 구현되는지로부터 분리하는 프로그래밍 언어 기능입니다.
"효과"가 수행되고, 호출 스택 어딘가의 "효과 핸들러"가 이를 해석하는 방법을 결정합니다.
'use workflow' 환경은 완벽한 예입니다. Math.random과 Date.now 같은 API는 결정론적으로 동작해야 합니다. 효과 핸들러는 Date.now 호출을 가로채서 시스템 시간을 반환하는 대신 워크플로우의 이벤트 로그에서 타임스탬프를 반환하여 재생 가능성을 보장할 수 있습니다.
일급 효과를 가진 가상의 언어의 또 다른 예로, 클라이언트와 서버 컨텍스트에 대해 다른 핸들러를 정의할 수 있습니다:
이는 이동 가능한 클로저가 접근할 수 있는 리소스를 제어하는 안전하고 신뢰할 수 있는 방법을 제공합니다.
이 개념은 JavaScript 세계에 새로운 것이 아닙니다. Effect와 같은 라이브러리와 Koka와 같은 언어들은 수년 동안 대수적 효과를 탐색해왔습니다. 하지만 효과를 사용하여 다양한 실행 환경과 리소스 접근을 관리하는 것은 이 개념의 새롭고 강력한 응용입니다. 증분 계산
분산 시스템에서 캐싱은 단순한 최적화가 아니라 성능을 위해 필수적입니다. 증분 계산은 모든 것을 처음부터 다시 계산하는 대신 데이터 변경의 영향을 받는 출력만 다시 계산하는 원칙입니다.
이 개념은 이미 널리 퍼져 있습니다:
- React의 Virtual DOM diffing은 증분 계산의 한 형태입니다.
- 메모이제이션과
'use cache' 같은 지시문은 명시적인 형태입니다.
- Turbopack과 Bazel 같은 빌드 시스템은 변경되지 않은 코드를 다시 빌드하지 않기 위해 이를 사용합니다.
증분 계산을 일급 언어 개념으로 만들면, 미래의 언어는 다양한 렌더링 전략(CSR, SSR, SSG, ISR), 빌드 시스템, 데이터 계층에 걸쳐 캐싱과 데이터 의존성을 자동으로 관리하여 효율성을 극적으로 향상시킬 수 있습니다.
실제로 "use cache"는 증분 계산의 단순한 형태로 볼 수 있습니다. 더 고급 시스템은 더 세밀한 수준에서 의존성을 추적하여 일부 데이터만 변경될 때 부분 재계산을 허용할 수 있습니다. 이 개념은 JavaScript 세계에서 skiplabs와 Skip langs와 같은 프로젝트로 탐색되었습니다. "Vercel Lang"의 새벽?
Vercel은 단순히 플랫폼을 구축하는 것이 아니라 강력한 프로그래밍 모델을 개발자 경험에 직접 내장하고 있습니다. 분산 시스템을 위한 언어 수준의 구성을 도입함으로써, 개발자가 구축할 수 있는 것과 얼마나 쉽게 구축할 수 있는지의 경계를 밀어붙이고 있습니다.
이것이 좋은 일일까요? 논쟁은 계속되고 있지만, 방향은 명확합니다. 이 패러다임은 더욱 밀어붙여질 수 있습니다. 다음과 같은 언어를 상상해보세요:
오류 모니터링이 플랫폼에 의해 관리됩니다. 함수는 잠재적 오류를 선언할 수 있고, 언어와 플랫폼은 자동으로 모니터링과 경고를 제공할 수 있습니다.
데이터 프라이버시와 보안이 컴파일러에 의해 강제됩니다. 효과 시스템을 통해 데이터 흐름을 추적함으로써, 언어는 접근 제어를 강제하고 민감한 데이터 유출을 방지할 수 있습니다.
Observability가 내장됩니다. 효과 시스템은 데이터베이스와 같은 리소스에 대한 접근을 관리하여 수동 계측 없이 성능에 대한 깊은 통찰력을 제공할 수 있습니다.
차세대 프로그래밍 언어 자체가 현대 애플리케이션의 분산 특성을 이해하고 관리하여, 개발자가 인프라가 아닌 로직에 집중할 수 있게 합니다.