gwimong's blog Software Engineer

artifact-transformer 작업 일지 #22

개발에서 적용으로 — 도구가 큰 틀에서 완성되자, 아홉 저장소에 규약을 밀어넣으며 파서·리네임·업로더의 남은 모서리를 다듬다


이 글은 2026-07-01~07-07 일주일 동안 artifact-transformer가 개발 국면을 지나 적용 국면으로 넘어간 기록이다. 핵심 파이프라인(생성·역파싱·검증·라운드트립)이 큰 틀에서 자리를 잡자, 하루의 일은 새 기능을 얹는 게 아니라 이미 세운 규약을 산하 아홉 저장소(fdsp·iam·loras·padx·paix·sdsp·sugcs·sulas·suoms)에 전수 적용하며 도구의 남은 모서리를 다듬는 쪽으로 옮겨 갔다. 산출물을 어떻게 정리했는지가 아니라, 여러 프로젝트에 밀어넣는 동안 도구가 어디까지 지켜 줬고 어디서 멈췄는지에 초점을 둔다.

배경 — 개발에서 적용으로

artifact-transformer는 Jira 이슈와 PlantUML 다이어그램을 입력으로 받아 요구사항·유스케이스·기능·시퀀스 명세서와 데이터 정의서/명세서 등을 docx/xlsx로 자동 생성·역파싱하는 도구다 (#4 참조).

스무 편 남짓 이어 오며 도구의 골격은 어느새 완성됐다. #21에서 도출 경로에 세 겹 가드를 박았고, 그 무렵부터 배운 명제는 늘 같았다 — 결정적 규약은 사람의 손질이 아니라 도구가 지킨다. 이제 국면이 바뀌었다. 새 기능을 만드는 날보다, 만든 규약을 여러 프로젝트에 적용하며 어긋남을 잡는 날이 많아졌다. 그리고 적용은 개발이 혼자서는 못 보던 것을 보여 준다 — 한 저장소에선 안 드러나던 파서·리네임·업로더의 사각이, 아홉 곳에 같은 규약을 밀어넣자 정직하게 튀어나왔다.

결정 1 — 규약을 아홉 저장소 전수로 밀어붙이다

이 주의 중심 작업은 새 규약을 만드는 게 아니라, 정해 둔 규약을 남은 저장소 전부에 적용하는 일이었다.

  • 대표 하나로 모으기(OVERVIEW) — 다이어그램 종류마다 대표를 하나 세운다. C4는 “구성요소가 1개면 partial 없이 OVERVIEW만”, 흐름도 계열은 “영역별 partial + 대표 OVERVIEW”. SDSP·FDSP에서 시작해 여섯 저장소로 폈다.
  • 거버넌스별 분리 — BCDG를 관리 영역(거버넌스)별 partial로 쪼개고 OVERVIEW로 조합하는 규약을 loras·padx·sulas·sugcs·suoms·paix까지 밀었다(loras 728b7ca, sulas 4e9e202, sugcs 253f62a, padx eaab18e).
  • 파일명에서 순번 걷어내기 — 이름을 {프로젝트}-{종류}-{영역} bare 규약으로 통일하고 뒤에 붙던 -001·-00N을 없앴다(sulas c66c26b·1c70a7f).

이 전수 재편이 하루 만에 안전했던 이유는 도구가 조용히 지켜 준 계약 덕이었다. BCDG를 아무리 쪼개고 이름을 바꿔도, 이들은 파서가 무시하는 표시 전용 요소라 원천 JSON(business·usecase·physical)의 라운드트립은 매번 [+0 -0 ~0]을 유지했다. 그래서 전부 revise 없이 plain 커밋으로 처리했다.

적용 국면의 미덕은 규약이 아니라 계약에서 나온다 — “표시 전용은 원천을 안 건드린다”. 여섯 저장소의 다이어그램을 하루에 재편하고 순번까지 걷어내면서도 데이터 손상을 걱정하지 않을 수 있었던 건, [+0 -0 ~0]이라는 초록불이 “그림만 만졌다”를 매번 증명해 줬기 때문이다. 개발이 남긴 계약이 적용을 떠받친다.

결정 2 — 적용이 도구를 고치게 했다: 규약을 코드에 심기

규약을 전수로 밀자, 도구가 그 규약을 아직 못 읽는 자리 둘이 드러났다. 이 주에서 가장 “개발”다운 순간이었다 — 정리하는 손이 아니라, 정리가 도구 수정을 끌어낸 자리다.

하나 — OVERVIEW-only를 드리프트로 읽던 파서. “구성요소 1개면 OVERVIEW만” 규약을 SDSP에 적용하자 파서가 걸렸다. SDSP는 systems가 9개인데 CMPDG partial로 파싱되는 건 2개뿐이고, 나머지 7개는 파서가 무시하는 OVERVIEW 안에만 있어 parse.py cdg가 원천이 사라진 드리프트로 잡았다. 근본 원인은 resolve_architecture_inputs가 아키텍처 원천을 partial 파일에서만 읽는다는 것 — OVERVIEW-only로 가자 읽을 partial 자체가 없어졌다. 파서가 partial이 없으면 OVERVIEW를 원천으로 읽도록 고쳤다. 드리프트로 잡히던 SDSP·PADX가 곧바로 무변화로 돌아섰고, -001을 유지하는 SUOMS나 partial 2개짜리 FDSP도 함께 통과했다. 전체 207 테스트 그린(22f1646).

둘 — 파일명은 바꿔도 파일 속 @startuml ID는 안 따라온다. PAIX에서 순번을 걷어내며 파일명·배너를 비순번으로 바꿨는데 렌더가 어긋났다. 파일이 스스로 부르는 이름 — PlantUML이 정체성으로 읽는 @startuml PAIX-CMPDG-ASLAYER-001 줄 — 이 아직 -001을 달고 있었다. 리네임 스크립트는 경로는 옮겨도 파일 안 텍스트엔 손이 닿지 않았다. @startuml ID 6건을 마저 맞추자 조합이 돌아왔다(4029e6f→c359b26).

규약을 사람이 지키게 두면, 도구는 그 규약을 드리프트로 읽는다. “구성요소 1개면 OVERVIEW만”은 사람 눈엔 깔끔한 정리지만 partial을 원천 삼던 파서 눈엔 “원천이 사라진 스키마”였고, “순번을 뗀다”는 파일명만 옮겼을 뿐 @startuml은 옛 이름으로 자기를 소개했다. 규약을 코드에 심는 일은 규칙 문서 한 줄이 아니라, 파서·리네임이 그 규칙대로 원천을 찾고 이름을 옮기게 만드는 일이다. 적용이 개발을 마저 끝냈다.

결정 3 — 반복해 걸린 사각, 그리고 순서가 곧 논리인 자리들

적용 국면엔 새로 고친 것만 있는 게 아니라, 아직 못 고쳐 또 걸린 것도 있었다.

생성기가 FK를 문자열로 읽는다 — 이번 주에만 세 번. SULAS·SUOMS ERD에서 관계선이 통째로 사라졌다(SULAS 5건, SUOMS 0개). 생성기는 물리 데이터의 FK를 필드 메타가 아니라 constraint 설명의 “FK” 문자열로 읽는다 — _FK_TARGET_RE가 “FK”/“references” + 대상 이름을 찾아야 crow’s-foot을 도출한다. FK가 데이터에 살아 있어도 설명에 키워드가 없으면 관계 없는 스키마였다. 그때마다 constraint: "FK → 대상(PK)"를 박아 메웠다(SUOMS 0721651, SULAS 36a9e48, 그리고 SFDG 신설 중 재발한 SULAS a355a24). 세 번 다 데이터로 땜질했고, 도구의 진짜 수정은 아직 백로그에 있다.

재업로드 전에 지우면 링크가 깨진다. 업로더(upload.py --diagrams)를 “대표 하나” 규약에 맞춰, 무-OVERVIEW 종류는 종류별 서브폴더 {단계}/diagrams/{kind}를 링크하도록 고쳤다(5e687c1). 그런데 옛 위치의 flat PNG 380개를 지우려던 순간 전제가 뒤집혔다 — per-kind 서브폴더가 Drive에 아직 없었다. 아무도 새 코드로 재업로드를 안 했으니 그 380개는 여전히 대장이 가리키는 live 이미지였다. 지금 지우면 대체 사본 없이 링크만 깨진다. 올바른 순서는 재업로드 먼저 → 그 다음 정리. 읽기 전용 조사만 하고 홀드했다.

정리의 입력을 정리 전에 지우면, 정리는 “지울 게 없다”가 아니라 **“지워도 되는 줄 안다”**로 답한다 — 위임 스크립트가 참조를 판정 전에 scrub하던 그 버그와 똑같은 결이다. “고아 PNG를 지운다”는 그 PNG가 고아가 된 뒤에만 참이다. 순서가 곧 논리다. 여기선 사람이 눈으로 잡았지만, 대장 링크와 실제 파일의 관계를 업로더가 알았다면 “재업로드 전 삭제”를 도구가 막았을 것이다 — 이게 다음 다듬기의 자리다.

결정 4 — 라운드트립이 가르는 두 세계

전수 적용의 대부분은 표시 전용 편집이라 라운드트립이 침묵했지만, SUOMS만은 결이 달랐다. 다이어그램 정리가 아니라 비행 업무의 계획·운용 국면을 재정의하는 일이 들어왔고(87ddb30), 안전 영역도 다시 그었다(8ee95a0). 국면을 다시 나누자 그에 매달린 원천이 통째로 움직였고 — 재채번·재생성·재렌더가 연쇄로 돌아, 라운드트립이 이번엔 [+0 -0 ~0]을 내지 않았다. 도구는 그 변화를 산출물 **23건(16 + 7)**의 개정으로 밀어냈다(b8e66f7·8024213).

결정 1과 결정 4는 같은 라운드트립 위에서 정반대로 갈린다. 표시 전용 편집엔 라운드트립이 침묵해야 맞고(그림만 만졌으니), 도메인 재정의엔 23건을 움직여야 맞다(원천이 바뀌었으니). 도구가 미더운 건 자동으로 뭔가를 많이 해서가 아니라, 언제 가만히 있어야 하고 언제 움직여야 하는지를 원천 기준으로 구분하기 때문이다. 같은 초록불이 한쪽에선 “안전하다”를, 한쪽에선 “빠짐없이 반영됐다”를 뜻한다 — 도구가 완성됐다는 건 이 구분을 사람이 아니라 도구가 한다는 뜻이다.

곁가지 — 재현성과 협업화: 파이프라인 바깥의 다듬기

적용 국면은 도구를 나 혼자 로컬에서 쓰던 단계에서 여럿이 협업하는 단계로 넓히는 준비이기도 했다.

  • 낡은 CI 렌더러 고정 — SDSP의 Bitbucket CI가 PlantUML 파싱 오류로 죽었다. .puml은 116줄인데 오류는 “line 452”를 가리켰다 — 원격 !include한 C4-PlantUML master가 최신 preprocessor 문법을 쓰기 시작했고, CI의 apt PlantUML은 2020년판(1.2020.02)이라 못 읽었다. 로컬(최신 jar)에선 멀쩡했으니 코드도 .puml도 아닌 렌더러가 낡은 것이다. apt를 걷어내고 최신 jar(1.2024.8)를 받아 실행하게 바꿔 CI 그린을 되찾았다(c63bd41). 편의(부동 include)와 재현성(고정 렌더러)은 한쪽만 챙기면 반드시 물린다.
  • 산출물에서 도구의 흔적 걷어내기 — 아홉 저장소를 훑어, 딸려 커밋돼 있던 CLAUDE.md와 .claude/ 작업 파일을 추적 해제하고 gitignore에 넣었다. 혼자 쓸 땐 문제가 아니었지만, 협업으로 넓히려면 도구의 로컬 스캐폴드가 납품물 저장소를 오염시켜선 안 된다. 산출물 저장소에는 산출물만 남아야 한다.
  • 새 프로젝트 PAIX를 백지에서 — 파블로항공 인텔리전스 플랫폼(PAIX) 제안서 초안(pptx)을 입력으로 전 단계 산출물을 병렬 서브에이전트로 신규 작성한 뒤, DFDG·SFDG 흐름도 10종(07c2909), 5개 영역의 물리 ERD(19bff41)와 유스케이스 다이어그램(0024a6c), logical/physical-data 1.1.0(f16178a)까지 붙였다. 다듬는 대상이던 도구가, 백지에서 산출물 골격을 세우는 쪽으로도 하루를 썼다.

마무리

이 주를 관통한 결은 하나였다 — 도구가 큰 틀에서 완성되자, 일의 무게가 “만들기”에서 “적용하며 다듬기”로 옮겨 갔다.

  • 규약 전수 적용 — OVERVIEW 대표화·거버넌스 분리·순번 제거를 아홉 저장소에 밀었다. 표시 전용이라 라운드트립 [+0 -0 ~0]이 매번 안전을 증명했다.
  • 적용이 끌어낸 도구 수정 — OVERVIEW-only를 드리프트로 읽던 파서를 고치고(22f1646, 207 테스트 그린), 리네임이 놓친 @startuml ID를 마저 맞췄다(4029e6f→c359b26). 규약을 코드에 심는 일이 곧 개발의 마지막 10%였다.
  • 반복 사각과 순서 버그 — 생성기가 FK를 문자열로 읽는 사각이 세 번 재발해 매번 데이터로 메웠고(0721651·36a9e48·a355a24), 업로더는 “재업로드 → 정리” 순서를 지켜 flat PNG 380개를 홀드했다.
  • 재정의는 침묵하지 않는다 — SUOMS 국면 재정의가 원천을 바꿔 산출물 23건을 재개정했다(b8e66f7·8024213). 표시 전용의 침묵과 정확히 대칭이다.
  • 협업화 준비 — 낡은 CI 렌더러를 고정하고(c63bd41), 도구 흔적(CLAUDE.md·.claude)을 걷어내고, 새 프로젝트 PAIX를 백지에서 세웠다.

다음에 할 것 (도구 백로그):

  • 생성기 FK 도출을 필드 수준으로 — 이번 주에만 세 번 걸린 그 사각. constraint 문자열 의존을 걷어내고 FK 메타 필드에서 직접 관계를 도출한다. 겸사겸사 렌더 검증에 고립 엔티티 점검을 넣어, 관계선이 편집 중 조용히 사라지는 일을 검증 단계가 잡게 한다. 다듬기의 우선순위 맨 앞이다.
  • 렌더 전 이름 일치 점검 — 파일명·배너·@startuml ID·include alias가 같은 이름을 부르는지 한 자리에서 확인해, 사람 눈으로 잡은 어긋남을 절차로 막는다.
  • flat PNG 재업로드 + 정리 실행 — 9개 프로젝트를 render → upload --diagrams --force로 종류별 서브폴더를 채운 뒤, 그때 비로소 고아가 된 PNG를 정리한다.
  • 부동 include의 렌더러 고정 전수 — SDSP만 고친 CI jar 교체를, master C4 include를 쓰는 다른 저장소에도 마저 반영한다.

Comments

Content