gwimong's blog Software Engineer

artifact-transformer 작업 일지 #45

허용 규칙을 넣었는데도 외부 쓰기가 막힌 날


이 글은 2026-09-21 하루의 기록이다. 다이어그램 편집 화면에서 접힌 JSON 편집 영역을 팝업으로 옮기는 일로 시작했다. 이어서 한 프로젝트의 Task 진행 상황을 검토했고, 상태가 실제 작업보다 뒤처진 6건을 Jira에서 옮기려다 권한 검사에 두 번 막혔다.

배경 — 편집 화면과 Task 상태, 둘 다 실제와 어긋나 있었다

저녁 작업은 크게 두 갈래였다.

첫째는 편집기 UI다. 업무 모델 패널 맨 아래에 「고급 모델 JSON 편집」 접이식 영역이 있었다. 다이어그램에서 작업하다가 JSON을 고치려면 패널을 끝까지 내려야 했다. 구성도·흐름도 캔버스는 높이가 고정값이라 메인 패널 아래쪽이 비어 있었다.

둘째는 Task 검토다. /scope로 세션을 한 프로젝트에 고정하고 “Tasks에서 진행 상황 검토해줘”라고 시켰다. Task는 BATON의 정본 저장소(build/state.db)에 있고, Jira는 그 저장소를 밖으로 비추는 선택적 투영이다.

문제

  1. JSON 편집 진입점을 다이어그램 안으로 옮기면서 기존 동작(검증 결과 클릭 시 해당 위치로 이동)을 유지할 수 있나
  2. 캔버스가 메인 패널을 채우게 하려면 높이를 어떻게 정해야 하나
  3. Task 상태가 실제 데이터 작업과 맞는지 무엇으로 판단하나
  4. 어긋난 상태는 Jira와 로컬 중 어디를 먼저 고쳐야 하나

결정 1 — JSON 편집은 다이어그램 헤더의 버튼 하나로

접이식 영역을 없애고, 다이어그램 헤더 줄(속성·검색 옆)에 [모델 JSON] 버튼을 달았다. 논리·물리 데이터 다이어그램에도 제목 줄 오른쪽 끝에 같은 버튼을 붙였다.

팝업은 새로 만들지 않고 기존 AI 지시 팝업 컴포넌트(ModelAssistDialog)를 재사용했다. 이 컴포넌트가 제목을 인자로 받도록 바꾸고, 폭은 최대 1080px, 입력 영역은 고정폭 글꼴로 했다.

기존 동작옮긴 뒤
패널 하단 접이식 영역다이어그램 헤더 버튼 → 팝업
검증 결과의 documentAttributes 클릭 → 영역 펼침같은 클릭 → 팝업 열림
문서 정보 안내문 “고급 모델 JSON에서 수정""다이어그램의 [모델 JSON] 팝업에서 수정”

마지막 줄은 놓치기 쉬웠다. 옛 위치를 가리키는 안내문이 DocEditor.tsx에 하나 남아 있었다. 버튼을 옮기면 그 버튼을 설명하는 문장도 같이 옮겨야 한다.

결정 2 — 캔버스 높이는 고정값 대신 남은 공간을 잰다

캔버스 높이를 CSS 고정값으로 두지 않고, 메인 패널에서 캔버스 아래로 남은 높이를 재서 넣는다. 창·패널·캔버스 위쪽 컨트롤의 크기가 바뀌면 다시 잰다.

  • 최솟값은 360px
  • 측정에 실패하면 기존 값(450~740px clamp)으로 돌아간다
  • 문서 편집기 안에서는 패널의 테두리와 안쪽 여백을 없애 폭도 꽉 채운다

tsc --noEmit과 vite build는 통과했다. 다만 브라우저에서 직접 열어 보지는 않았다. 스크롤 맨 위에서 캔버스 바닥이 패널 바닥과 맞는지, 속성 사이드 패널이 늘어난 캔버스 위에서 제자리에 있는지는 아직 확인하지 않았다.

결정 3 — Task 상태는 개정 이력의 Jira 키로 대조한다

Task 저장소는 읽기 전용(mode=ro)으로 열었다. 29건 중 v1.1 검토 13건과 업무 정의서 1건은 끝났고, v1.2 개정 15건은 진행 중 4건, 해야 할 일 11건이었다. 29건 모두 9월 7일에 한 번에 만들어진 뒤로 상태 변화가 없었다.

상태가 맞는지는 각 Jira 키가 데이터 파일(data/*.json)의 개정 이력에 나오는지로 판단했다.

구분건수
데이터 작업은 했는데 “해야 할 일”로 남음6
”진행 중”인데 개정 이력에 흔적이 없음1
유스케이스 다이어그램 키가 엉뚱한 파일(participant.json) 이력에 적힘1

같이 돌린 check.py 정합성 검사는 스키마·추적성 모두 오류 0건이었다. 데이터에는 문제가 없고, Task 상태와 버전(아직 1.1.x)만 실제를 따라가지 못한 셈이다.

개정 이력에 적힌 이슈 키가 Task 상태의 가장 싼 증거다. 누가 상태를 옮기지 않아도 작업 흔적은 남는다.

결정 4 — Jira를 먼저 옮기고, 로컬은 그다음

순서를 Jira 전이 → 로컬 갱신 → 재조회로 정했다. 로컬만 먼저 바꾸면 서버가 그 변경을 outbox로 Jira에 대신 밀어낸다. 그러면 Jira 쓰기가 거부된 상황에서 권한을 우회하는 셈이 된다.

이 Jira 워크플로에는 “해야 할 일”에서 “진행 중”으로 바로 가는 전이가 없다. 서버 코드에 있는 우회 경로(_INPROGRESS_HOPS)를 그대로 따랐다.

해야 할 일 --(7 Open Issue)--> 미해결 --(4 시작 진행)--> 진행 중

의도치 않은 함정 — 허용 규칙보다 자동 모드 검사가 먼저였다

첫 전이 호출에서 자동 모드의 권한 검사가 [External System Writes]로 거부했다. 허용 규칙을 넣는 방법을 안내했고, /permissions에서 전이 조회·실행 두 도구가 허용됐다는 메시지까지 떴다.

그런데 같은 호출이 같은 사유로 또 막혔다. 규칙이 어느 설정 파일에 저장됐는지 확인하려던 읽기 전용 grep까지 거부됐다. 여기서 우회를 시도하지 않고 멈췄다.

결국 Shift+Tab으로 자동 모드를 끄고 호출마다 승인하는 방식으로 바꾸자 바로 통과했다. 6건 모두 두 번씩 전이해 “진행 중”이 됐고, 로컬 Task도 정본 모듈(local_tasks.update)과 expectedVersion으로 맞췄다.

정리하면 이 환경에서는 허용 규칙이 자동 모드 분류기보다 우선하지 않았다. 외부 시스템에 쓰는 작업을 여러 건 할 때는 처음부터 자동 모드를 끄고 시작하는 편이 빠르다.

곁가지 — 다른 대시보드의 UX 개편 프롬프트

별도 프로젝트의 시험 대시보드에서 “Task 기반 IDE형 UX를 워크스페이스 기반 단일 흐름으로 바꾸는 프롬프트”를 요청했다. 코드는 건드리지 않고 구조만 훑었는데, 같은 기능으로 가는 길이 여러 개인 게 가장 먼저 보였다.

  • 워크스페이스 전환 경로 4곳
  • 단계 이동 UI 2곳, 흩어진 점검 버튼 5개
  • 서로 덮어쓰는 CSS 레이어 약 15개

프롬프트의 원칙은 “기능마다 진입점은 하나”와 “단계는 사용자가 고르지 않고 서버 실행 상태가 정한다” 두 가지로 잡았다. 같은 날 한 JSON 버튼 이동도 결국 같은 원칙이었다.

마무리

  • 편집 진입점은 쓰는 자리 가까이에 하나만 둔다. 옮길 때는 그 진입점을 가리키는 안내문도 같이 옮긴다.
  • 외부 투영이 있는 상태는 바깥을 먼저 바꾸고 안쪽을 맞춘다. 거꾸로 하면 동기화 장치가 권한을 우회하는 통로가 된다.

다음에 할 일:

  • 캔버스 높이·테두리 제거를 브라우저에서 확인
  • 로컬 갱신 뒤 syncStatus가 pending으로 남은 6건의 outbox 처리 확인 (Jira는 이미 옮겨 둔 상태라 중복 전이가 안 나는지)
  • 유스케이스 다이어그램 키가 participant.json에 적힌 건 정정, v1.2 버전 올리기, 커밋 안 된 SVG 8개 정리

Comments

Content