# 당근 SEED

> 디자인 시스템은 제 일과 무관했습니다. 값어치는 레포를 에이전트가 읽을 수 있게 정리한 방식에 있었습니다.

- 수치: 7종 → 2종
- 사람이 보는 화면: https://aitryed.com/ko/teardowns/memory/karrot-seed/
- 반대 언어: https://aitryed.com/en/teardowns/memory/karrot-seed/index.md
- 저장소: https://github.com/daangn/seed-design
- 이 사이트 안내(AI용): https://aitryed.com/ko/llms.txt

---

**당근이 공개한 디자인 시스템을 열어 봤습니다. 정작 디자인 부분은 제 일과 상관이 없었고, 값어치는 전혀 다른 데 있었습니다 — 「창고를 AI도 읽을 수 있게 정리한 방식」이었습니다.**

> **[도판]** 인스타그램 게시물을 입구로 삼되, 판정은 공식 문서와 레포 트리 8,100 엔트리를 직접 대조해서 냈다.
>
> 레포가 두 종류의 독자를 가진다. 위쪽은 사람용으로 토큰 정의에서 생성물을 거쳐 소비 라이브러리로 흐르고, 아래쪽은 에이전트용으로 LLM 전용 인덱스와 단일 원천 스킬, 훅 가드, 검사 전용 에이전트가 나란히 배치돼 있다.

## 「디자인 시스템」이 뭔가요

앱이나 웹을 만들 때, 버튼·글자 크기·색 같은 것을 **매번 새로 정하지 않고 미리 정해 두고 갖다 쓰는 규칙 모음**입니다.

비유하면 **레고 부품 설명서**와 같습니다. 「파란 버튼은 이 색, 이 크기, 모서리는 이만큼」을 한 번 정해 두면, 화면을 100개 만들어도 버튼이 다 똑같이 생깁니다.

당근은 이걸 만들어서 **누구나 볼 수 있게 공개**해 뒀습니다.

## 그런데 그 부분은 제게 쓸모가 없었습니다

솔직하게 적습니다. 저는 앱 화면을 만드는 사람이 아닙니다. **버튼 색과 글자 크기 규칙은 제 일에 들어올 자리가 없습니다.**

그런데도 이 창고를 뜯은 보람이 있었습니다. **디자인이 아니라 창고 자체가 특이했기 때문**입니다.

## 특이한 점 — 사람용 설명서 「옆에」 AI용 입구를 따로 뒀습니다

보통 창고에는 **사람이 읽는 설명서**만 있습니다. 이 창고는 그 옆에 **AI가 읽는 입구**를 나란히 만들어 뒀습니다.

| | 사람용 | AI용 |
|---|---|---|
| 형태 | 읽기 좋은 문서 사이트 | AI가 직접 물어볼 수 있는 통로 |
| 왜 | 사람이 찾아보려고 | **AI가 코드를 짤 때 규칙을 직접 확인하려고** |

이게 왜 의미가 있냐면 — 요즘은 **코드를 AI가 짜는 경우가 많습니다.** 그런데 AI가 그 팀의 디자인 규칙을 모르면, 아무 색이나 아무 크기나 씁니다. 그럼 규칙을 만들어 둔 의미가 없어집니다.

그래서 **AI가 직접 물어볼 수 있는 자리**를 만들어 둔 것입니다. 「사람이 읽고 AI에게 알려 주는」 게 아니라 **AI가 직접 읽게** 했습니다.

## 그리고 여기서 제가 크게 틀렸습니다

이 편에서 제일 값나간 자리입니다.

창고를 다 읽고 나서 <strong>「배울 만한 것 일곱 가지」</strong>를 적었습니다. 뿌듯했습니다.

**나흘 뒤에 제 환경을 실제로 재 봤습니다. 일곱 중 다섯을 지웠습니다.**

왜 지웠냐면, 다섯 개는 **제 환경에 이미 있거나, 제 환경에서는 애초에 성립하지 않는 것**이었습니다. 창고를 읽을 때는 「좋다」로 보였는데, **제 것과 나란히 놓고 보니 들어올 자리가 없었습니다.**

살아남은 둘은 이겁니다. 둘 다 **자동 실행 장치 한 줄**짜리입니다.

| 남은 것 | 무슨 사고를 막나 |
|---|---|
| 원본을 고치면 **변환 작업을 자동으로 돌린다** | 고쳐 놓고 **결과물 갱신을 잊어버리는 것** |
| 작업이 끝날 때 **「확인했나」를 한 줄 띄운다** | **「오류 없이 통과」를 「제대로 동작함」으로 착각하는 것** |

둘 다 화려하지 않습니다. 그런데 **일곱 개의 화려한 후보 중에 실제로 남은 게 이 둘**이었습니다.

## 그래서 규칙을 하나 적었습니다

> **「남의 창고에서 기법을 배워 왔다」는 판정은, 내 환경을 실제로 재 보기 전에는 유효하지 않다.**

읽을 때 「좋다」고 느끼는 것과, 내 자리에 들어올 자리가 있는 것은 **완전히 다른 문제**입니다. 그리고 그 차이는 **읽는 동안에는 절대 안 보입니다.**

## 덧붙여 — 입구가 된 게시물이 한 문장을 오해시켰습니다

제가 이 창고를 알게 된 경로는 인스타그램 게시물이었습니다.

게시물 내용은 대체로 정확했습니다. **대부분이 공식 문서를 그대로 옮긴 것**이라 틀린 사실이 없었습니다.

그런데 **한 문장이 실무자를 오해시킬 만하게** 적혀 있었습니다. 요약하는 과정에서 조건이 하나 빠졌는데, 그 조건이 빠지면 **「누구나 쓸 수 있다」로 읽히는데 실제로는 그렇지 않은** 종류였습니다.

→ 요약본은 **틀린 게 없어도 오해를 만들 수 있습니다.** 그래서 저는 요약을 입구로만 쓰고, **판정은 항상 원본을 열어서** 냅니다.

## 여기부터는 자세한 기록입니다

**컴포넌트와 토큰은 제 일과 무관했고, 값어치는 전혀 다른 데 있었습니다.** 이 레포가 실제로 보여준 것은 디자인 시스템이 아니라 — **사람용 문서 옆에 에이전트용 진입로를 나란히 둔 레포 운영 구조**입니다. 거기서 기법 일곱을 수확이라 적었는데, **나흘 뒤 제 환경을 실측하고 다섯을 지웠습니다.** 살아남은 둘은 훅 하나짜리입니다.



## 무엇을 뜯었나

**당근의 공개 디자인 시스템이다.** 토큰과 컴포넌트를 YAML로 정의하고, 거기서 CSS를 생성하고, React와 Lynx용 라이브러리로 내보낸다. Apache-2.0, 별 1,023개, 커밋 3,488건.

토큰 설계 자체는 배울 게 적었다 — **의도(`color.primary`)와 값(`color.carrot500`)을 분리해 두면 환경이 바뀔 때 스키마를 안 건드리고 값만 갈아 끼운다**는 발상인데, 제 쪽에도 같은 형태가 이미 있다(규칙과 실행 기계의 분리, 좌표를 절대 픽셀이 아니라 비율로 들고 있는 것). **새로 배울 것이라기보다 이미 쓰고 있는 패턴의 이름표**다.

진짜 볼 것은 그 아래층이었다.

## 2차 전달을 1차 출처로 검증한 결과

입구가 인스타그램 게시물이었다. 대체로 정확하다 — 대부분이 공식 문서를 그대로 옮긴 것이라 사실 오류가 없다. **그런데 한 문장이 실무자를 오해시킨다.**

> 하나의 토큰 소스에서 React, iOS, Android, Lynx까지 여러 플랫폼에 일관된 디자인을 전달

문자 그대로 읽으면 틀린다. 레포 트리 8,100 엔트리를 전수 검색한 결과 — **Swift 파일 0개, Kotlin 파일 0개, iOS·Android 디렉터리 0개.** 공개 패키지 26개 중 모바일 네이티브 산출물이 없다.

원문을 찾아가 보면 iOS·Android 열거형이 이 프리셋으로부터 <strong>"생성될 수 있다"</strong>고 적혀 있다. 가능성 서술이지 산출물 제공이 아니다.

**로드맵 문장을 현황으로 읽게 만드는 형태**다. 게시물이 거짓말을 한 게 아니라, 원문의 조건법을 평서문으로 옮긴 것뿐인데 그것만으로 판정이 뒤집힌다.

## 이 레포의 신기술은 컴포넌트가 아니었다

사람용 문서 **옆에** 에이전트용 배선을 나란히 둔 것. 게시물은 MCP 서버 두 개만 언급했는데, 실물은 그보다 넓었다.

**LLM 전용 진입로를 3단으로 판다.** 루트 인덱스가 영역 목록만 주고 → 영역 인덱스가 문서 목록을 주고 → 단건 URL이 본문을 준다. **에이전트가 필요한 만큼만 내려가서 읽는다.**

**스킬을 단일 원천 + 링크로 둔다.** 소비처가 셋인데 파일은 한 벌이고, 나머지는 전부 그 디렉터리로의 링크다. 원문이 이렇게 적어 뒀다 — *"신규·수정은 이 디렉터리에서만 수행한다. 링크이므로 별도 동기화 작업은 불필요하다."* **"동기화하라"를 규칙으로 쓴 게 아니라 구조로 불가능하게 만들었다.**

**생성 파일 수정을 훅이 막는다.** 그런데 **차단만 하는 게 아니라 원본 위치와 재생성 명령을 같이 출력한다.** 설계 요점이 거기 있다 — **가드가 막다른 길이 아니라 안내판이다.**

**훅을 세 시점에 나눠 건다.** 편집 전에는 생성물을 막고, 편집 후에는 고친 경로를 보고 필요한 빌드를 알아서 돌리고, **세션을 끝내려 할 때는 고친 파일들을 위험 패턴에 대조해 검증 없이 끝내려 하면 붙잡는다.**

**검사 전용 에이전트를 따로 둔다.** 네 종 중 **셋이 편집 도구를 아예 갖고 있지 않다** — 판정만 하고 고치지 않는다. 코드를 짜는 에이전트가 아니라 **구조와 문서가 어긋났는지 보는 에이전트**다.

게시물에 없는 것도 하나 건졌다. MCP 서버에 **모드 옵션**이 있는데, 문서가 이유를 이렇게 적었다 — *"해당 모드에서 사용 가능한 도구만 등록하여 컨텍스트 크기를 줄일 수 있습니다."* **MCP 서버를 도구 묶음이 아니라 컨텍스트 예산 단위로 설계한 사례**다.

## 그리고 제 수확 판정이 깨졌습니다

> **[도판]** 레포를 읽고 낸 판정과, 내 환경을 재고 낸 판정이 달랐다. 후자가 정본이다.
>
> 1차에 기법 일곱을 수확으로 적었는데 나흘 뒤 내 환경을 실측하고 다섯을 지웠다. 이미 갖고 있거나 인과가 맞지 않았다. 살아남은 둘은 훅 하나짜리다.

1차에서 기법 일곱을 수확이라 적었다. 각각에 "제가 이미 겪은 사고"를 붙여 뒀으니 근거가 있어 보였다. **나흘 뒤 제 환경을 실측하고 다섯을 지웠다.** 이미 갖고 있거나, 헛다리였다.

**특히 한 건이 나빴다.** 과거에 겪은 사고와 이 레포의 기법을 그럴듯하게 짝지어 놨는데, **인과가 맞지 않았다.** 그 사고의 원인은 그 기법이 막는 것이 아니었다.

**이 오류는 레포를 아무리 정독해도 안 잡힌다.** 제 설정 파일을 열어야만 잡힌다. 대상 쪽 자료를 아무리 깊게 읽어도 **"내 쪽 원인이 무엇이었나"는 거기 없기 때문**이다.

살아남은 건 둘이고, 둘 다 훅 하나짜리다.

| 할 일 | 막는 사고 |
|---|---|
| 소스를 고치면 빌드 스크립트를 자동 실행 | 고쳐 놓고 생성물 동기화를 잊는다 |
| 세션 끝에 검증 리마인더 한 줄 | "정적으로 통과"를 작동 검증으로 착각한다 |

둘 다 **차단하지 않고 경고만 하는 모드로 먼저 돌린다.** 세션 끝마다 뜨는 훅이 소음이 되면 즉시 역효과다.

## 남는 문장

> **"외부 레포에서 기법을 수확했다"는 판정은, 내 환경을 실측하기 전에는 유효하지 않다.**

이 페이지에서 그 판정이 7에서 2로 줄었다. 줄어든 다섯은 레포가 나빠서가 아니라 **제가 제 환경을 안 보고 적었기 때문**이다.
