이 글은 2026-06-29 하루 동안
artifact-transformer와 그 산하 일곱 도메인 저장소(SULAS·SUOMS·PADX·IAMS·SUGCS·LORAS·FDSP)에서 흩어진 것을 한 줄기로 모은 작업 기록이다. 제각각이던 개정 이력을 1.0.x 한 줄기로, partial 조각들을 OVERVIEW로, 남처럼 그려져 있던 Keycloak을 IAMS 안으로 모았다. 그리고 그 와중에 — 환원해도 되살아나는 가짜 엔티티를, 도출 경로 자체에 가드를 박아 막았다.
배경
artifact-transformer는 Jira 이슈와 PlantUML 다이어그램을 입력으로 받아 요구사항·유스케이스·기능·시퀀스 명세서와 데이터 정의서/명세서 등을 docx/xlsx로 자동 생성·역파싱하는 도구다 (#4 참조).
#19에서 경계를 긋고, #20에서 무엇을 한 단위로 볼지를 바로잡았다. C4를 boundary로 쪼개 OVERVIEW로 묶는 구조를 도구에 들였고, 유스케이스를 사용자 목표 단위로 통합했다. 그날들에 남긴 빚은 분명했다 — boundary 분할 구조를 잔여 저장소까지 전개할 것, 그리고 그 구조에 맞춰 흩어진 산출물의 단위를 마저 정리할 것.
오늘은 그 전개의 날이었다. #19가 나누는 날, #20이 가르는 날이었다면, 오늘은 그 경계와 단위에 맞춰 흩어진 것들을 한 줄기로 모으는 날이다. 그리고 늘 그렇듯 도메인을 들여다보니 도구가 아직 못 막는 구멍이 보였고 — 그래서 오늘도 도메인 바깥과 도구 안쪽을 번갈아 손댔다.
문제
손대기 전, 네 결의 어긋남이 보였다.
- 개정 이력이 저장소마다 제각각이었다 — 어떤 곳은 patch만 올라야 할 자리에 minor가 잘못 올라가 있었고(LORAS·SUGCS), 어떤 곳은 1.0.x 형태조차 아니었으며, 같은 날짜의 변경이 여러 줄로 흩어져 있었다.
- 다이어그램이 partial 조각으로만 흩어져 있었다 — 쪼갠 조각은 있는데 그걸 묶는 OVERVIEW가 없었고,
*-COM-001명명이 그대로 남아 “무엇이 대표 그림인가”가 파일 구조로 드러나지 않았다. - Keycloak이 IAMS 바깥의 남처럼 그려져 있었다 — #19에서 “Keycloak은 Keycloak 소관”으로 갈라 보냈지만, 이 도메인에서는 keycloak = iams다. 인증의 구현이 곧 IAMS의 실체인데, 산출물 어디에도 그 사실이 반영돼 있지 않았다.
- ERD·물리 데이터에 빈 스키마 엔티티가 비정상 생성돼 있었다 — FDSP·IAMS에서 도출 단계가 벤더가 관리할 데이터를 자꾸 되살려 빈 엔티티로 찍어 놨다.
결정 1 — 개정 이력을 1.0.x 한 줄기로, 같은 날짜는 한 건으로
아침은 일곱 저장소의 개정 이력을 한 형태로 맞추는 일이었다.
- patch만 올려 최종 1.0.x로 통일했다(SULAS·SUOMS·PADX·IAMS·LORAS). LORAS는 minor가 잘못 올라가 있어 1.0.x patch 줄기로 되돌렸고, 아키텍처를 바꾼 SUGCS만 1.1.0부터 새 줄기를 세웠다.
1.0.0의 서술을 “최초 작성”으로 통일했다. 첫 줄이 저장소마다 다른 말로 적혀 있으면, 이력표는 “언제부터의 기록인가”라는 기준점을 잃는다.- 같은 날짜의 변경은 한 건으로 통합하고, 결합된 설명을 더 간결하게 다듬었다.
개정 이력의 한 줄은 리프 경로의 나열이 아니라 의미 요약이다. 같은 날 손댄 걸 한 줄로 묶고 말을 줄이는 건 게으름이 아니라, 이력표를 커밋 로그의 사본이 아닌 “무엇이 언제 바뀌었나”의 색인으로 되돌리는 일이다.
결정 2 — partial을 OVERVIEW로 묶는다: L1은 OVERVIEW, L2는 시스템별, L3은 컨테이너별
#19에서 만든 boundary 분할 구조의 잔여 저장소 전개다. 규약을 한 줄로 못박았다.
- 1종만 있으면 OVERVIEW 단독, 2종 이상이면 import로 취합하는 OVERVIEW. 아키텍처는 레벨1은 OVERVIEW만, 레벨2는 시스템별, 레벨3은 컨테이너별로 생성한다.
- 그 규약에 맞춰
*-COM-001명명을*-OVERVIEW로 정규화했다 — PADX의 BCDG·CTXDG·CNTDG를 OVERVIEW로, CMPDG는PADX-CMPDG-API로 쪼갠 뒤 OVERVIEW를 더했고, BPDG에도 OVERVIEW를 신설했다. SUGCS는 레벨3에 APP을 import하는 OVERVIEW를 두고, 엉뚱하게 박혀 있던 CMPDG-APP 배너 id를 바로잡았다.
OVERVIEW를 만드는 건 그림을 하나 더 그리는 게 아니다. 무엇이 대표이고 무엇이 그 안의 조각인가를 파일 구조로 못박아, 한 조각만 따로 보든 전체를 합쳐 보든 같은 경계가 보이게 하는 일이다.
*-COM-001은 “공통”이라는 이름 뒤에 그 위계를 숨기고 있었다.
결정 3 — Keycloak은 남이 아니다: IAMS 안으로 흡수
오늘의 가장 큰 도메인 작업이자, #19에서 그은 선 하나를 다시 안으로 들인 결정이다.
#19에서는 “Keycloak 스키마는 Keycloak 소관”이라며 외부로 갈라 보냈다. 하지만 이 도메인에서 Keycloak은 IAMS의 구현 그 자체다 — 인증·인가를 실제로 떠받치는 엔진이 곧 IAMS라는 도메인의 실체이지, 옆에 선 외부 시스템이 아니다. 그래서 keycloak을 IAMS 안의 경계로 들이고, 그 사실을 산출물 전반에 내렸다.
- 모든 표현에 keycloak을 반영했다 — CDG·시퀀스·BPDG·DFDG·UCDG·BCDG, 그리고
IAMS-CMPDG-API-001까지. 다만 core 내부는 참조로만 표시했다. keycloak 경계 안에서 core를 통째로 다시 그리지 않고, 참조 관계로만 가리킨다. - CNTDG를
IAMS-CNTDG-OVERVIEW로 묶으며 Web Server·Web App 컨테이너를 제거했다(현 아키텍처에 불필요), 그 변경을 영향받는 모든 산출물에 전파했다. - 시험 산출물도 따라왔다. keycloak 융합이 단위 시험에 미치는 영향성을 검토하고, ITC/ATC 13건을 재분류했다 — 방안 A·B·C를 차례로 적용하며 통합/인수 시험의 단위를 keycloak 경계에 맞췄다. 운영·시험 산출물과 ASC 플랫폼 노트까지 같은 손으로 갱신했다.
- 그리고 init은 “돌려도 문제없게” — keycloak 엔티티를 지우는 식이 아니라, 두 init를 다시 돌려도 안전하도록 손봤다(아래 함정과 한 뿌리).
경계를 긋는 일(#19)과 흡수하는 일(#21)은 반대가 아니라 같은 질문의 양면이다 — “이 구조는 누구의 책임인가.” 인증을 데이터 플랫폼에서 걷어내 IAMS로 보낸 것과, Keycloak을 IAMS 안으로 들인 것은 모순이 아니라 같은 원칙의 두 적용이다. 책임의 주인을 찾으면, 어떤 건 밖으로 나가고 어떤 건 안으로 들어온다.
결정 4 — FDSP ETL을 정석 구조로, CMPDG는 컨테이너별로
오후의 한 축은 FDSP·SUGCS의 데이터 흐름을 정석으로 되돌리는 일이었다.
- FDSP-CMPDG-ETL-001의 Ingestion·Storage 컴포넌트를 검토하고, 일반적인 ETL 데이터 파이프라인과 제공 시스템의 정석 구조를 반영했다. 다이어그램을 원천으로 고치고, 배너 버전 stamp를 올렸다.
- CMPDG를 영역별이 아니라 컨테이너별로 다시 작성했다 — 현 FDSP 아키텍처에선 API 1개로 충분하다. #20에서 컴포넌트를 기능 영역 단위로 보강한 결의 연장이되, 컨테이너가 하나면 그 하나로 묶는 게 맞다.
- 묶고 나니 CMPDG-OVERVIEW가 렌더링되지 않았다(PlantUML Syntax Error). 단독 렌더로 오류를 좁혀 고쳤다 — SUGCS의 CMPDG-OVERVIEW도 같은 증상이라 함께 잡았다.
- SUGCS는 데이터 모델도 정석으로 맞췄다. 물리 데이터의 물리명이 곧 엔티티 이름이 되도록 ERD·논리/물리 데이터의 전체 흐름을 다시 보고, FK 관계선과 DAT camelCase를 정석대로 정리했으며,
models같은 레거시 산출물을 걷어냈다.
의도치 않은 함정
오늘의 헛디딤은 하나였지만, 두 번 되살아났다.
FDSP·IAMS의 ERD·물리 데이터에 빈 스키마 엔티티가 비정상적으로 생성돼 있었다. 환원했더니 — 다시 생겼다. “방금 또 생성됐다, 왜?”를 추적하니, 범인은 init이 아니라 publish·도출(derivation) 단계였다. 큐레이트한 정본 위에 도출이 벤더가 관리할 데이터를 매번 다시 얹어, 빈 엔티티로 정본을 덮어쓰고 있었다.
일회성 환원으로 끝내지 않고 도구에 세 겹 가드를 박았다 — 결정적 단계는 사람의 손질이 아니라 도구가 책임진다는 #13의 연장이다.
- logical 도출에
externalDataNames제외 목록을 둬, 벤더 관리 데이터가 다시 끼어들지 못하게 했다(053d0e0). - 도출 JSON 재도출 가드 —
--force없이는 큐레이트 정본을 덮어쓰지 않는다(8a0bd3d). - 그 가드를 소스 함수로 내려,
generate·publish경로까지 함께 차단했다(0af7368).
그리고 메모리에 재발 사실을 갱신해, 같은 증상이 다음에 또 떠도 “이미 본 함정”으로 잡히게 했다.
같은 오염이 환원 뒤에도 되살아난다면, 그건 데이터의 문제가 아니라 그 데이터를 만드는 경로의 문제다. 한 군데(init)만 막으면 다른 경로(publish)가 다시 연다. 가드는 진입점 하나가 아니라 소스 함수에 박아야, 그 함수를 부르는 모든 경로가 한꺼번에 닫힌다.
곁가지로, IAMS-BCDG-OVERVIEW는 글자와 선이 중첩돼 읽기 어려웠다 — 레이아웃을 풀어 가독성을 회복했다. 묶는 일(OVERVIEW)이 곧 보기 좋은 그림을 보장하진 않는다는, 작은 되새김이었다.
마무리
오늘 관통한 결은 “흩어진 것을 한 줄기로 모으는 것” 이었다.
- 개정 이력을 1.0.x 한 줄기로 — patch만 올려 통일,
1.0.0=최초 작성, 같은 날짜는 한 건으로(SUGCS만 1.1.0 새 줄기). - partial을 OVERVIEW로 — L1=OVERVIEW, L2=시스템별, L3=컨테이너별 규약화,
*-COM-001 → *-OVERVIEW정규화. - Keycloak을 IAMS 안으로 — keycloak=iams를 모든 산출물에 반영(core는 참조만), Web Server/Web App 제거, ITC/ATC 13건 재분류.
- ETL을 정석 구조로, CMPDG를 컨테이너별로 — FDSP 파이프라인 표준화, 렌더링 오류 수정, SUGCS 물리명=엔티티명·FK·camelCase 정리.
- 되살아나는 벤더 엔티티를 도출 가드로 — 제외 목록·재도출 가드·소스 함수 차단의 세 겹, 그리고 메모리에 재발 기록.
#19가 경계를 긋고 #20이 단위를 바로잡은 날이라면, 오늘은 그 경계와 단위에 맞춰 흩어진 산출물을 한 줄기로 모은 — 전개와 수렴의 날이었다. 도구는 그 과정에서 도출 경로의 세 겹 가드를 얻었고, 나는 “한 군데를 막아도 다른 경로가 다시 연다”는 교훈을 가드 한 줄로 박아 뒀다.
다음에 할 것:
- Keycloak 흡수 잔여 전파 — ITC/ATC 재분류와 keycloak 반영을 영향받은 모든 산출물에 검증 게이트로 끝까지 재확인한다.
- 개정 이력 통합 규약화 — “같은 날짜 1건”을 사람 판단이 아니라
revise.py단계에서 자동으로 묶는다. - 도출 가드 회귀 검증 —
publish·generate를 다시 돌려도 가짜 엔티티가 안 생기는지를 정기 점검에 박아, 사람 기억이 아니라 절차로 막는다.