화면에서 시작하지 마라.
경계에서 시작하라.
Do not start from screens. Start from boundaries.
React·Next.js·React Native에 공통으로 적용하는 프론트엔드 설계 규격. 화면을 먼저 그리는 대신 라우팅·상태·도메인·통합·실패·런타임의 경계를 먼저 정의하고, 그 결정에서 화면이 따라 나오게 한다. 원칙은 문서가 아니라 아키텍처 검증기로 강제된다.
Propositions
- 1
화면은 결과이고, 경계는 원인이다.
화면은 이미 다른 곳에서 내려진 결정들의 배열일 뿐이다 — 데이터가 어디서 오는지, 각 상태를 누가 소유하는지, 실패하면 무엇이 일어나는지. 그 결정을 화면 안에서 즉흥적으로 내리면 모든 화면이 그것을 다시 발명하고, 코드베이스는 표류한다.
- 2
좋은 아키텍처는 세 가지를 보장한다.
- · 모든 변경에는 예측 가능한 위치가 있다.
- · 모든 의존성에는 허가된 방향이 있다.
- · 모든 런타임 실패에는 사전 정의된 경계가 있다.
- 3
소스는 방향 있는 모듈 그래프다.
G = (V, E) V = 모듈의 집합 E = 방향 있는 import (A → B ≡ A imports B) 불변식 1 — 순환 없음 ∀ v ∈ V, 경로 v → … → v 는 존재하지 않는다. 불변식 2 — 계층 순서 L(module) ∈ ℕ A는 L(A) ≥ L(B) 일 때만 B를 import한다.순환은 “한 곳만 고치면 된다”는 성질을 파괴한다. 낮은 계층은 높은 계층에 의존하지 않는다. 두 불변식 모두
check:arch가 거부한다. - 4
화면 이전에 일곱 개의 경계를 정의한다.
- 01Routing / Navigation— 사용자가 위치 사이를 어떻게 이동하는가.
- 02State— 각 상태를 누가 소유하고, 어디에 사는가.
- 03Domain— UI와 무관한 비즈니스 개념은 무엇인가.
- 04UI— 도메인에 종속되지 않는 재사용 프리미티브.
- 05API / SDK Integration— 외부 데이터가 앱으로 들어오는 방식.
- 06Failure— 비동기 흐름이 성공하지 못했을 때 무엇이 일어나는가.
- 07Runtime / Platform— 네트워크·생명주기·플랫폼 같은 실행 조건.
- 5
하나의 원리, 세 런타임.
Template Runtime Main Boundary React Browser SPA State / Feature / API Next.js Server + Browser Route / Server-Client / Cache React Native iOS / Android Navigation / Native / Runtime - 6
검증기는 문서가 아니라 게이트다.
pnpm check:arch # forbidden imports · circular deps # env access · deep imports규칙은 의존성 매트릭스의 실행 가능한 형태다. 위반하면 빌드가 깨진다. 이것이 의견과 규격을 가른다.
Import Direction
import는 항상 아래로만 흐른다. 상위(application-specific) 계층은 하위 계층을 import할 수 있지만, 하위 계층은 상위를 절대 참조하지 않는다. shared는 도메인 코드를 모른다.
Specification
세 개의 독립 실행 가능한 스타터 템플릿과 아키텍처 검증기가 레포지토리에 공개되어 있다. 데모 도메인은 일부러 지루하게 두었다 — 주제는 기능이 아니라 경계이기 때문이다.