상황
AI 기반 SDLC 플랫폼(spec_flow)의 설정 화면은 처음에 하나의 전역 설정으로 시작했다. Jira 인스턴스 주소, 개인 액세스 토큰(PAT), 프로젝트 키, LLM 키가 전부 한 곳에 섞여 있었다. 사용자가 늘고 프로젝트가 여러 개가 되자 문제가 드러났다. 누구의 토큰으로 Jira를 호출하는지 불분명했고, 프로젝트마다 다른 Jira 프로젝트 키를 쓸 방법이 없었다.
회의에서 방향은 정해졌다. "설정을 시스템/개인/프로젝트 3단으로 분리한다. PAT는 개인으로, 프로젝트 키는 프로젝트로 옮긴다." 결정 두 줄이 전부였다. 데이터 구조를 어떻게 바꿀지, 기존 설정은 어떻게 마이그레이션할지, 세션이 없는 비동기 작업은 누구 자격증명으로 실행할지 — 구현에 필요한 결정은 하나도 없었다.
문제
회의록 수준의 결정과 구현 가능한 스펙 사이에는 큰 간극이 있다. 이 간극을 메우는 흔한 방식 두 가지가 모두 함정이다.
- 바로 코딩 시작: 구현 중에 결정 지점을 만날 때마다 즉흥 판단하게 되고, 판단들이 서로 충돌한다. 자격증명 귀속처럼 인증 레이어 전체를 관통하는 원칙은 즉흥으로 정하면 반드시 구멍이 생긴다.
- 혼자 설계 문서 작성: 한 번에 전체를 쓰면 스스로에게 유리한 가정을 검증 없이 깔게 된다. "폴백이 있으면 편하겠지" 같은 가정이 문서에 그대로 들어간다.
선택한 방식은 그릴링(grilling) 세션이었다. 한 번에 한 질문만 던지고, 각 질문에 추천안을 함께 제시한 뒤, 답이 확정되면 다음 질문으로 넘어가는 구조다. 질문 하나가 결정 하나를 만들고, 결정이 쌓이면 다음 질문이 좁혀진다.
접근과 판단
그릴링 세션에서 12개 설계 결정이 확정됐다. 핵심 결정 몇 가지와 그 근거는 다음과 같다.
자격증명 귀속 원칙 — 폴백 전면 제거. 설계 초안에는 "개인 PAT가 없으면 시스템 공용 토큰으로 폴백"이 있었다. 여기에 결정적 질문이 들어왔다: "사용자 세션이 없으면 동작이 안 되어야 하는 거 아니야?" 이 질문 하나가 원칙을 뒤집었다. 폴백은 편의처럼 보이지만, 실제로는 "누구의 권한으로 실행됐는가"를 추적 불가능하게 만든다. 결론은 폴백 전면 제거였고, 이 원칙이 인증 레이어 전체를 관통하게 됐다.
- 동기 요청: 세션 사용자의 자격증명만 사용, 없으면 실패
- 비동기 작업: 작업을 트리거한 시점의 사용자를 캡처해서 그 사용자 자격증명으로 실행
- MCP API 키: 키를 발급한 사용자에게 귀속 — 키로 들어온 요청은 발급자의 권한으로 동작
좋은 질문 하나가 설계 원칙 전체를 관통한 사례다. 폴백을 지우자 비동기 트리거 캡처와 키 발급자 귀속이 자연스럽게 따라 나왔다.
JiraConfig의 인스턴스/인증 분리. 기존에는 Jira 주소와 PAT가 한 구조체에 있었다. 인스턴스 주소는 조직 공용 정보(시스템 설정)이고 PAT는 개인 정보(개인 설정)이므로, 같은 구조체에 두면 3단 분리가 불가능하다. 구조체를 쪼개서 인스턴스는 시스템 계층에, 인증은 개인 계층에 배치했다.
마이그레이션 — 휴리스틱 고아 자격증명 이전. 기존 전역 설정에 저장된 PAT는 "누구 것인지" 메타데이터가 없다. 완벽한 귀속이 불가능하므로, 최초 로그인한 관리자에게 귀속시키는 휴리스틱을 택하고, 이후 각 사용자가 개인 설정에서 본인 PAT를 등록하면 자연스럽게 교체되는 구조로 갔다. 일회성 마이그레이션 스크립트에 정교함을 투자하지 않는다는 판단이다.
스코프 컷 — 하지 않기로 한 결정들. 설계 세션의 절반은 "무엇을 안 할지" 정하는 일이었다.
- 크리덴셜 암호화 생략: 사내망 전용 환경에서 앱 레벨 암호화는 보안을 실질적으로 올리지 못하고 키 관리 문제만 추가한다. 평문 저장을 유지하되, 응답 직렬화에서
json:"-"태그로 자격증명 필드가 API 응답에 절대 실리지 않게 차단했다. 위협 모델에 맞는 최소 방어다. - FieldMap/StatusMap 프로젝트 오버라이드: 컬럼과 조회 로직만 먼저 넣고 UI는 후속으로 미뤘다. 데이터 구조를 지금 안 잡으면 나중에 마이그레이션이 한 번 더 필요하지만, UI는 언제 만들어도 비용이 같다.
- 임시 화면 생략: 최종 화면이 나오기 전 중간 단계 화면은 만들지 않기로 했다.
구현
12개 결정을 구현 이슈 5개로 분해했다. 분해 기준은 의존 순서다: 데이터 구조가 먼저, 그 위의 실행 규칙이 다음, 실행 규칙이 확정돼야 UI 두 건을 병렬로 진행할 수 있고, 마지막에 기존 시스템 설정 정리가 온다.
flowchart LR
A["#65 데이터 구조<br/>설정 3단 분리 스키마<br/>+ 마이그레이션"] --> B["#66 자격증명 실행 규칙<br/>폴백 제거 · 트리거 캡처<br/>· 키 발급자 귀속"]
B --> C["#67 개인 설정 메뉴<br/>PAT · 개인 키 관리"]
B --> D["#68 프로젝트 Jira 화면<br/>프로젝트 키 · 오버라이드"]
C --> E["#69 시스템 설정 정리<br/>이동된 항목 제거"]
D --> E
이슈 작성에서 지킨 규칙 두 가지:
- 선행 의존을 이슈 헤더에 명시: 각 이슈 첫 줄에 "선행: #65 완료 후 시작"을 박았다. 병렬 가능한 것(#67, #68)과 불가능한 것을 이슈만 보고 판단할 수 있게 했다.
- 상위 이슈는 비즈니스 용어로 순화: 구현 이슈 5개를 묶는 상위 이슈(#64)를 재작성하면서 구조체 이름, 필드명 같은 코드 용어를 전부 제거했다. 상위 이슈는 비개발 이해관계자가 진행 상황을 파악하는 창구이므로 "개인별 Jira 인증 분리", "프로젝트별 연동 설정" 수준의 언어로 유지했다. 코드 용어는 하위 구현 이슈에만 존재한다.
결과
- 회의록 두 줄짜리 결정이 12개 설계 결정 + 상위 이슈 1개 재작성 + 구현 이슈 5개로 구체화됐다.
- 구현 착수 전에 자격증명 귀속 원칙이 확정되어, 인증 관련 즉흥 판단이 들어갈 자리가 없어졌다.
- 이슈 헤더의 의존 표기 덕분에 UI 2건은 실행 규칙 완료 즉시 병렬 착수 가능한 상태가 됐다.
배운 것
- 회의 결정과 구현 스펙 사이의 간극은 질문으로 메운다. 한 번에 한 질문 + 추천안 제시 방식은 결정을 강제한다. 추천안이 있으면 "나중에 정하자"로 미룰 수 없고, 질문이 하나씩이면 결정 간 충돌이 즉시 드러난다. 회의록 수준 결정 → 그릴링 → N개 설계 결정 → 의존 순서 명시한 이슈 분해, 이 파이프라인은 어느 프로젝트에도 적용된다.
- 좋은 질문은 개별 기능이 아니라 원칙을 겨눈다. "세션이 없으면 동작이 안 되어야 하는 거 아니야?"는 폴백 하나를 지운 게 아니라, 비동기 트리거 캡처와 키 발급자 귀속까지 인증 레이어 전체의 일관성을 만들었다. 설계 리뷰에서 찾아야 할 것은 버그가 아니라 이런 관통 질문이다.
- 이슈 분해의 기본 골격은 데이터 구조 → 실행 규칙 → UI 병렬 → 정리다. 데이터가 제일 아래에 있고 UI가 제일 위에 있으므로, 이 순서를 지키면 재작업이 없고 병렬 구간이 자연스럽게 드러난다.
- 스코프 컷은 위협 모델과 비용 구조로 정당화한다. "암호화는 좋은 것"이라는 일반론 대신 "사내망에서 앱 레벨 암호화는 키 관리 문제만 추가한다"는 환경 기반 판단, "데이터 구조는 지금, UI는 나중"이라는 마이그레이션 비용 기반 판단이 컷의 근거가 됐다. 근거 없는 컷은 부채지만, 근거 있는 컷은 설계다.