개발 기록 2026-10-19 docs/devlog/2026-10-19-1-화면설계서와-시안-정합.md GitHub에서 보기

화면설계서와 시안 정합

목표

디자인 시스템 시안은 화면마다 대표 상태를 하나씩만 보여 준다. 구현할 때 필요한 상태를 화면별로 모두 그린 화면설계서를 만들고, 설계서를 쓰다 찾은 시안 오류를 고쳐 두 문서의 숫자와 이벤트를 맞춘다.

화면설계서는 10/17 밤에 커밋했는데(8093098) 그날 devlog 를 남기지 않았다. 그래서 이 기록에 함께 적는다.

한 일

날짜 커밋 내용
10/17 8093098 화면설계서 HTML (1,661줄, 약 270 KB). S1-S6 기본 화면에 영역 번호를 달고, 영역별 표시 조건, 권한, 이벤트를 표로 정리. 상태 변형(빈 상태, 진행 중, 실패, 권한 없음, 동시 수정 등)과 S5 375px 좁은 화면. 부록 A 화면 문구, B 감사 이벤트와 화면 매핑, C 미결 사항 C-01-C-13. 디자인 시스템 문서에 설계서 링크, S3 오류 코드 4종 추가, "목표 라인 수" 제거
10/19 3cb51fb 시안 오류 6건 수정, 화면설계서 v1.1 (부록 C 의 시안 항목을 "고쳤다" 로 정리), 디자인 시스템 문서 Changelog

10/19 에 고친 시안 오류:

항목 전 후 근거
라인 수 (4곳) 19,794 19,804 시드 20251231 실측 (devlog -11, -12)
합성 GL 출처, 시드 안내 "기본 시드" "시드 20251231" Ledger.Generator.default_seed/0
"목표 라인 수" 입력 칸 있음 삭제 generate_sample_import/3 는 seed 만 받는다 (계약 2.1)
S5 숨은 ai_triage_id 빈 값 화면에 보인 AI 제안의 id 결론과 제안을 잇는 값 (ADR-7)
S6 #74 review.denied 박검토의 review.approved C-10. 작성자는 권한 검사에서 먼저 막힌다
마크업 body 끝에 짝 없는 </main> 삭제

결정과 트레이드오프

  • 설계서는 시안의 CSS 를 그대로 가져와 조립한다. 컴포넌트 모양을 두 곳에서 따로 관리하면 곧 어긋난다. 시안의 <style> 과 스크립트를 잘라 오고 화면별 조각을 붙이는 조립 스크립트를 썼다. 대가는 설계서가 시안 파일 구조에 묶인다는 점이다 (아래 "막힌 점").
  • 미결 사항은 설계서 안에 고치지 않고 부록 C 로 모은다. 설계서를 쓰며 계약과 다른 곳 13건(C-01-C-13)을 찾았다. 계약을 바꾸는 항목(C-07 S2 실행 요약 함수, C-08 list_findings 페이지 옵션, C-09 :below_threshold, C-11 낡은 결론 결정, C-12 감사 payload, C-13 S6 대상 필터)은 메인 세션이 계약 문서에 먼저 반영하고 구현한다(AGENTS.md 5.2). 화면 문서가 계약을 앞질러 바꾸지 않게 하려는 것이다.
  • S6 #74 는 지우지 않고 승인으로 바꿨다 (C-10). Policy 에서 preparer 는 :review_conclusion 권한이 없다. Review.decide/4 가 권한을 먼저 보면 작성자의 자기 검토 시도는 :forbidden 으로 끝나고 :self_review 와 review.denied 에 닿지 않는다. 역할이 reviewer 로 바뀐 작성자만 닿는 방어 경로다. 시안이 일어나지 않는 이벤트를 보여 주면 데모에서 설명이 틀어지므로 실제 흐름(검토자 승인)으로 바꿨다. 작성자의 시도까지 기록할지는 M4 에서 정한다.
  • 시안 숫자는 실측값을 따른다. 19,794 는 생성기를 돌리기 전에 적은 값이었다. 시드 하나로 결정되는 데이터라 실측값이 정답이고, 시안이 그 값을 따라간다.

막힌 점과 해결

  • 시안 한 줄을 지우자 설계서에서 <script> 가 빠졌다. 조립 스크립트가 시안의 스크립트 구간을 줄 번호로 잘라 오고 있었다. "목표 라인 수" 칸을 지워 시안이 짧아지자 구간이 한 줄 밀려 여는 태그를 놓쳤다. 스크립트 구간은 </footer> 뒤 첫 <script> 부터 syncPressed(); 줄까지로 내용 기준으로 찾게 바꿨다. 다시 조립한 설계서의 diff 가 의도한 줄(버전, 부록 C, Changelog)만 바뀐 것을 확인했다. <head> 의 스타일 구간은 아직 줄 번호 기준이다. 이번 수정은 그 구간 밖이라 영향이 없었다.
  • 정보 카드 넘침 (10/17). .facts dd.mono 의 nowrap 때문에 긴 id 가 카드 밖으로 나갔다. 줄바꿈을 허용하는 규칙을 문서 영역(:not(.frame *))에만 걸었다. 화면 시안 프레임 안까지 걸면 날짜가 어색하게 끊겼다. 좁은 프레임의 정보 카드는 2열로 줄였다.
  • 검증 스크립트의 오탐. id 중복 검사 정규식이 aria-invalid="true" 를 id 로 잡았고, 표시 토글 검사는 범례의 .mk 를 먼저 집었다. 정규식과 선택자(.frame .mk)를 고쳐 다시 확인했다. 브라우저 스크린샷이 한 단계 늦게 갱신되는 일이 있어 판정은 JS 검사 결과로 했다.

검증

  • 내장 브라우저에서 두 페이지: 1024px, 375px 가로 넘침 없음, 다크 테마 정상, 콘솔 오류 없음, 문서 안 앵커와 상대 링크 모두 대상 존재.
  • 시안에서 바꾼 6개 값이 화면에 그대로 나오는 것을 확인.
  • mix precommit: 두 커밋 모두 테스트 247개 통과, 실패 0 (문서만 바뀌어 수는 그대로).

Elixir 학습 포인트

코드는 바꾸지 않았지만, 화면을 상태별로 그리면서 LiveView 구현 때 지킬 점이 나왔다.

  • 숨긴 단추는 보안 경계가 아니다 (C-09). LiveView 의 phx-click 이벤트는 웹소켓으로 가는 메시지라 클라이언트가 단추 없이도 보낼 수 있다. 경미 적중의 AI 요청 단추를 숨기는 것과 별개로 handle_event 가 부르는 컨텍스트 함수가 기준 점수를 다시 검사해야 한다. 같은 이유로 S5 의 숨은 ai_triage_id 도 그 finding 의 제안인지 서버가 확인해야 한다 (M4 Review 구현 때 확인).
  • 화면은 그린 시점의 스냅샷이다 (C-11). 검토자가 결론을 읽는 동안 작성자가 결론을 다시 내면, PubSub 갱신이 도착하기 전에 누른 승인은 새 결론에 붙는다. 이벤트에 검토자가 본 conclusion_id 를 실어 보내고 서버가 최신 결론과 비교하면 막을 수 있다 (낙관적 동시성 제어).
  • 검사 순서가 도달 가능한 오류를 정한다 (C-10). Review.decide/4 를 with 체인으로 쓰면 앞 단계가 실패했을 때 뒤 단계는 실행되지 않는다. authorize 를 먼저 두면 :self_review 는 역할이 바뀐 사용자만 보는 오류가 된다. 시그니처에 오류가 적혀 있다고 해서 모든 오류가 실제로 나오는 것은 아니다.

다음 할 일

  • M2 (룰 엔진). 계획일 10/19 에 시작하지 못했다. 10/20 에 시작하면 M3 이후가 하루씩 밀리므로 WBS 일정을 다시 잡는다 (M2 와 M3 를 묶을지, M5 완충을 줄일지는 확인 필요). 워커를 띄우기 전에 메인 세션이 계약 문서에 다음을 반영한다.
    • 4.2 의 test_run 이벤트 payload (설계서 부록 B 제안): test_run.started 에 ledger_import_id, rule_ids, triage_threshold, test_run.completed 에 status, finding_count, test_run_rule.failed 에 rule_id (원인 원문은 넣지 않는다).
    • Tickmark.Jobs.FailureHandler 를 telemetry 에 붙이는 위치. application.ex 는 메인 소유라 워커 A 가 고칠 수 없다.
    • C-07 S2 실행 요약 함수 이름과 반환 모양.
  • C-08, C-09 는 M3, C-11, C-13 은 M4 계약에 넣는다.
  • WBS 1.19: PR #2 (feature/foundation -> main) 는 머지 가능 상태다. 병합되면 M1 을 완료로 바꾼다.
  • 설계서 조립 스크립트와 화면 조각은 저장소에 없다. 다음 설계서 수정 전에 스크립트를 저장소에 둘지, 결과 HTML 을 직접 고칠지 정한다.
  • 배포 대상(Azure az containerapp up 또는 Fly.io)은 사용자 결정 대기 (WBS 5.1).

관련 커밋

8093098 (화면설계서), 3cb51fb (시안 오류 수정).