--- name: architecture-generator description: docs/PRD.md와 docs/TRD.md를 읽고 프로젝트 전체 아키텍처를 docs/ARCHITECTURE/ 아래에 작성한다. overview.md에 시스템 구성·경계·핵심 흐름을 담고, frontend.md·backend.md·database.md·auth.md·security.md 등 영역별 문서로 나눠 기록하며, 무엇보다 PRD·TRD와 충돌하는 설계가 있는지 검토해 봉합하지 않고 드러낸다. 사용자가 "아키텍처 설계해줘", "구조 잡아줘", "설계 문서 써줘", "테이블 설계해줘", "API 설계해줘", "폴더 구조 어떻게 나눌지 정해줘"라고 하거나, TRD 검토를 마치고 다음 단계로 넘어갈 때 반드시 이 스킬을 사용한다. 요구사항과 기술 스택은 정해졌는데 구조가 문서로 없는 상태에서 개발 계획을 세우거나 코드를 짜기 시작하려 할 때도 이 스킬로 먼저 설계를 고정한다. --- # 아키텍처 작성 (Layer 2) ## 이 스킬의 목적 아키텍처는 **"고른 기술 안에서 어떤 모양으로 만들 것인가"**에 대한 합의문이다. PRD가 사용자에게 한 약속이고 TRD가 그 약속을 지키려고 고른 수단이라면, 아키텍처는 그 수단을 실제 구조로 배치한 것이다. 여기서 정한 구조가 뒤에서 이렇게 흘러간다. ``` 아키텍처의 설계 단위 (database.md §3.2 인보이스 번호 채번) → 태스크의 Files·Architecture 항목이 이걸 가리킨다 (Layer 3) → 품질 게이트가 검증할 대상이 여기서 나온다 (Layer 4) → 루프의 한 태스크가 "무엇을 건드려도 되는가"의 경계가 된다 (Layer 5) ``` 그래서 이 문서의 품질은 "구조가 세련됐는가"가 아니라 두 가지로 판정된다. 1. **각 설계가 어느 요구사항·기술 결정 때문인지 적혀 있는가** 2. **PRD·TRD와 어긋나는 지점을 조용히 봉합하지 않고 드러냈는가** 두 번째가 이 레이어의 핵심이다. 요구사항과 기술 결정이 처음 **동시에** 한 사람 앞에 놓이는 곳이 여기다. PRD를 쓸 때는 기술이 없었고 TRD를 쓸 때는 구조가 없었으므로, 둘이 못 만나는 지점은 **아키텍처를 그려 봐야 비로소 보인다.** 그리고 그 지점을 여기서 못 보면, 다음에 보이는 곳은 Layer 5에서 태스크가 세 번 실패하고 멈추는 순간이다. ### 여기서 하는 일과 하지 않는 일 | 하지 않는 것 | 어디서 하는가 | |---|---| | 요구사항을 새로 만들거나 우선순위를 바꾸는 것 | PRD (`prd-generator`) — 사용자가 정하면 이 세션이 PRD 부터 고치고 이어 간다(8단계 "앞 문서 반영") | | 기술을 새로 고르거나 바꾸는 것 (라이브러리 교체 포함) | TRD (`trd-generator`) — 위와 같다 | | 개발 순서, 태스크 분할, phase 구성, 일정 | Layer 3 마스터 플랜 (`plan-generator`) | | 품질 게이트 4단계 구성, E2E가 덮을 흐름 목록, task validation 절차 | Layer 4 하네스 (`harness-setup`) | | 실제 코드, 마이그레이션 파일, 설정 파일 작성 | Layer 5 개발 루프 | **아키텍처는 요구사항도 기술도 만들지 않는다.** 설계하다 보면 둘 다 만들고 싶어진다 — "여기 관리자 화면이 있어야겠는데"(요구사항), "이건 큐가 있어야 되겠는데"(기술). 그렇게 문서에 슬쩍 들어간 것은 추적표에 근거가 없고, PRD·TRD 어느 쪽에서도 검토받지 않은 채 Layer 3에서 태스크가 된다. **둘 다 충돌로 올려 사용자가 정하게 하고, 정해지면 앞 문서부터 고친 뒤 설계한다.** 2단계와 8단계 "앞 문서 반영"이 그 방법이다. 아키텍처가 스스로 넣는 것은 여전히 없다 — 바뀌는 것은 정해진 뒤 누가 문서를 고치느냐다. ### TRD와 아키텍처의 경계 TRD가 이미 정해 둔 기준이 있다 — **후보 중 하나를 고르는가, 고른 것 안에서 모양을 정하는가?** | TRD (고른다) | 아키텍처 (모양을 정한다) | |---|---| | 관계형 DB를 쓴다. 후보 중 X를 고른다 | `invoices` 테이블에 어떤 컬럼과 인덱스를 두는가 | | HTTP + JSON, 오류 응답은 한 형식으로 통일한다 | 그 형식이 정확히 어떤 모양이고, 어떤 경로가 있는가 | | 세션 기반 인증, 역할은 소유자 단일 | 소유권 검사를 어느 계층에서 강제하는가 | | 브라우저 자동화 도구로 X를 쓴다 | (아키텍처 밖 — Layer 4) | **TRD의 결정을 다시 검토하지 않는다.** "이 DB보다 저게 나은데"는 여기서 할 말이 아니다. 다만 **그 결정으로는 요구사항을 만족시킬 수 없다는 것이 설계 중에 드러나면** 그건 취향이 아니라 충돌이므로 반드시 올린다. --- ## 1단계. 입력 확보와 사전 점검 **`docs/ARCHITECTURE/` 가 이미 있으면 작성(1~7단계)을 다시 돌지 않는다** — 남은 충돌·미결을 푸는 것이면 8단계, 설계를 바꾸는 것이면 9단계(부분 갱신)만 한다. 8단계로 풀었는데 `plan_setup/` 이 이미 있으면, 끝에 9단계의 버전·`변경 이력` 한 줄·뒤 문서 맞추기를 한다 — 버전이 그대로면 플랜이 알아채지 못한다. `docs/PRD.md` 와 `docs/TRD.md` 를 **둘 다 전문으로 읽는다.** 요약본으로 대체하지 않는다. 충돌 검토는 두 문서의 세부 문장이 서로 안 맞는 것을 잡는 일이라, 요약하는 순간 잡아야 할 것이 사라진다. **둘 중 하나라도 없으면 아키텍처를 쓰지 않는다.** - PRD가 없으면 → 무엇을 만족시켜야 하는지 모르는 채로 구조를 그리게 된다. `prd-generator` 를 먼저 제안한다 - TRD가 없으면 → 기술 선택이 설계에 섞여 들어간다. `trd-generator` 를 먼저 제안한다 사용자가 "그냥 있는 걸로 진행해달라"고 하면, 없는 문서 대신 무엇을 근거로 삼았는지를 overview.md 1절에 명시하고 진행한다. 근거가 사용자의 구두 설명이면 그 문장을 그대로 인용해 둔다. 나중에 이 설계가 왜 이런지 물을 사람에게 남길 수 있는 것이 그것뿐이다. 읽으면서 다음 네 가지를 먼저 추린다. | 추릴 것 | 어디서 | 왜 | |---|---|---| | **차단 미결** | PRD 8절 · TRD 12절 | 되돌리기 비용이 큰 결정(저장소·인증 모델·배포 형태)에 걸린 미결이 남아 있으면 그 위의 설계는 통째로 재작업 후보다 | | **잠정 결정** | TRD 각 TD의 확정도 | `잠정`·`스파이크 필요` 인 결정 위에는 **갈아 끼울 수 있는 모양**으로 설계한다 | | **NFR 전부** | PRD 5절 · TRD 10절 | NFR은 구조를 직접 결정한다. 성능·보안·보존 기간은 기능보다 먼저 구조를 정한다 | | **P0 요구사항** | PRD 9절 추적표 | P0가 흐르는 경로가 아키텍처의 뼈대다 | **차단 미결이 남아 있으면 설계를 시작하기 전에 사용자에게 알린다.** 두 가지 중 하나를 고르게 한다. 1. 이 자리에서 그 미결을 사용자와 풀고, 답을 앞 문서에 반영(8단계의 "앞 문서 반영")한 뒤 설계를 이어 간다 (권장) 2. 기본값으로 진행하되, 영향받는 영역을 **'잠정 설계'**로 표시하고 뒤집혔을 때 무엇을 다시 그려야 하는지 명시한다 임의로 2번을 고르지 않는다. 다시 그리는 비용을 치르는 건 사용자다. ## 2단계. 충돌 검토 — 이 스킬의 핵심 원본 사양이 이 레이어에 명시적으로 요구한 것이 **"PRD.md·TRD.md와 충돌하는 설계가 있는지 검토한다"**이다. 설계를 다 그린 뒤 검토하는 것이 아니라, **그리는 동안 계속 하는 일**로 다룬다. 충돌은 대개 구체적인 구조를 그려 볼 때만 드러나기 때문이다. ### 무엇이 충돌인가 네 종류가 있고, 각각 다른 곳으로 돌려보낸다. | 종류 | 어떤 모양으로 나타나는가 | 어디로 돌려보내는가 | |---|---|---| | **요구사항 ↔ 기술 결정** | 어떤 구조를 그려도 그 TD로는 그 FR·NFR을 만족시킬 수 없다 | TRD (결정 교체) 또는 PRD (요구사항 조정) — 사용자가 고른다 | | **요구사항 ↔ 요구사항** | 두 FR·NFR을 동시에 만족시키는 구조가 없다 | PRD | | **기술 결정 ↔ 기술 결정** | 두 TD가 같은 지점에서 서로 다른 것을 요구한다 | TRD | | **설계 유발** | 설계가 앞 문서에 없는 요구사항·기술을 요구하게 된다 | 그 요구사항은 PRD, 그 기술은 TRD | | **사용자 요청 ↔ 앞 문서** | 지금 이 작업을 시키면서 사용자가 말로 요구한 것이 PRD·TRD에 없거나 그것과 어긋난다 | 요구사항이면 PRD, 기술이면 TRD | **다섯 번째가 실무에서 가장 자주 나온다.** "이왕 하는 김에 저것도 넣어줘", "그건 바꿔도 돼" 같은 말은 설계를 시키는 자리에서 자연스럽게 나오지만, **말로 한 요청은 아직 어느 문서에도 없다.** 그대로 넣으면 검토받지 않은 요구사항·기술이 아키텍처를 통해 뒷문으로 들어오고, Layer 3은 그것을 PRD·TRD와 같은 무게로 읽는다. 그렇다고 무시하지도 않는다. **사용자가 요청한 것을 조용히 빼면 사용자는 자기가 말한 것이 빠진 줄 모른 채 다음 레이어로 넘어간다.** 충돌로 올려 "지금 반영하지 않았고, 넣으려면 어느 문서를 고쳐야 하는가"를 보이는 것이 양쪽을 다 피하는 유일한 길이다(사용자가 그 CF 에 답하면 8단계 "앞 문서 반영"으로 PRD·TRD 부터 고친다). 사용자의 원래 문장을 그대로 인용해 둔다 — 나중에 "내가 그런 말 했나"를 판정할 근거가 그것뿐이다. 네 번째 종류(설계 유발)도 자주 놓친다. **"이걸 만들려면 X가 필요한데 어디에도 없네"** 는 설계자가 조용히 X를 넣어 해결할 수 있기 때문이다. 그렇게 들어간 X는 아무도 검토하지 않았고, 예산에도 일정에도 없다. ### 충돌은 봉합하지 않고 드러낸다 가장 흔하고 비싼 실수가 **"설계로 어떻게든 맞추는 것"**이다. 그럴듯한 구조를 하나 만들어 내면 문서상으로는 충돌이 사라진다. 사라진 것은 충돌이 아니라 **충돌이 있었다는 사실**이고, 남은 것은 복잡한 구조와 아무도 이유를 모르는 우회 경로다. 그래서 이렇게 처리한다. - 충돌마다 **CF-001** 형태의 ID를 붙이고 overview.md의 충돌 검토 결과 표에 남긴다 - 지금 진행하기 위해 **잠정 설계**를 세우는 것은 괜찮다. 다만 그것이 잠정임을 해당 문서에 적고 CF를 가리킨다 - **해소는 사용자의 결정이다.** 어느 쪽을 굽힐지(요구사항인가 기술인가)는 비용과 목표를 아는 사람이 정한다 ### 충돌 하나의 형식 ```markdown | CF-002 | NFR-002(PDF 10초) ↔ TD-017(서버 헤드리스 브라우저 렌더) | 요구사항↔기술 결정 | 조항 30개 문서에서 렌더 시간이 예산을 넘길 가능성이 높고, 어떤 구조로도 렌더 자체를 빠르게 만들 수 없다 | ① TD-017을 문서 생성 라이브러리로 교체 ② NFR-002를 20초로 조정 ③ 비동기 생성으로 바꾸고 FR-008의 수용 기준을 다시 쓴다 | ③으로 잠정 설계. backend.md §3.4에 표시 | TRD 또는 PRD | 아니오 | ``` 열은 `ID | 무엇과 무엇이 | 종류 | 왜 충돌인가 | 선택지 | 지금 취한 조치 | 돌려보낼 곳 | P0 뼈대`. **마지막 열이 무엇을 위한 것인지**가 중요하다. 이 충돌이 **P0 흐름의 뼈대**(개체와 관계, 인증 모델, 요청 처리 경로) 위에 있으면 `예`, 아니면 `아니오`를 적는다. 8단계의 멈춤 조건이 이 열로 판정되고, Layer 3은 이 열이 `예`인 미해소 충돌에 걸린 태스크를 `blocked` 로 만든다. 표시가 없으면 다음 레이어는 다섯 건이 다 같은 무게로 보이고, 정작 뼈대를 흔드는 하나가 묻힌다. **선택지를 반드시 셋 이하로 적는다.** 사용자가 판단할 수 있어야 충돌을 올린 의미가 있다. "충돌이 있습니다"만 적으면 사용자는 다시 설계자에게 물어보게 되고, 결국 설계자가 정하게 된다. **진짜 충돌만 올린다.** 구조를 조금 손보면 둘 다 만족하는 것은 충돌이 아니라 그냥 설계 문제다. 그건 풀고 넘어간다. 판단 기준 하나 — **어느 한쪽 문서를 고쳐야만 풀리는가?** 그래야 충돌이다. 충돌 목록이 길수록 꼼꼼한 문서가 아니라 앞 레이어가 부실했거나 설계를 안 한 문서다. ## 3단계. 어떤 문서를 만들 것인가 `docs/ARCHITECTURE/` 아래에 만든다. 원본 사양이 그린 구조가 이것이다. ``` project_name/docs/ └── ARCHITECTURE/ ├── overview.md ├── frontend.md ├── backend.md ├── database.md └── auth.md ``` `security.md` 등 영역이 더 필요하면 같은 자리에 추가한다. 경로와 파일 이름은 위 그림을 그대로 따른다. **overview.md 는 항상 만든다.** 나머지는 **TRD가 실제로 결정을 내린 영역만** 만든다. | 만드는 기준 | 예 | |---|---| | TRD에 그 영역의 결정이 있고, 그 안에서 정할 모양이 있으면 만든다 | TRD 4절에 저장소 결정 → `database.md` | | TRD가 "해당 없음"으로 비운 영역은 만들지 않는다 | 외부 연동이 없으면 `integration.md` 없음 | | 영역이 작아서 한 문서가 두세 절뿐이면 상위 문서에 흡수한다 | 보안 규칙이 세 줄이면 `backend.md` 안에 | **빈 문서를 만들지 않는 이유**가 있다. Layer 3은 아키텍처 파일 목록을 훑어 태스크를 만들고, Layer 4는 각 문서의 설계 단위를 검증 대상으로 읽는다. **형식적으로 채운 문서는 그대로 형식적인 태스크와 검증이 된다.** 반대로 필요한 영역을 안 만들면 그 부분은 태스크가 즉흥적으로 정하게 된다. overview.md 6절에 **문서 지도**(어느 파일이 무엇을 정하는가)를 두어, 뒤 레이어가 찾을 곳을 헤매지 않게 한다. ## 4단계. overview.md — 전체 아키텍처의 개요 overview.md 는 **다른 문서를 읽기 전에 읽는 문서**다. 여기서 전체가 어떻게 생겼는지, 어디에 무엇이 적혀 있는지를 잡아 준다. 영역 문서의 내용을 여기에 옮겨 적지 않는다. 두 곳에 적힌 설계는 반드시 한쪽이 낡는다. 담을 것은 이렇다. **시스템 구성** — 구성 요소와 그 사이의 연결. 다이어그램 하나를 둔다(mermaid). 구성 요소는 TRD의 배포·실행 환경 결정에서 나온다. **TRD에 없는 구성 요소를 그리지 않는다** — 그리면 그 순간 충돌(설계 유발)이다. **구성 요소와 책임** — 각 요소가 무엇을 책임지고 무엇을 책임지지 않는가. "안 하는 것"이 실제로는 더 유용하다. **경계와 의존 방향** — 무엇이 무엇을 부를 수 있는가, 그리고 **부를 수 없는가.** 방향이 적혀 있지 않으면 Layer 5에서 태스크마다 편한 쪽으로 부르게 되고, 몇십 개 태스크 뒤에는 아무 방향도 남지 않는다. **핵심 흐름** — PRD의 유저 스토리 중 P0 흐름 3~5개를 골라 요청이 구성 요소를 어떤 순서로 지나가는지 적는다. 각 흐름에 근거 `US-xxx` 를 붙인다. **여기서 대부분의 충돌이 발견된다** — 흐름을 끝까지 그려 보면 빠진 조각이 드러나기 때문이다. **횡단 규칙** — 모든 영역이 함께 지켜야 하는 것. 오류 표현, 시간·시간대, 금액·반올림, 식별자 생성, 로깅에 남기는 것과 남기지 않는 것. **한 곳에 모으는 이유**는 이것들이 영역마다 다르게 정해지면 경계를 넘을 때마다 변환이 생기고, 그 변환 지점이 전부 버그 자리가 되기 때문이다. 각 규칙에 근거 NFR·TD를 붙인다. **문서 지도** · **충돌 검토 결과(2단계의 CF 표)** · **요구사항 → 설계 추적표** · **미결 사항**. ## 5단계. 영역 문서 — 설계 단위로 쓴다 각 영역 문서는 **번호 붙은 절**들로 이뤄진다. 절 하나가 설계 단위 하나이고, 다른 문서와 뒤 레이어가 `database.md §3.2` 로 가리킬 곳이다. **TD처럼 별도 ID를 만들지 않는 이유**는 설계는 기술 결정과 달리 자주 갈라지고 합쳐지기 때문이다. 번호 절이 더 잘 견딘다. 설계 단위 하나는 이렇게 쓴다. ```markdown ### 3.2 인보이스 번호 채번 - **근거**: FR-013(연도별 연속 번호), NFR-008(누락·중복 없음) / TD-003(관계형 DB), TD-004(정수 저장) - **설계**: (구조를 적는다. 무엇이 어디에 있고 어떻게 연결되는가) - **왜 이 모양인가**: 동시에 두 건이 생성될 때 번호가 겹치지 않아야 하므로, 채번을 저장소의 원자적 연산 한 지점에 몰았다 - **검증 기준**: 인보이스 20건을 동시에 생성하면 번호가 20개 모두 다르고 빈 번호가 없다. 연도가 바뀌면 다음 번호가 1로 시작한다 - **바뀔 수 있는 지점**: TD-003이 뒤집히면 채번 방식을 다시 정한다 (걸린 CF 없음 / 잠정 아님) ``` 다섯 항목이 각각 하는 일이 있다. - **근거** — 비어 있으면 그 설계를 지운다. 요구사항도 기술 결정도 요구하지 않은 구조라는 뜻이고, 그건 대개 설계자가 습관으로 넣은 계층이다. 그 계층은 Layer 3에서 태스크가 되고 매 태스크마다 비용을 받아 간다 - **설계** — 구조를 적는다. 코드를 적지 않는다. 이름·필드·관계·순서까지가 여기다 - **왜 이 모양인가** — 다른 모양도 가능했는데 왜 이것인가. **이게 없으면 Layer 5에서 태스크가 편한 대로 바꾼다.** 이유를 아는 모델은 지키고, 모르는 모델은 리팩터링한다 - **검증 기준** — 아래를 보라 - **바뀔 수 있는 지점** — 잠정 TD나 미해소 CF 위에 세운 설계는 여기에 적는다. 뒤집혔을 때 어디를 다시 그리는지 알려 준다 ### 검증 기준을 왜 각 설계 단위에 붙이는가 Layer 4의 task validation은 **그 태스크를 구현한 세션과 분리된 세션에서** 돈다. 구현 중 형성된 판단이 검증에 새는 것을 막기 위해서다. 그 검증자에게는 문서에 적힌 문장이 정보의 전부다. "적절히 분리되어 있다"로는 아무것도 판정할 수 없다. 그래서 PRD·TRD와 같은 규칙을 따른다. - **관찰 가능한 것만** — 무엇을 하면 무엇이 나오는가, 어떤 값이 저장되는가, 어떤 응답이 오는가 - **실패 경로를 최소 하나** — 성공 경로만 적힌 기준은 절반만 검증된 것이다. 권한 없는 접근, 잘못된 입력, 중복 요청 - **숫자가 필요한 곳엔 숫자** — PRD의 NFR 숫자를 그대로 가져온다 - **한 기준은 한 가지만 검사** 검증 기준을 못 쓰겠으면 그 절이 실은 아무 구조도 정하지 않았다는 신호다. 다시 쓴다. ### 영역별로 무엇을 정하는가 **해당 없는 항목은 비운다.** 형식적으로 채우면 뒤 레이어가 그걸 만족시키려고 태스크를 만든다. | 영역 | 정하는 것 | 자주 틀리는 지점 | |---|---|---| | **frontend** | 화면 목록과 각 화면이 만족시키는 FR, 라우팅 구조, 상태를 어디에 두는가, 서버와 주고받는 지점, 공통 UI 규칙(로딩·오류·빈 상태), 반응형 기준 | 화면을 나열만 하고 어느 FR인지 안 적는다. 빈 상태·오류 상태를 빠뜨려 Layer 5에서 즉흥적으로 만들어진다 | | **backend** | 계층 구조와 의존 방향, 모듈 분할과 각 모듈의 책임, 요청 처리 경로(엔드포인트 목록과 요청·응답 모양), 오류 처리 규약, 백그라운드·정기 작업, 외부 연동 지점 | 엔드포인트만 나열하고 계층·책임을 안 적는다. 실패했을 때의 동작을 안 적는다 | | **database** | 개체와 관계(다이어그램), 테이블·컬럼·타입·제약, 인덱스와 그 근거 질의, 상태값 목록과 전이 규칙, 보존·삭제 정책의 구현 방식, 마이그레이션 규칙 | 인덱스를 근거 없이 넣거나, PRD의 보관·파기 기간(NFR)이 스키마에 반영 안 된다 | | **auth** | 인증 흐름(가입·로그인·재설정·로그아웃), 세션·토큰의 저장 위치와 수명, 권한 검사 지점, 비인증 접근 경로의 구조 | TRD에 있는 비로그인 경로를 설계에서 빠뜨린다. 권한 검사가 여러 계층에 흩어진다 | | **security** | 신뢰 경계, 입력 검증 지점, 비밀값이 지나가는 경로, 감사 로그에 남기는 것과 남기지 않는 것, 민감 데이터의 저장·전송 형태 | "표준을 따른다"로 뭉갠다. 검증할 수 없다 | **엔드포인트 목록·테이블 정의·컴포넌트 구조는 여기서 처음 등장한다.** TRD가 일부러 넘긴 것이므로 이건 침범이 아니라 이 레이어의 일이다. 반대로 **어떤 DB를 쓸지, 어떤 프레임워크를 쓸지를 여기서 다시 정하면 침범이다.** ### `CLAUDE.md` · `AGENTS.md` 갱신 `docs/ARCHITECTURE/` 를 쓴 뒤 프로젝트 루트의 `CLAUDE.md` 와 `AGENTS.md` 를 **같은 내용으로** 갱신한다. 사용자가 직접 연 세션과 루프의 자식 세션은 이 스킬을 읽지 않고 시작하는데, 그때 자동으로 읽히는 파일은 Claude Code 는 `CLAUDE.md`, Codex 는 `AGENTS.md` 뿐이다. 그래서 **지금 어느 호스트에서 돌든 둘 다 쓴다** — 한쪽만 쓰면 다른 호스트의 세션이 규칙을 모른 채 시작한다. 내용은 **어느 세션에서든 반드시 지킬 것**만 두고 세부 규칙은 문서를 가리킨다 — 규칙을 옮겨 적으면 두 곳이 곧 어긋나고, 어긋나면 세션은 짧은 쪽을 믿는다. - 둘 다 없으면 아래 뼈대로 만든다. 있으면 **`## 구조 (docs/ARCHITECTURE/)` 절과 `현재 단계` 줄만** 고친다. 다른 절과 사용자가 손으로 적은 내용은 건드리지 않는다. 두 파일이 서로 다르면 지금 호스트의 파일을 기준으로 다른 쪽을 맞춘다. 손으로 적은 줄은 양쪽에 남긴다 - 파일은 있는데 `## 문서 지도`·`## 공통 규칙` 이 없으면(예: `/init` 이 만든 파일) 기존 내용 **아래에** 뼈대 두 절을 더한다. 기존 내용은 손대지 않는다. 절이 없으면 `공통 규칙` 뒤에 제품·기술·구조·플랜·하네스·루프 순서의 자리에 더한다 - 전체 **100줄 안팎, 200줄을 넘기지 않는다.** 넘치면 규칙을 문서 쪽으로 돌려보내고 가리키는 줄만 남긴다 ```markdown # <프로젝트 이름> > harness-loop-fullstack 스킬이 만들고 갱신하는 파일이다. 각 절은 그 레이어의 스킬만 고친다. > `CLAUDE.md` 와 `AGENTS.md` 는 같은 내용이다. 한쪽을 손으로 고치면 다른 쪽도 같이 고친다. > 세부 규칙은 각 문서에 있다 — 여기에는 어느 세션에서든 반드시 지킬 것만 둔다. 200줄을 넘기지 않는다. ## 문서 지도 - `docs/IDEA.md` → `docs/PRD.md` → `docs/TRD.md` → `docs/ARCHITECTURE/` → `plan_setup/` → `harness_setup/` → `loop_setup/LOOP.md` - 뒤 문서는 앞 문서를 근거로 한다. 어긋나면 앞 문서가 이긴다 — 바꿔야 하면 사용자 확인 뒤 **가장 앞 문서부터** 고치고(버전·`변경 이력` 한 줄. 프로젝트 완료 뒤에는 `feature-add`·`refactor-plan` 의 후미 절로) 사이 문서를 맞춘 다음 이어 간다(변경 전파). 손으로 고칠 때도 같다. 루프 세션은 앞 문서를 고치지 않고 LOOP.md 대로 멈춘다 - 현재 단계: <마지막으로 끝낸 스킬> → 다음: <다음 스킬> ## 공통 규칙 - 앞 레이어의 **파일**만 입력이다. 대화 기억이나 추측으로 요구사항·기술 결정을 만들지 않는다 - ID(`FR-`·`NFR-`·`US-`·`OQ-`·`TD-`·`phase-NN-task-MM`)는 참조만 한다. 새 ID 는 마지막 번호 다음으로만 만든다 — OQ 는 프로젝트 전체(`HARNESS.md`·`LOOP.md` 의 미결 표까지)에서, 나머지는 그 문서에서 센다(변경 전파로 앞 문서에 더할 때도) - 사용자가 말하지 않은 값은 `(가정)` 으로 표시한다. 모호하면 추측하지 말고 묻는다 - 요청된 범위를 조용히 넓히거나 줄이지 않는다. 범위 판단은 보고한다 ``` `## 구조 (docs/ARCHITECTURE/)` 절에는 이것만 적는다. ```markdown ## 구조 (docs/ARCHITECTURE/) - 의존 방향: <예: UI → 서비스 → 저장소. 역방향 import 금지> - <경계 규칙 2~3개. 예: DB 접근은 repository 계층에서만 / 외부 API 호출은 adapter 에서만> - 설계 단위(영역 문서 3절)에 없는 모듈을 만들지 않는다. 필요하면 영역 문서를 먼저 고친다 ``` ## 6단계. 추적과 자체 점검 overview.md 에 추적표를 둔다. **PRD의 모든 FR·NFR이 최소 하나의 설계 단위에 걸려야 한다.** | 요구사항 | 설계 단위 | |---|---| | FR-013 | `database.md §3.2`, `backend.md §3.1` | 어디에도 안 걸린 요구사항은 **"이걸 어떻게 만들지 아무도 안 정했다"**는 뜻이고, Layer 3에서 태스크가 만들어질 때 그 자리에서 즉흥적으로 정해진다. 즉흥적으로 정해진 구조는 다른 태스크와 안 맞는다. **이 표가 Layer 3의 입력이다.** PRD 9절 추적표에는 `담당 태스크` 열이 비어 있는데, 그 칸을 채우는 것이 Layer 3이고, 그때 "이 요구사항의 태스크는 어느 설계를 구현하는가"를 여기서 읽는다. 그래서 설계 단위를 `database.md §3.2` 처럼 **절 번호까지** 적는다 — 파일 이름만 적으면 Layer 3이 파일 전체를 태스크 하나로 잡거나, 어느 절을 말하는지 다시 추측한다. 파일을 다 쓴 뒤 처음부터 다시 읽으면서 아래를 확인한다. | 확인할 것 | 통과 조건 | 걸렸을 때 | |---|---|---| | 근거 없는 설계 | 근거가 비어 있는 절이 0개 | 지운다. 아무도 요구하지 않은 구조다 | | 검증 기준 | 모든 설계 단위에 관찰 가능한 기준이 있고, 실패 경로가 최소 하나 | 채운다. 못 쓰겠으면 그 절이 아무것도 정하지 않은 것이므로 다시 쓴다 | | 요구사항 누락 | 어떤 설계에도 안 걸린 FR·NFR이 0개 (PRD 9절 `상태` 가 `폐기` 인 것은 세지 않는다) | 채운다 | | NFR 반영 | TRD 10절의 실현 수단이 전부 구조로 나타남 | 채운다. 구조로 못 만들면 충돌로 올린다 | | 기술 결정 침범 | TRD가 고른 기술을 바꾸거나 새 기술을 도입한 곳이 0건 | 충돌(CF)로 올려 사용자에게 묻는다. 고르면 TRD 부터 고치고 설계를 맞춘다(8단계 "앞 문서 반영") | | 요구사항 신설 | PRD에 없는 기능이 설계에만 있는 곳이 0건 | 충돌(CF)로 올려 사용자에게 묻는다. 넣기로 하면 PRD 부터 고친다(8단계) | | 사용자 구두 요청 | 이번 대화에서 말로 받은 요청이 전부 사용자의 답을 받아 PRD·TRD 에 반영된 뒤 설계됐거나, CF로 남아 있음(보류했거나 답을 받지 못함). 조용히 빠진 것 0건 | 묻고 반영한다. 원래 문장을 인용해 남긴다 | | 앞 문서 정합 | 해소된 CF·미결이 PRD·TRD 에도 반영됐고, overview 의 `입력 문서` 버전이 실제 PRD·TRD 버전과 같음 | 반영한다(8단계). 대화에서만 풀린 것을 남기지 않는다 | | 플랜 침범 | 개발 순서·태스크 분할·일정이 0건 | 지우고 Layer 3으로 넘긴다 | | 하네스 침범 | 품질 게이트 구성·E2E 흐름 목록·task validation 절차가 0건 | 지우고 Layer 4로 넘긴다 | | 충돌 봉합 | 잠정 설계로 넘어간 것이 CF 표에 전부 있음 | 올린다. 봉합된 충돌은 Layer 5에서 터진다 | | 문서 지도 | overview.md가 만든 파일을 전부 가리키고, 없는 파일을 가리키지 않음 | 맞춘다 | | 중복 | 같은 설계가 두 문서에 적힌 곳이 0건 | 한쪽을 참조로 바꾼다 | | 잠정 결정 위의 설계 | 잠정 TD 위에 세운 설계에 '바뀔 수 있는 지점'이 적혀 있음 | 채운다 | | 설계 밀도 | 절 하나가 태스크 몇 개로 나뉠 크기인가 | 한 절이 한 태스크보다 작으면 합치고, 열 개보다 크면 나눈다 | | `CLAUDE.md` · `AGENTS.md` | 두 파일이 같고 `## 구조` 절이 갱신됐고 각 200줄 이하 | 자기 절만 고친다. 넘치면 규칙을 문서로 돌려보내고 가리키는 줄만 남긴다 | **자체 점검 결과를 아키텍처 문서 안에 절로 남기지 않는다.** 점검은 작업 기록이고 문서는 산출물이다. Layer 3·4가 이 문서를 읽을 때 필요한 것은 설계이지 "내가 무엇을 확인했는가"가 아니며, 문서에 남기면 나중에 설계가 바뀌어도 점검표는 그대로 남아 통과한 적 없는 상태를 통과했다고 말하게 된다. **점검 결과는 7단계의 보고문으로 간다.** **임의로 고쳐도 되는 것과 보고해야 하는 것이 다르다.** 형식 문제(빠진 검증 기준, 문서 지도 불일치, 중복)는 고치면 된다. **충돌은 절대 혼자 해소하지 않는다.** 어느 쪽을 굽힐지는 비용과 목표를 아는 사용자가 정한다. 여기서 조용히 요구사항 쪽을 깎으면, 사용자는 자기가 요청한 것이 빠진 줄 모른 채 다음 레이어로 넘어간다. ## 7단계. 작성 후 보고 `docs/ARCHITECTURE/` 아래 파일을 다 쓴 뒤 사용자에게 이 순서로 보고한다. 1. 만든 파일 목록과 각 파일이 무엇을 정하는지 한 줄씩 2. **충돌 검토 결과 — 이게 보고의 핵심이다.** CF 하나하나에 대해 무엇과 무엇이 부딪히는지, 선택지, 지금 취한 잠정 조치를 보여 준다. 충돌이 0건이면 "0건"이라고 명시한다. 안 적으면 검토를 안 한 것인지 없는 것인지 구별되지 않는다 3. 잠정 설계 목록 — 어느 TD·CF가 뒤집히면 어디를 다시 그리는지 3-1. **앞 문서 반영** — 이번에 고친 PRD·TRD 의 새 버전과 바뀐 ID, 누가 무엇을 골랐는가. 0건이면 적지 않는다 4. 새로 생긴 미결 사항 (번호는 프로젝트 전체의 마지막 OQ 다음 — 보통 TRD 끝 다음이지만, 이 세션의 "앞 문서 반영"으로 PRD·TRD 에 새 OQ 가 생겼으면 그 다음) 5. 자체 점검에서 걸렸지만 임의로 고치지 않은 것 6. 다음 단계 안내: "검토하시고, 괜찮으면 마스터 플랜으로 넘어갈까요? (`plan-generator`)" **사용자 검토 전에 Layer 3으로 넘어가지 않는다.** 아키텍처가 틀린 채로 넘어가면 태스크 전체가 같이 틀리고, 그때는 문서 한 장이 아니라 phase 하나를 다시 쓰게 된다. ## 8단계. 충돌·미결 해소 세션 **충돌 먼저, 그다음 미결이다.** 미결은 아직 안 정한 것이지만 충돌은 이미 어긋나 있는 것이라, 놔두면 양쪽 문서가 계속 서로 다른 것을 말한다. ``` 아키텍처에 충돌 1건 (NFR-002 ↔ TD-017) → 플랜: 관련 태스크가 어느 쪽 설계로 만들지 모른 채 만들어진다 → 하네스: 어느 기준으로 검증할지 정할 수 없다 → 루프: 구현 → 검증 실패 → 수정 3회 → 멈춤. 원인은 코드가 아니라 여기다 ``` 각 충돌에 대해 **선택지를 셋 이하로 제시하고 결과를 그 자리에서 문서에 반영한다.** 대화에서만 합의하고 문서를 안 고치면 다음 레이어는 옛날 문서를 읽는다. PRD·TRD 쪽이 바뀌었으면 **그쪽 문서도 함께 고친다** — 아키텍처에만 반영하면 세 문서가 서로 다른 말을 하게 되고, 그때부터는 어느 것이 합의인지 아무도 모른다. ### 앞 문서 반영 — 보고하고 멈추지 않는다 `돌려보낼 곳` 열은 "사용자가 나중에 고칠 문서"가 아니라 **이 세션이 지금 고칠 문서**다. 사용자가 고르면 그 자리에서 — ① **가장 앞 문서부터**: 요구사항이면 `prd-generator` 8단계, 기술이면 `trd-generator` 9단계(부분 갱신). 둘 다면 PRD 먼저. 부를 수 없으면 같은 규칙으로 직접(바뀐 항목만, ID 유지·새 ID 는 끝번호·없어진 것은 `폐기 — 대체:`, 추적표, 버전과 `변경 이력` 한 줄). ② PRD 를 고쳤으면 그 FR·NFR 이 근거인 TD 가 있는지 TRD 13절에서 보고 TRD 도 맞춘다 — 사이 문서를 건너뛰면 TRD 만 옛 요구사항을 말한다. ③ CF 행의 `지금 취한 조치` 를 "해소 — PRD 0.2 FR-008 대체" 처럼 고치고, 그 CF 를 가리키던 잠정 설계 표시를 걷고, overview 머리의 `입력 문서` 버전을 올린다. ④ 하던 설계로 돌아가고, 7단계 보고의 **앞 문서 반영** 묶음에 적는다. Layer 6(`feature-add`·`refactor-plan`)이 이 스킬을 부른 중이면 앞 문서는 본문이 아니라 **그 요청의 후미 절**(`## 추가 N`·`## 리팩토링 N`)에 적는다 — 원본 규칙이다. `refactor-plan` 이 부른 중에 PRD 를 바꿔야 하면 그것은 요구 변경이라 반영하지 않고 "`feature-add` 로 다룰 일"로 보고한다(리팩토링은 PRD 를 쓰지 않는다). 사용자가 "지금은 앞 문서를 고치지 말라"고 할 때만 CF 로 남긴다. 답을 받기 전에는 반영하지 않는다 — 대화할 수 없는 세션(무인·평가)이면 결정이든 기록이든 다른 레이어 문서는 고치지 않고(그 스킬도 부르지 않고) 지금처럼 보고·CF·미결로 남긴다. 기록 종류(대화에서 이미 정한 것이 문서에 안 적힌 것, 낡은 추적표 행)는 묻지 않고 고친 뒤 보고한다. **사용자가 말로 "이것도 넣어줘"라고 한 새 요구는 기록이 아니라 결정이다** — 수용 기준·우선순위·범위가 아직 정해지지 않았으므로 CF 로 올려 묻는다. 미결은 PRD·TRD와 같은 규칙을 따른다. 종류는 `질문 / 확인 / 실험 / 유예` 넷이고, **번호는 프로젝트 전체의 마지막 OQ 다음에 이어 붙인다** (TRD가 OQ-018에서 끝났으면 OQ-019부터). `확인`·`실험`·`유예`는 객관식으로 묻지 않는다 — 사용자가 모르는 것을 찍게 되고 그 답이 확정된 합의로 문서에 박힌다. 모델이 혼자 가정한 것보다 나쁘다. ### 언제 멈추는가 전부 해소되지 않아도 Layer 3으로 넘어갈 수 있다. 조건은 두 가지다. 1. **요구사항↔기술 결정 충돌이 0건이거나, 남은 것에 대해 사용자가 잠정 설계를 명시적으로 승인했다** 2. **P0 흐름의 뼈대(개체·관계, 인증 모델, 요청 처리 경로)에 걸린 미해소 충돌이 없다** 이 뼈대 위에 태스크 수십 개가 쌓이므로, 나중에 뒤집히면 phase 하나가 통째로 재작업이 된다. ## 9단계. 이미 `docs/ARCHITECTURE/` 가 있을 때 — 부분 갱신 루프가 돌다 "아키텍처에 없는 계층이 필요하다"고 돌려보내거나, PRD·TRD 가 바뀌어 설계 단위 몇 개가 낡는 일이 생긴다. **PRD·TRD 버전이 overview 머리의 `입력 문서` 버전보다 높으면** 그 문서의 `변경 이력` 에서 기록된 버전 뒤의 줄부터 읽는다 — `영향` 과 바뀐 ID 로 8절 추적표를 찾으면 다시 볼 설계 단위가 나온다. 그때 1~8단계를 처음부터 다시 돌리면 **CF 표의 `지금 취한 조치` 와 각 절의 `바뀔 수 있는 지점`, 사용자가 손으로 고친 설계가 초기값으로 덮인다.** `docs/ARCHITECTURE/` 가 이미 있으면 **이 단계만 한다**(검토 뒤 남은 충돌·미결을 푸는 것은 8단계다). **사용자가 직접 불렀는데 프로젝트가 완료됐으면**(`STATE.md` 의 `Phase Overview` 가 전부 `completed`) 이 단계로 본문을 고치지 않고 `feature-add`(요구 변경)·`refactor-plan`(기술·구조 변경)으로 안내한다 — 완료 뒤에는 후미 절로 반영하는 것이 원본 규칙이다. - **바뀐 것만 고친다.** 새 설계 단위는 그 영역 문서의 `## 3. 설계 단위` **끝번호**에 붙인다 — 중간에 끼우면 태스크의 `architecture` 가 가리키는 `§3.x` 가 다른 절이 된다. 기존 절은 번호를 유지한 채 본문만 고치고, 없어진 절은 지우지 않고 "폐기 — 대체: §3.y" 로 표시한다 - **근거·검증 기준·바뀔 수 있는 지점**은 새 절에도 똑같이 채운다. 5단계의 규칙 그대로다 - **충돌 검토를 새 절에 대해서만 다시 한다.** 새 CF 는 끝번호에 붙이고, 해소된 CF 는 지우지 않고 `지금 취한 조치` 를 "해소 — (무엇으로)" 로 바꾼다. Layer 3의 차단 판정이 이 표를 읽으므로 행을 지우면 무엇이 풀렸는지 알 수 없다 - **overview.md 의 문서 지도·추적표·미결을 맞춘다.** 새 절이 만족시키는 FR·NFR 을 8절 추적표에 더한다 - **버전을 올리고 `변경 이력` 에 한 줄** (`0.1` → `0.2`. Layer 6 후미 절 모드면 `변경 이력` 줄은 쓰지 않고 버전만 올린다 — 후미 절 첫 줄(날짜·요청·ID)이 이력이다). 뒤 문서가 `docs/ARCHITECTURE/ (0.1)` 을 입력으로 적어 두었으므로 무엇이 낡았는지 여기서 드러난다 - 파일을 통째로 다시 쓰지 않고 바뀌는 절만 고친다 - 새 결정이 필요해 PRD·TRD 를 바꿔야 하면 8단계 "앞 문서 반영"을 먼저 한다 - **다른 스킬이 이 단계를 불렀으면(앞 스킬이든 뒤 스킬이든) 뒤 문서 연쇄를 하지 않고 그 스킬로 돌아간다** — 뒤 문서 연쇄는 처음 시작한 스킬 하나가 순서대로 부른다. 둘이 각자 연쇄하면 같은 문서를 두 번 고친다. `CLAUDE.md` 의 `현재 단계` 줄은 건드리지 않는다 — 단계가 바뀐 것이 아니다. - 사용자가 직접 불렀으면 끝나고 뒤 문서 중 이미 있는 것을 차례로 부른다 — **`plan-generator` 10단계** → `harness-update` → `loop-update`. 루프가 도는 중(`Phase Overview` 에 `in_progress`)이면 플랜부터는 부르지 않고 무엇이 낡았는지 보고만 한다(그 문서들의 필자는 루프다). 플랜이 필요한 이유는 이렇다 — 새 설계 단위는 태스크가 없고, 낡은 절에 걸린 태스크는 다시 잘라야 한다. **폐기한 절을 `architecture` 로 가리키는 태스크 목록**을 보고에 적는다(`plan_setup/` 의 태스크 문서를 그 절 번호로 검색하면 나온다). 플랜이 그 목록으로 미완료 태스크를 옮기고 완료 태스크는 색인에 병기한다 PRD·TRD 도 같은 원칙이다(바뀐 항목만, 번호 유지, 버전 올림) — `prd-generator` 8단계, `trd-generator` 9단계가 그 절차다. --- ## 산출물 템플릿 ### `docs/ARCHITECTURE/overview.md` ````markdown # 아키텍처 개요: (제품 이름) - **버전**: 0.1 (초안) - **작성일**: YYYY-MM-DD - **입력 문서**: docs/PRD.md (0.1), docs/TRD.md (0.1) - **상태**: 사람 검토 대기 - **변경 이력**: (없음 — 고칠 때마다 `0.2 (YYYY-MM-DD, <고친 스킬>) — <무엇을 왜>. 영향: <태스크·게이트>` 한 줄씩. 영역 문서까지 이 버전 하나로 센다) ## 1. 이 문서의 범위 (무엇을 정하고 무엇을 정하지 않는가. TRD·플랜과의 경계를 한 문단으로.) ## 2. 시스템 구성 ```mermaid flowchart LR ``` | 구성 요소 | 책임 | 책임지지 않는 것 | 근거 | |---|---|---|---| ## 3. 경계와 의존 방향 | 부르는 쪽 | 부르는 대상 | 허용 | 금지되는 방향 | 왜 | |---|---|---|---|---| ## 4. 핵심 흐름 ### 4.1 (흐름 이름) — US-00x (요청이 구성 요소를 지나는 순서. 실패했을 때 어디로 가는지도 적는다.) ## 5. 횡단 규칙 | 규칙 | 내용 | 근거 | |---|---|---| | 오류 표현 | | TD-008, NFR-00x | | 시간·시간대 | | | | 금액·반올림 | | NFR-008 | | 식별자 | | | | 로깅 | 남기는 것 / 남기지 않는 것 | NFR-00x | ## 6. 문서 지도 | 파일 | 정하는 것 | |---|---| | `frontend.md` | | ## 7. PRD·TRD 충돌 검토 결과 | ID | 무엇과 무엇이 | 종류 | 왜 충돌인가 | 선택지 | 지금 취한 조치 | 돌려보낼 곳 | P0 뼈대 | |---|---|---|---|---|---|---|---| | CF-001 | | 요구사항↔기술 결정 | | ①②③ | | TRD | 예 | > 검토 대상: PRD의 FR-001~FR-0xx, NFR-001~NFR-0xx / TRD의 TD-001~TD-0xx. 충돌 n건. ## 8. 요구사항 → 설계 추적표 | 요구사항 | 설계 단위 | |---|---| | FR-001 | `auth.md §3.1`, `frontend.md §3.2` | ## 9. 미결 사항 (TRD에서 이어지는 번호를 쓴다.) | ID | 결정할 것 | 종류 | 차단하는 설계 | 해소 방법 | 미해소 시 기본값 | 되돌리기 비용 | |---|---|---|---|---|---|---| ```` ### 영역 문서 (`frontend.md`, `backend.md`, `database.md`, `auth.md`, `security.md`) ```markdown # (영역) 아키텍처 - **근거 문서**: docs/PRD.md (0.1), docs/TRD.md (0.1) - **관련 기술 결정**: TD-00x, TD-00y - **잠정인 부분**: (없으면 '없음') ## 1. 이 문서가 정하는 것 / 정하지 않는 것 ## 2. 구조 (그 영역 전체가 어떻게 생겼는지. 필요하면 다이어그램.) ## 3. 설계 단위 ### 3.1 (이름) - **근거**: FR-00x, NFR-00x / TD-00x - **설계**: - **왜 이 모양인가**: - **검증 기준**: (관찰 가능하게. 실패 경로 최소 1개) - **바뀔 수 있는 지점**: (없으면 '없음') ## 4. 이 영역이 만족시키는 요구사항 | 요구사항 | 설계 단위 | |---|---| ``` --- ## 에이전트별 참고 - Claude Code에서 실행 중이면: `references/claude-code.md` - Codex에서 실행 중이면: `references/codex.md`