List 디자인 시스템은 왜 자유도를 제한해야 했을까

오픈소스 컴포넌트와 사내 컴포넌트가 다른 답을 고르는 이유
List란 무엇인가
이 시리즈에서 말하는 List는 <ul>이나 <ol> 같은 특정 태그도, 배열 하나를 그대로 화면에 매핑한 결과도 아니다. 같은 규칙을 따르는 행이 여러 개 반복되는 화면을 가리키며, 행 하나의 형태와 동작뿐 아니라 행과 행 사이의 관계, 목록 전체가 지켜야 할 규칙까지 함께 다뤄야 하는 UI 패턴이다. 화면만 보면 비슷한 행이 반복되는 단순한 구조로 보이지만, 그 규칙을 코드로 옮기기 시작하면 판단할 것이 하나둘이 아니었다.
컴포넌트를 잘못 쓰면 대개 티가 난다. 빌드가 깨지거나 런타임 예외가 발생하면 누구든 원인을 찾으러 간다.
찾기 어려운 것은 멀쩡하게 렌더링되는 잘못된 화면이다. 코드만 봐서는 이상이 없고, Figma와 나란히 놓고 비교하거나 QA를 거쳐야 비로소 어긋남이 보인다.
내가 List 디자인 시스템 구현을 맡았을 때도 이 문제가 반복되고 있었다. 디자인 시스템에 처음 기여한 업무이기도 했다.
제품 화면 하나를 구현할 때와 달리, 이 컴포넌트는 웹 개발자인 내가 iOS와 Android 개발자들과 함께 만들어야 했다. 플랫폼마다 구현 방식은 달랐지만, 무엇을 같은 List로 볼 것인지와 어떤 결정을 공통 규칙으로 둘 것인지는 세 플랫폼이 함께 논의해야 했다. 낯설었지만 그만큼 재미있었다. 디자인 시스템은 공통 컴포넌트를 공급하는 데서 끝나지 않았다. 여러 팀과 플랫폼이 같은 결정을 반복하지 않도록 함께 지킬 기준을 정하는 일이기도 했다.
이 시리즈에 나오는 컴포넌트와 prop 이름은 설명을 위해 일반화했다. 실제 사내 이름과는 다르지만, 시리즈 전체에서 처음부터 끝까지 같은 이름을 사용한다.
한 가지 더 미리 밝혀둔다. 이 시리즈는 당시 구현을 시간순으로 복기한 기록이 아니다. 그때 실제로 마주친 요구와 고민에서 출발하되, 지금 다시 설계한다면 무엇을 어떤 기준으로 판단할지를 따라간다. 당시의 결정과 글을 쓰며 새로 확인한 내용이 섞일 수 있는 지점에서는 그때와 지금을 구분해 적었다.
같은 List인데 화면마다 다르게 구현돼 있었다
먼저 한 일은 마이그레이션 대상을 세는 것이었다. 공통 List로 옮길 수 있는 화면이 수십 개였다.
그 과정에서 수십 개의 화면이 서로 얼마나 다른지도 함께 보였다. 여러 팀이 같은 Figma를 보고 있었지만, 실제 List는 화면마다 따로 만들어져 있었다. 간격과 타이포그래피가 조금씩 달랐고, 상태와 긴 텍스트를 처리하는 방식도 구현한 사람에 따라 달랐다.
어긋남은 대체로 이런 모습이었다.
- 정해진 크기보다 큰 아이콘이 들어갔지만 화면은 그럭저럭 그럴듯해 보이는 경우
- 특정 형태에서만 승인된
count가 다른 List에도 노출되는 경우 - 우측에 화살표가 있어 누를 수 있을 것처럼 보이지만 실제 동작은 없는 경우
- 디자인이 승인하지 않은 버튼과 배지 조합이 한 행에 함께 놓인 경우
- 좁은 영역에서 중요한 정보가 잘리지만 컴포넌트는 정상적으로 렌더링되는 경우
이런 화면은 아무 신호도 보내지 않는다. 빌드는 통과하고 런타임에도 아무 일이 없다. 디자인을 아는 사람이 코드 리뷰나 QA에서 발견할 수는 있지만, 그건 매번 눈으로 대조해야 한다는 뜻이다. 대조가 빠진 화면은 그대로 나간다. 새 화면을 만드는 사람은 기존 구현 중 가장 비슷한 것을 찾아 복사한 뒤, 디자인과 맞는지 다시 눈으로 확인하고 있었다.
문제는 복사 자체보다 복사할 원본이 여러 개인데 무엇이 정본인지 표시돼 있지 않다는 데 있었다. 어느 화면의 List가 최신 디자인을 반영했는지 코드만 봐서는 알 수 없었다. 조금 어긋난 구현이 다음 화면의 출발점이 되고, 그 화면은 다시 다음 복사의 원본이 됐다. 어긋남 대부분은 누군가 대충 만들어서 생겼다기보다 이런 과정에서 누적된 것에 가까웠다.
수십 개 화면이 하나의 컴포넌트를 공유하지 않는다는 사실만 보면 답은 간단해 보인다. 공통 컴포넌트를 만들면 된다.
하지만 무엇이든 넣을 수 있는 List 하나를 만들어 수십 개 화면이 함께 쓰게 해도 앞의 문제는 그대로 남는다. 큰 아이콘도, 디자인이 승인하지 않은 버튼과 배지 조합도 여전히 만들 수 있다. 무엇이 올바른지는 화면마다 다시 판단해야 한다. 재사용은 코드 중복을 줄이지만 디자인 해석의 중복까지 줄여주지는 않는다.
한 가지 더 짚어둘 점이 있다. 이 화면들을 만든 사람들이 디자인을 보지 않은 것은 아니다. 모두 같은 Figma를 보고 있었다.
Figma에 담긴 것은 디자인팀이 정리한 결과였다. 어떤 표현이 승인됐고 어떤 표현이 승인되지 않았는지도 시각적으로는 분명했다. 그러나 디자인이 정해져 있다는 것과, 그 결과를 코드에서 어떤 단위로 나누고 무엇을 어느 쪽이 결정할지까지 정해져 있다는 것은 별개의 문제다.
Figma에 그런 정보를 적을 수 없다는 뜻은 아니다. Dev Mode의 annotation은 코드가 없어도 개발, 상호작용, 접근성 맥락을 화면 옆에 남길 수 있게 한다. Code Connect는 디자인 컴포넌트를 실제 코드 컴포넌트와 prop에 연결한다. 다만 어느 쪽도 어떤 조합을 공개 API로 허용할지, 각 결정을 제품 코드와 디자인 시스템 중 어디에 둘지를 대신 정해주지는 않는다. annotation은 팀이 이미 내린 결정을 기록하는 자리이고, Code Connect는 그 결정이 코드에 있을 때 양쪽을 잇는다. 시각적 결과만으로는 무엇이 행의 책임이고 무엇이 목록의 책임인지, 금지된 조합을 어디에서 막을지 하나로 정해지지 않는다.
무엇을 만들지 정하기 전에 조건이 먼저 있었다
설계를 시작할 때 이미 주어져 있던 것은 넷이었다.
- Web · iOS · Android 세 플랫폼이 같은 List 개념을 공유해야 했다.
- 디자인팀이 구현에 앞서 Figma에 유즈케이스와 Do/Don’t를 정리해둔 상태였다.
- 마이그레이션 대상은 수십 개 화면이었고, 기존 구현은 화면마다 달랐다.
- 디자인 시스템은 컴포넌트를 공급하고, 여러 제품 개발자가 이를 사용했다.
디자인 시스템이 제공해야 할 것은 List를 그리는 코드만이 아니었다. Figma에 정리된 조합을 제품 코드가 어떻게 선택하고, 승인하지 않은 조합을 어디에서 막을지까지 공개 API의 계약으로 옮겨야 했다.
이 가운데 무엇이 자유도를 제한하는 판단에 직접 작용했는지는 뒤에서 다시 살펴본다.
오픈소스 컴포넌트는 쓰일 제품을 모른 채 설계된다
그렇다면 MUI나 Ant Design, Radix처럼 널리 쓰이는 라이브러리는 왜 소비자에게 더 많은 선택을 맡길까?
MUI에는 인스턴스마다 스타일을 덮어쓰는 sx prop이 있고, 테마에서 컴포넌트별로 기본 prop과 스타일, variant 규칙을 한꺼번에 바꿀 수도 있다.

Ant Design은 전역 토큰과 컴포넌트별 토큰을 설정할 수 있게 하고, 토큰을 파생시키는 알고리즘까지 바꿀 수 있게 한다. seed 토큰 하나를 바꾸면 알고리즘이 파생 토큰을 다시 계산하고, 그 결과가 컴포넌트까지 내려간다.

컴포넌트 하나만 따로 조정할 수도 있다. algorithm 옵션을 켜면 그 컴포넌트에 넘긴 색이 seed처럼 취급돼 파생 토큰까지 다시 계산되고, 켜지 않으면 전역 토큰을 덮어쓰기만 한다.
Radix 같은 headless 라이브러리는 다른 방식을 택한다. 스타일을 아예 제공하지 않는다. 접근성 속성과 포커스 관리, 키보드 내비게이션, 열림과 닫힘 같은 상태 배선처럼 구현하기 까다로운 부분을 맡고, 어떻게 보일지는 통째로 위임한다. asChild를 사용하면 라이브러리가 렌더할 요소를 내가 넘긴 자식으로 바꿀 수도 있다.

한쪽은 기본 스타일을 제공하면서 소비자가 조정할 수 있게 하고, 다른 쪽은 시각 표현 자체를 소비자에게 맡긴다. 두 방식이 마주한 조건은 같다.
이 컴포넌트를 쓸 제품의 디자인을 우리가 모른다.
쓰일 제품을 모르면 그 제품에 맞는 조합을 완결된 목록으로 정할 수 없다. 어떤 조합이 옳은지 정하려면 어떤 브랜드의 어떤 화면인지 알아야 하지만, 배포한 순간부터 그것은 알 수 없는 값이 된다. 그래서 설계는 크게 두 방향으로 갈린다. 기본 디자인을 제공하되 제품에 맞게 고칠 통로를 넓게 두거나, 시각 표현을 비워두고 조합과 스타일을 소비자에게 맡기는 것이다. 물론 그 사이에도 여러 지점이 있다. 정해진 선택지를 제공하면서 별도의 조정 수단은 좁게 두는 방식도 가능하다.
이 자리에서 조합을 제한하는 것은 미덕이 아니라 결함이다. 소비자가 조정할 수 있는 범위가 좁을수록 그 라이브러리를 쓸 수 있는 제품도 줄어든다. 제품과 브랜드를 미리 확정할 수 없는 자리에서는 자유도가 이 라이브러리를 채택할 수 있는 제품의 범위를 넓힌다.
물론 대가가 없는 것은 아니다. 소비자가 조정할 수 있는 범위가 넓을수록 문서는 두꺼워지고, 어떤 조합이 정상적으로 동작하는지 라이브러리가 보증하기 어려워진다. 내부 구조를 조금만 바꿔도 누군가 덮어쓴 스타일이 깨질 수 있다. 그 비용을 감수하는 이유는 쓸 제품을 모른다는 조건에서는 그편이 더 싸기 때문이다.
다만 이런 라이브러리도 모든 결정을 소비자에게 맡기지는 않는다. headless 라이브러리에서 특히 분명하게 드러난다. 시각 표현은 거의 전부 소비자에게 맡기지만, 키보드 상호작용과 포커스 관리, 접근성 시맨틱은 primitive가 책임진다. asChild로 렌더할 요소를 바꿀 수는 있어도, 요소를 바꾼 뒤 접근 가능하고 동작하게 유지할 책임은 소비자에게 있다. 무엇을 제한할지 정하는 일은 어느 자리에서나 일어난다. 자리에 따라 제한하는 대상이 다를 뿐이다.
사내 컴포넌트는 쓰일 제품과 팀을 알고 있다
내가 있던 자리에서는 두 가지 조건이 특히 달랐다.
하나는 이 컴포넌트가 쓰일 제품과 그것을 만드는 팀을 안다는 점이다. 쓰이는 화면은 같은 앱 안에 있고, 사용하는 사람은 같은 회사의 제품 개발자다. 단순히 명단을 뽑을 수 있다는 사실보다 중요한 것은 그다음이다. 요구를 모아 조율할 통로가 있고, 디자인 규칙을 바꿀 주체가 같은 회사 안에 있다.
다른 하나는 따라야 할 조합이 이미 정해져 있다는 점이다. 디자인팀이 Figma에 어떤 형태를 쓰고 쓰지 않는지 구현 전에 정리해둔 상태였다.
두 조건은 붙어 다니는 것처럼 보이지만 서로 별개다. 회사 밖으로 공개 배포되는 디자인 시스템을 떠올리면 차이가 드러난다. 그런 시스템에도 정해진 조합은 분명히 있다. 브랜드와 스펙 문서도 존재한다. 하지만 그것을 가져다 쓸 제품이 무엇인지는 알 수 없다. 예상하지 못한 요구가 들어올 가능성이 크고, 그때 조정할 방법이 없으면 우회 구현이 생기거나 채택 자체가 늦어진다. 정해진 조합이 있어도 별도의 조정 수단을 함께 제공하는 이유다.
두 조건을 축으로 놓으면, 같은 List 컴포넌트라도 어디에 놓이느냐에 따라 무엇을 최적화해야 하는지가 갈린다.
세로축을 읽을 때 주의할 점이 하나 있다. 어떤 조합이 어딘가에 정의돼 있는지가 아니라, 그 조합이 사용하는 쪽에 적용되는 규범인지를 묻는 축이다. MUI는 Material이라는 스펙을 구현하지만 소비자에게 그 스펙을 지키라고 요구하지 않는다. 테마와 sx로 바꿀 수 있게 한다. 그래서 스펙이 있는데도 아래쪽에 놓인다.
물론 이 두 축만으로 세상의 모든 컴포넌트를 분류할 수는 없다. 소비자의 수와 이질성, 요구가 바뀌는 주기, 예외를 검토하고 반영하는 속도 같은 조건도 판단에 함께 작용한다. 여기서는 우리가 왜 오른쪽 위에 있었는지를 설명하는 데 필요한 두 축만 골랐다.
우리가 놓인 자리는 오른쪽 위였다. 쓰일 제품을 알고, 따라야 할 조합도 이미 정해져 있었다. 이 자리에서는 불필요한 선택지를 제공하는 것 역시 비용이 된다.
prop 하나가 판단을 호출부로 넘긴다
조정 가능한 prop이 호출부에 무엇을 요구하는지 보면 그 이유가 분명해진다. 행 하나에는 다음과 같은 prop이 열려 있었다.
type ListRowProps = {
label: string;
description?: string;
count?: number;
countColor?: string;
leadingIcon?: string;
leadingSize?: number;
};호출부는 이렇게 쓸 수 있다.
<ListRow
label="신용대출"
count={3}
countColor="red"
leadingIcon="user"
leadingSize={40}
/>정상적으로 컴파일되고 화면에도 잘 나온다. 하지만 이 코드를 쓰는 사람은 데이터를 넣는 동시에 두 가지 디자인 결정을 내렸다. count를 어떤 색으로 보여줄지, 좌측 아이콘을 몇 픽셀로 그릴지 결정한 것이다.
둘 다 화면마다 다시 판단할 일이 아니다. count의 강조 색은 Figma에 하나로 정해져 있고, 아이콘 크기도 마찬가지다. 그런데 API가 물어보니 호출부는 답해야 하고, 그 답이 화면 수만큼 쌓인다.
비용은 처음 사용할 때보다 나중에 생긴다. 디자인에서 count의 강조 색을 바꾸면 중앙 정의 하나가 아니라 값을 넘긴 모든 호출부와 그 위에 덧씌운 래퍼를 수정해야 한다. 검색으로 후보를 모을 수는 있어도 어느 화면이 어떤 값을 넘겼는지는 결국 하나씩 확인해야 한다. 같은 List 안에서 아이콘 크기가 서로 다른 화면이 몇 개인지 파악할 때도 마찬가지다.
같은 prop도 배포하는 쪽이 어디에 있느냐에 따라 평가가 뒤집힌다. 범용 라이브러리에서 countColor를 공개 prop으로 제공하는 것은 자연스러운 선택이다. 그 색을 정할 정보가 없으니 호출부에 묻는 것 말고는 방법이 없다. 반면 우리는 그 정보를 갖고 있었다. 색은 Figma에 정해져 있었고, 우리는 그 사실을 알면서도 호출부에 다시 묻는 API를 만들고 있었다.
이런 prop은 제품 개발자에게 선택지를 준 것처럼 보인다. 실제로는 같은 결정을 화면 수만큼 반복하게 만든다. countColor="red"와 leadingSize={40}은 API를 유연해 보이게 하지만, Figma의 결정이 제품 코드로 새어나가는 통로이기도 하다.
제한의 목적은 호출부의 자유나 prop의 개수를 줄이는 데 있지 않았다. 화면만 아는 값과 동작은 그대로 공개해야 한다. 걷어내야 할 것은 시스템이 이미 답을 갖고 있는데도 호출부에 다시 묻는 prop이었다.
그래서 목표를 이렇게 잡았다.
디자인팀이 정한 정보 구조와 행동만 제품 코드에서 표현할 수 있게 만들고, 새로운 조합을 설계할 책임은 디자인 시스템 안에 남긴다.
이 목표를 이루면 수십 개 화면이 같은 코드를 쓰는 결과는 자연스럽게 따라온다. 실제로 풀려던 문제는 그 수십 개 화면이 디자인 시스템에서 지원하지 않는 조합을 아무 저항 없이 만들 수 있다는 데 있었다. 목표를 재사용에 두면 무엇이든 넣을 수 있는 컴포넌트 하나만으로도 문제가 해결된 것처럼 보인다.
그렇다고 항상 제한하는 것이 답은 아니다
이 목표가 언제나 옳은 것은 아니다.
앞의 조건 목록을 다시 읽어보면 유독 무겁게 작용한 항목이 보인다. 디자인이 먼저 정리돼 있었고, 옮길 화면이 이미 수십 개 쌓여 있었으며, 컴포넌트를 공급하는 쪽과 사용하는 쪽이 나뉘어 있었다. 이 세 조건이 함께 있으면 같은 형태가 여러 번 반복된다. 그리고 우리가 있던 자리에서는 요구 자체가 자주 바뀌지 않아서, 한 번 반복된 형태가 당분간 유지될 것이라고 볼 수 있었다. 그 결과 화면마다 판단을 반복하는 비용이 시스템 안에서 형태를 바꾸는 비용보다 커졌다.
같은 회사 안에도 이 조건이 성립하지 않는 자리가 있다. 아직 무엇을 만들지 모르는 신규 실험이 그렇다. 화면이 매주 바뀌고, 이번 주에 만든 형태가 다음 주에 사라지며, 디자인과 개발이 바로 옆에서 그때그때 결정을 내린다. 반복해서 사용할 조합 자체가 아직 정해지지 않았다.
그 자리에서 같은 방식으로 자유도를 제한하면 어떤 일이 생길지는 어렵지 않게 그려진다. 새 형태가 필요할 때마다 디자인 시스템에 요청해 검토를 거치고 배포를 기다려야 한다. 실험의 속도를 결정하는 주체가 실험하는 팀에서 컴포넌트를 공급하는 팀으로 넘어간다. 요구가 이렇게 빠르게 바뀌는 자리에서는 제한이 지우는 승인·배포 비용이 선택지를 넓게 제공하는 비용보다 커질 수 있다.
제한한다고 비용이 사라지는 것도 아니다. 화면마다 반복되던 판단이 디자인 시스템의 승인과 배포 비용으로 옮겨갈 뿐이다. 어느 쪽이 더 싼지는 판단이 몇 번 반복되는지, 새로운 형태를 얼마나 자주 추가해야 하는지에 달려 있다.
제한이라는 선택을 정당하게 만든 것은 원칙이 아니라 조건의 조합이었다. 디자인이 선행하고, 쓰일 제품이 알려져 있으며, 같은 형태가 수십 번 반복되고, 그 형태가 당분간 유지될 것. 이 가운데 몇 가지가 무너졌다면 나도 다른 답을 골랐을 것이다.
이 시리즈는 제한하는 편이 좋다고 논증하려는 글이 아니다. 주어진 조건에서 무엇을 어디까지 제한했고, 그 선택으로 무엇을 잃었는지를 적는 글이다.
행의 규칙과 목록의 규칙이 섞여 있었다
무엇을 제한할지 정하려고 Figma의 요구사항을 다시 읽다가 한 가지가 눈에 걸렸다. 모두 List에 관한 요구였지만 적용되는 범위는 같지 않았다.
어떤 것은 행 하나에 대한 요구였다.
- 좌측 아이콘은 정해진 크기로만 들어간다
count가 붙는 형태에서는label의 굵기가 달라진다description은 최대 몇 줄까지 보여준다- 우측에 화살표가 있으면 그 행은 눌렀을 때 어딘가로 이동한다
반면 어떤 것은 행 하나만 봐서는 판단할 수 없는 요구였다.
- 행과 행 사이 구분선은 좌측 아이콘 폭만큼 들여쓴다
- 마지막 행 아래에는 구분선을 두지 않는다
- 목록 전체가 하나의 카드로 묶이는 형태가 따로 있다
- 한 목록 안에서는 행 형태가 섞이지 않는다
- 항목이 하나도 없을 때 자리를 대신하는 화면이 있다
Figma 문서에서는 행의 규칙과 목록의 규칙이 구분 없이 섞여 있었다. 이상한 일은 아니다. 디자인은 완성된 화면을 그리고, 그 화면에서는 두 범위의 규칙이 한 장에 함께 보인다. 구분선 하나만 봐도 색과 두께는 행 옆에 적혀 있지만, 어디에 있고 어디에 없는지는 화면 전체를 봐야 알 수 있다.
구현에서는 각 규칙을 판단할 주체를 나눠야 했다. 마지막 행 아래의 구분선을 지우려면 자신이 마지막인지 알아야 하지만, 행 하나만으로는 그 사실을 알 수 없다. 행에 정보를 넘겨줄 수도 있고 CSS로 마지막 자식만 선택할 수도 있다. 어느 쪽이든 순서를 아는 정보는 목록 전체를 보고 있는 쪽에 있다.
처음 읽을 때 이 구분이 잘 보이지 않았던 이유도 같다. 적용 범위가 다른 규칙이 한 장에 그려져 있으면 모두 List 요구사항 하나로 읽힌다. 이를 나눠야겠다는 생각은 행 하나를 실제 코드로 옮기기 시작한 뒤에 들었다.
여기서는 요구사항의 범위가 행과 목록으로 나뉜다는 사실까지만 적어둔다. 각 규칙을 누가 소유할지는 행 하나를 정한 뒤, 여러 행이 모인 목록을 다룰 때 다시 꺼낸다.
제품 코드는 선택하고, 디자인 시스템은 조합한다
자유도를 제한하기로 했다고 해서 조합의 자유 자체가 사라져서는 안 된다. 디자인 시스템이 지원하는 형태는 앞으로도 늘어날 텐데, 새로운 형태를 만들 방법이 어디에도 없다면 몇 달 안에 요청이 쌓이고 결국 누군가 우회 구현을 만들게 된다.
그래서 구현의 역할을 나눴다. 제품 코드에 공개하는 API에서는 디자인 시스템이 지원하는 조합만 선택할 수 있게 하고, 디자인 시스템 내부에는 새로운 조합을 만들 수 있는 구성 요소를 남겼다. 제품 개발자는 지원되는 형태 하나를 골라 화면만 아는 값과 동작을 넘긴다. 새로운 조합을 만드는 일은 디자인 시스템 안에서 일어난다.
공개 API에는 입력의 제약을 두고, 조합의 자유는 내부 구현에 남긴 셈이다.
이 구조가 실제로 어떤 API가 되는지, 그리고 왜 하나의 형태로 둘을 모두 충족하기 어려운지는 여기서 답하지 않는다. 2막에서 같은 행 하나를 세 가지 API로 만들어 비교한다.
문제는 재사용이 아니라 결정의 자리였다
처음에는 수십 개 화면에서 List를 어떻게 재사용할지가 문제로 보였다. 그러나 조건을 늘어놓고 우리가 선 자리를 확인하자 질문이 달라졌다.
제품 개발자가 내려야 할 결정과 디자인 시스템이 소유해야 할 결정을 어떻게 구분할 것인가.
이 글에서 내린 첫 번째 답은 조건에 따라 경계가 달라진다는 것이다. 쓰일 제품과 팀을 알고 있고 정해진 조합이 반복되는 자리라면, 화면만 아는 값과 동작은 제품 코드가 정하되 이미 내려진 디자인 결정은 디자인 시스템 안에 남겨야 한다. 반대로 반복해서 사용할 조합이 아직 정해지지 않았거나 요구가 빠르게 바뀌는 자리라면 제품 코드가 선택할 수 있는 범위를 넓히는 편이 낫다.
countColor와 leadingSize, 행과 목록이 각각 무엇을 아는지는 모두 이 질문의 다른 얼굴이다. 이어지는 글에서는 이 경계를 정할 기준을 만들고, 그 기준이 통하지 않는 지점에서 고친 뒤 다시 적용해본다.
시리즈는 네 막으로 나뉜다. 1막에서는 무엇을 제한할지 정하고, 2막에서는 행 하나를 제한하며, 3막에서는 여러 행이 모인 목록을 제한한다. 앞에서 구분한 행의 규칙과 목록의 규칙은 3막에서 다시 정리한다. 4막에서는 그렇게 정한 계약이 플랫폼, 환경, 운영, 패키지, 렌더링 전략, 서버와 클라이언트라는 여섯 경계와 부딪히는 과정을 다룬다. 기준은 그 과정에서 수정되고 구체화된다.
다음 글에서는 이 질문을 행 하나에 적용한다. Figma에서 하나의 완성된 화면으로 보이던 행을 코드에서는 어떤 자리로 나눌지 살펴보고, 각 자리에서 무엇을 제품 코드에 맡기고 무엇을 디자인 시스템에 남길지 판단한다.