---
template: policy-doc@1
doc_id: 02-identifier-namespaces
title: 코드 식별자 네임스페이스 — 다섯 갈래 · 서브레벨 접미 · 메뉴 코드 이중 소스
config: ../_meta/template-config.yaml
last_verified: 4d798f55
policies:
  - id: NAMESPACE_PARTITION
    status: active-prod
    evidence: [S-constant, S-contract]
    limitations:
      - 각 갈래의 코드 전수는 이 문서가 담지 않는다. 전수는 ../_meta/index/codes/ 의 파일들이 소유한다
      - 갈래를 나누는 규칙이 옳은가는 이 문서의 범위 밖이다. 이 문서는 정본이 정한 분할을 옮길 뿐이며 분할 자체의 소유자는 ../_meta/extraction-manifest.yaml 이다
    anchors:
      - insuniverse-server/apps/api/src/constants/admin.constant.ts:11
      - insuniverse-server/apps/api/src/modules/analyze/analyze.dto.ts:38
      - insuniverse-server/apps/api/src/modules/treat-test/reference/mapping-reference.ts:227
      - insuniverse-admin/src/app/router/index.ts:7
      - insuniverse-admin/src/features/authority/constants/menu.ts:14
  - id: SYMBOL_JOIN_KEY
    status: active-prod
    evidence: [S-constant, S-contract]
    limitations:
      - 같은 코드값을 쓰는 두 선언이 정말 다른 뜻인가는 기계가 판정하지 못한다. 이 문서는 중복이 실재한다는 사실까지만 쓴다
    anchors:
      - insuniverse-server/apps/api/src/constants/admin.constant.ts:18
      - insuniverse-server/apps/api/src/constants/admin.constant.ts:63
      - insuniverse-server/apps/api/src/constants/api.constant.ts:40
      - insuniverse-server/apps/api/src/constants/client.constant.ts:41
      - insuniverse-server/apps/api/src/constants/api.constant.ts:16
      - insuniverse-server/apps/api/src/constants/admin.constant.ts:58
      - insuniverse-server/apps/api/src/modules/analyze/analyze.dto.ts:38
      - insuniverse-server/apps/api/src/modules/analyze/analyze.dto.ts:64
  - id: SUBLEVEL_SUFFIX
    status: active-prod
    evidence: [S-contract, S-constant]
    limitations:
      - 서브레벨이 앞으로 어느 코드까지 넓어질지는 알 수 없다. 지금 관측되는 것은 두 개뿐이다
    anchors:
      - insuniverse-site/front/src/features/analysisDetailView/constants/analysisDetail.const.ts:15
      - insuniverse-site/front/src/features/analysisDetailView/constants/analysisDetail.const.ts:24
      - insuniverse-server/apps/api/src/modules/analyze/analyze.dto.ts:38
  - id: SCREEN_CODE_DERIVED
    status: active-prod
    evidence: [S-route, S-component]
    limitations:
      - 파생 규칙이 바뀌면 화면 코드 집합 전체가 바뀐다. 정본 매핑이 제품 안에 생기면 이 규칙은 교체 대상이다
    anchors:
      - insuniverse-admin/src/app/router/index.ts:7
      - insuniverse-admin/src/app/router/index.ts:11
      - insuniverse-admin/src/app/router/index.ts:18
      - insuniverse-admin/src/app/router/routes/page.routes.tsx:46
      - insuniverse-admin/src/app/router/routes/page.routes.tsx:35
  - id: MENU_CODE_DB_ENUMERATION
    status: data-dependent-unknown
    unknown_reason: 2단계 메뉴 전수가 운영 DB 에만 있고 저장소에는 증분 등록문만 있다. 조회 시점에 확보한 열거분 밖은 값을 지어내지 않고 미상으로 남긴다
    evidence: [S-schema, S-constant]
    limitations:
      - 이 정책은 코드가 무엇인가만 다룬다. 그 코드가 누구에게 배분되는가는 ../02-access/04-authz-db-menu.md 소관이다
    anchors:
      - insuniverse-server/drizzle/schema.ts:1573
      - insuniverse-server/drizzle/0027_loss_analysis.sql:48
      - insuniverse-admin/src/features/authority/constants/menu.ts:14
      - insuniverse-admin/src/features/authority/constants/menu.ts:205
---

# 코드 식별자 네임스페이스 — 다섯 갈래 · 서브레벨 접미 · 메뉴 코드 이중 소스

이 문서는 제품이 쓰는 **코드 식별자가 몇 갈래이고 각 갈래가 무엇을 가리키는가**를 정한다. 갈래마다 값의 생김새가 다르고, 한 갈래 안에서 같은 값이 두 번 이상 쓰인다는 사실까지가 여기 있다.

각 갈래의 **코드 전수**는 여기 없다 — `../_meta/index/codes/` 의 파일들이 소유하며 이 문서는 링크만 건다. 에러 코드의 기능 블록 규칙은 `03-error-codes.md` 가 맡는다. 메뉴 코드가 **누구에게 배분되는가**도 여기 없다 — 이 문서는 메뉴 코드가 무엇인지만 쓰고, 배분은 `../02-access/04-authz-db-menu.md` 소관이다.

## 정책 (기획)

### NAMESPACE_PARTITION

코드 식별자는 다섯 갈래로 나뉜다. 갈래를 나누는 이유는 값의 출처가 서로 다르기 때문이다 — 어떤 갈래는 저장소 안의 상수 파일에서 100% 확정되고, 어떤 갈래는 화면 구성에서 만들어지며, 한 갈래는 운영 데이터베이스에만 전수가 있다. 갈래를 섞으면 "이 값이 어디서 왔는가" 를 물을 수 없게 된다.

| 갈래 | 무엇을 가리키나 | 값의 예 | 전수를 갖는 자리 |
|---|---|---|---|
| 에러 코드 | 요청이 실패했을 때 응답에 실리는 실패 사유 | `E0101` | `../_meta/index/codes/error.yaml` |
| 도메인 상태 코드 | 분석 항목 · 회원 종류 · 주문 상태처럼 업무상 갈래를 나타내는 값 | `ANS003` · `MEM002` | `../_meta/index/codes/domain_status.yaml` |
| 벤더 코드 | 외부 연동사가 돌려주는 결과 값 | `CF-00000` | `../_meta/index/codes/vendor.yaml` |
| 화면 코드 | 운영사 콘솔의 화면 하나를 가리키는 값 | `admin:/manage/login` | `../_meta/index/codes/screen.yaml` |
| 메뉴 코드 | 사이드바에 서는 메뉴 항목 하나를 가리키는 값 | `SEC001` · `CRP_ORG001` | `../_meta/index/codes/menu_hardcoded.yaml` · `../_meta/index/codes/menu_db.yaml` |

**여섯 번째 갈래처럼 보이는 이름이 둘 있다. 둘 다 갈래가 아니다.**

| 이름 | 지위 |
|---|---|
| `fields_per_code` | 갈래가 아니라 **한 코드 항목이 갖는 필드 목록**이다. 갈래마다 이 필드들을 채운다 |
| `_unclassified` | 갈래가 아니라 **어느 갈래에도 맞지 않은 값을 모아 두는 자리**다. 정본에 이름이 없고, 여기 남아 있다는 것 자체가 미분류라는 뜻이다 |

**기업 담당자 콘솔의 메뉴 코드(`CRP_` 로 시작하는 값)는 별도 갈래가 아니다.** 메뉴 코드 갈래가 두 가지 생김새를 함께 받도록 정의돼 있고 `CRP_ORG001` 은 그중 뒤쪽 생김새에 해당한다. 별도 갈래로 세면 갈래가 여섯이 되고, 그 순간 메뉴 코드의 전수 계산이 두 곳으로 갈린다.

### SYMBOL_JOIN_KEY

**같은 코드값이 서로 다른 뜻으로 여러 번 선언돼 있다.** 한 파일 안에서도 그렇고 파일을 건너서도 그렇다. 그래서 코드값 하나를 들고 "이게 무슨 뜻이냐" 고 물으면 답이 하나로 정해지지 않는다.

조회의 키는 코드값이 아니라 **선언이 어느 파일의 어느 이름인가** 하는 쌍이다. 문서·인덱스·대화 어디서든 코드값만 말하면 상대가 다른 선언을 떠올릴 수 있으므로, 값과 함께 그 값이 선언된 자리를 같이 말한다.

반대 방향도 성립한다 — **이름이 같아도 값이 다르다.** 두 상수 파일에 같은 이름의 선언이 있고 코드값은 서로 다르다. 이름으로 조인해도 값으로 조인해도 성립하지 않는다는 것이 이 정책의 내용이다.

에러 코드 축에서 이 규칙이 어떻게 나타나는지는 `03-error-codes.md` 가 사례로 쓴다.

### SUBLEVEL_SUFFIX

도메인 상태 코드는 세 자리 숫자 뒤에 **대문자 한 자를 더 붙여 하위 갈래를 나눌 수 있다.** 갈래 정의가 그 자리를 이미 열어 두고 있으므로 접미가 붙은 값도 정상 값이다.

지금 실제로 쓰이는 것은 분석 상세 화면의 두 하위 갈래뿐이다 — 5년 내 7일 이상 치료 정보와 5년 내 30일 이상 투약 정보다. 원래 한 항목이던 것을 화면에서 둘로 나누면서 생겼다.

**그런데 이 둘은 코드 사전에 항목이 없다.** 서버가 이 두 값을 선언하지 않기 때문이다 — 값은 화면 쪽 표시 설정 표의 키로만 존재하고, 키는 조회하는 자리이지 선언하는 자리가 아니다. 코드 사전의 항목은 선언을 근거로 만들어지므로 이 둘은 사전에 실리지 못한다. **코드값 기준으로 세면 잡히고 항목 기준으로 세면 안 잡힌다** — 두 수를 같은 것으로 보면 사전이 빠뜨린 것처럼 읽힌다.

### SCREEN_CODE_DERIVED

**화면 코드라는 값은 제품 안에 존재하지 않는다.** 화면을 가리키는 리터럴이 코드 어디에도 없고, 화면의 정체는 그 화면으로 가는 주소가 정한다.

그래서 화면 코드는 **주소 목록에서 만들어낸다.** 콘솔은 로그인한 종류에 따라 서로 다른 주소 묶음을 붙이므로, 만들어진 값은 어느 묶음의 주소인가와 주소 자체를 함께 담는다. 주소에 들어가는 식별자 자리는 이름이 무엇이든 하나로 접는다 — 화면의 정체가 식별자 이름에 의존하지 않게 하기 위해서다.

이 규칙은 정본 매핑이 생기기 전까지의 한시 규칙이다. 규칙이 바뀌면 값 전체가 바뀌므로, 규칙과 그 결과 전수·해시를 함께 동결해 둔다.

## 강제 지점 (개발)

### NAMESPACE_PARTITION

- 강제 방식: 갈래별 정규식이 `../_meta/extraction-manifest.yaml` `code_namespaces` 에 동결돼 있고, `../_meta/verify/verify-code-index.mjs` 가 인덱스 항목마다 자기 갈래 정규식 적합과 **다른 갈래 정규식 부적합**을 양방향으로 판정한다.
- 아래는 그 정본의 원문이다. 이 문서가 다시 쓴 것이 아니라 옮긴 것이며, 갈래 이름과 정규식이 정본과 문자열로 같은지는 계획서 게이트 `#4` 가 대조한다.

```text
error_codes          ^E[0-9]{4}$
domain_status_codes  ^(ANS|ODD|SUB|PAY|MEM|PRD|BRD|IVC|LSA|REF|SND|POP|BNN|INS|ADL|ADT|APT)[0-9]{3}[A-Z]?$
vendor_codes         ^(CF|CODEF|COOCON|HYPHEN|OCTOVER)[-_A-Z0-9]+$
screen_codes         ^(admin|sales|corp):\/(?:[A-Za-z0-9][A-Za-z0-9-]*|:param)?(?:\/(?:[A-Za-z0-9][A-Za-z0-9-]*|:param))*$
menu_codes           ^(?:[A-Z][A-Z0-9]{2}[0-9]{3}|(?:MNU|CRP)_[A-Z0-9]+(?:_[A-Z0-9]+)*)$
```

- `fields_per_code` 는 위 목록에 없다. 정본에서 그 키의 값은 정규식이 아니라 필드 이름 목록(`defined_in` · `consumed_by` · `serialized` · `persisted` · `active_reference_count` · `parent`)이며, 갈래로 세면 다섯이 여섯이 된다.
- `_unclassified` 도 위 목록에 없다. 정본에 키 자체가 없고, `../_meta/index/codes/_unclassified.yaml` 은 검증기가 **정규식을 반대로 적용**하는 파일이다 — 어느 갈래 정규식에도 맞지 않아야 그 파일에 있을 수 있다.
- `CRP_` 접두는 `menu_codes` 정규식의 뒤쪽 대안(`(?:MNU|CRP)_[A-Z0-9]+(?:_[A-Z0-9]+)*`)이 덮는다. 여섯 번째 갈래가 아니다.
- 갈래별 선언 자리 — 에러 코드 `insuniverse-server/apps/api/src/constants/admin.constant.ts:11` · 도메인 상태 코드 `insuniverse-server/apps/api/src/modules/analyze/analyze.dto.ts:38` · 벤더 코드 `insuniverse-server/apps/api/src/modules/treat-test/reference/mapping-reference.ts:227` · 화면 코드 `insuniverse-admin/src/app/router/index.ts:7` · 메뉴 코드 `insuniverse-admin/src/features/authority/constants/menu.ts:14`

### SYMBOL_JOIN_KEY

- 강제 방식: 코드 인덱스의 조인 키가 `<namespace>:<symbol>` 이며 `symbol` 은 **저장소 한정 모듈 경로 + 선언 체인**이다. `../_meta/verify/verify-code-index.mjs` 가 그 유일성을 강제하고, 앵커 판정의 대조 토큰도 코드값이 아니라 심볼의 지역 식별자다.
- 같은 코드값 · 다른 선언 — `E0202` 가 네 자리에 있다. `insuniverse-server/apps/api/src/constants/admin.constant.ts:18` (계약 기간 중복) · `insuniverse-server/apps/api/src/constants/admin.constant.ts:63` (조직 내 활성 계약 중복) · `insuniverse-server/apps/api/src/constants/api.constant.ts:40` (이용기간 만료·수량 초과) · `insuniverse-server/apps/api/src/constants/client.constant.ts:41` (처리 중 오류)
- 같은 이름 · 다른 코드값 — `UNAUTHORIZED` 가 두 파일에서 서로 다른 값을 갖는다. `insuniverse-server/apps/api/src/constants/api.constant.ts:16` 은 `E0001`, `insuniverse-server/apps/api/src/constants/admin.constant.ts:58` 은 `E0601` 이다.
- 도메인 상태 축도 같다 — 같은 이름의 열거가 한 파일 안에 두 벌 있고 둘 다 `ANS003` 을 담는다. `insuniverse-server/apps/api/src/modules/analyze/analyze.dto.ts:38` · `insuniverse-server/apps/api/src/modules/analyze/analyze.dto.ts:64`
- 이 축의 에러 코드 사례 전개는 `03-error-codes.md` `ERROR_CODE_NOT_UNIQUE` 가 맡는다.

### SUBLEVEL_SUFFIX

- 강제 방식: 갈래 정규식의 `[0-9]{3}[A-Z]?` 접미가 서브레벨 자리를 연다. 서버 열거에는 접미 없는 `ANS003` 만 있고(`insuniverse-server/apps/api/src/modules/analyze/analyze.dto.ts:38`), 접미가 붙은 두 값은 화면 표시 설정 표의 맨 객체 키다.
- `ANS003A` — `insuniverse-site/front/src/features/analysisDetailView/constants/analysisDetail.const.ts:15`
- `ANS003B` — `insuniverse-site/front/src/features/analysisDetailView/constants/analysisDetail.const.ts:24`
- 맨 객체 키는 선언이 아니라 등장이라 조인 키를 만들 심볼이 없다. 그래서 `../_meta/index/codes/domain_status.yaml` 의 어느 항목도 이 두 코드값을 갖지 않으며, 그 파일 헤더의 `gap` 이 두 값을 심볼 없는 등장으로 명시한다. 앵커 실재와 인덱스 항목 부재를 함께 보는 것이 계획서 게이트 `#8` 이다.

### SCREEN_CODE_DERIVED

- 강제 방식: 파생 규칙이 산문이 아니라 추출기 코드에 있다. `../_meta/verify/extract-screen-codes.mjs` 가 라우터 진입 파일이 실제로 불러오는 주소 모듈만 따라가고, 그 결과 전수와 해시를 `../_meta/extraction-manifest.yaml` `code_namespaces.screen_codes` 가 동결한다.
- 라우터 3벌 — `insuniverse-admin/src/app/router/index.ts:7` (admin) · `insuniverse-admin/src/app/router/index.ts:11` (sales) · `insuniverse-admin/src/app/router/index.ts:18` (corp). 셋 다 팝업 주소 묶음을 먼저 주입한 뒤 자기 묶음을 잇는다.
- 주소와 화면이 한 자리에서 만나는 형태 — `insuniverse-admin/src/app/router/routes/page.routes.tsx:46`
- 환경 변수로만 등록되는 숨김 주소가 하나 있다 — `insuniverse-admin/src/app/router/routes/page.routes.tsx:35`. 소스에 있으므로 집합에 포함되며, 운영 환경 런타임에는 없다.

### MENU_CODE_DB_ENUMERATION

- 강제 방식: 두 소스가 각각 다른 층에서 강제한다. 운영 DB 쪽은 테이블 컬럼(`insuniverse-server/drizzle/schema.ts:1573`)이고, 저장소 쪽은 프론트 상수 배열이다.
- DB 축의 증분 등록문 — `insuniverse-server/drizzle/0027_loss_analysis.sql:48`. 저장소에는 이런 증분만 있고 기준 시드가 없다. 그래서 전수가 저장소에서 복원되지 않는다.
- 상수 축 — 영업대리점 메뉴 `insuniverse-admin/src/features/authority/constants/menu.ts:14` · 기업 담당자 메뉴 `insuniverse-admin/src/features/authority/constants/menu.ts:205`. 이 축은 저장소에서 100% 확정된다.
- 확보 상태의 수치는 `## 부록` 의 수치 출처 표가 정본 키와 함께 싣는다.

## 적용 범위 (actor × 서비스)

| 정책 id | server | site | admin |
|---|---|---|---|
| NAMESPACE_PARTITION | 에러 · 도메인 상태 · 벤더 선언 | 도메인 상태 소비 | 화면 · 메뉴 선언 |
| SYMBOL_JOIN_KEY | 중복 선언이 실재하는 자리 | — | — |
| SUBLEVEL_SUFFIX | 접미 없는 상위 값만 선언 | 접미 붙은 두 값의 등장 자리 | — |
| SCREEN_CODE_DERIVED | — | — | 파생 입력(라우터 3벌) |
| MENU_CODE_DB_ENUMERATION | DB 컬럼 · 증분 등록문 | — | 상수 축 두 벌 |

`—` = 그 서비스가 이 정책의 경로에 등장하지 않음.

이 표의 열은 서비스 3종이며 actor 는 열이 아니다. 코드 식별자는 로그인 주체별로 갈리지 않고 **서비스별로** 선언·소비 위치가 갈린다.

## 예외·폴백

| 정책 id | 예외 조건 | 폴백 동작 | 확인 근거 |
|---|---|---|---|
| NAMESPACE_PARTITION | 값이 다섯 갈래 정규식 어디에도 맞지 않을 때 | 갈래를 새로 만들지 않고 미분류 자리에 남긴다 | `../_meta/index/codes/_unclassified.yaml` |
| NAMESPACE_PARTITION | `CRP_` 접두 메뉴 코드를 별도 갈래로 세려 할 때 | 세지 않는다. 메뉴 코드 정규식의 뒤쪽 대안이 이미 덮는다 | `insuniverse-admin/src/features/authority/constants/menu.ts:205` |
| SYMBOL_JOIN_KEY | 코드값만으로 조회할 때 | 답이 하나로 정해지지 않는다. 선언 자리를 함께 지정해야 한다 | `insuniverse-server/apps/api/src/constants/admin.constant.ts:63` |
| SYMBOL_JOIN_KEY | 심볼 이름만으로 조회할 때 | 같은 이름이 다른 값을 갖는 자리가 실재한다 | `insuniverse-server/apps/api/src/constants/admin.constant.ts:58` |
| SUBLEVEL_SUFFIX | 접미가 붙은 값을 코드 사전에서 찾을 때 | 항목이 없다. 등장은 있으나 선언이 없어 심볼이 서지 않는다 | `insuniverse-site/front/src/features/analysisDetailView/constants/analysisDetail.const.ts:15` |
| SCREEN_CODE_DERIVED | 주소에 파라미터 자리가 있을 때 | 이름과 무관하게 한 형태로 접는다 | `../_meta/extraction-manifest.yaml` `code_namespaces.screen_codes.rules` |
| SCREEN_CODE_DERIVED | 환경 변수로만 등록되는 숨김 주소 | 소스에 있으므로 집합에 포함한다. 운영 런타임에는 없다 | `insuniverse-admin/src/app/router/routes/page.routes.tsx:35` |
| MENU_CODE_DB_ENUMERATION | 2단계 메뉴 전수를 저장소에서 복원하려 할 때 | 복원되지 않는다. 증분 등록문만 있고 기준 시드가 없다 | `insuniverse-server/drizzle/0027_loss_analysis.sql:48` |
| MENU_CODE_DB_ENUMERATION | 인증 없이 열린 메뉴 조회 경로로 전수를 채우려 할 때 | 쓰지 않는다. 결함을 상시 데이터 의존으로 굳히지 않는다 | `../_meta/extraction-manifest.yaml` `code_namespaces.menu_codes.db.not_used_source` |

## 부록

이 절의 정책은 **전수가 저장소 밖에 있어 현행 값을 판정하지 못한다.** 확보한 것은 열거 일부뿐이고 나머지는 미상이다. 그 상태로 본문에 두면 독자가 확정된 목록으로 읽는다. 전수가 확보되면 상태가 바뀌고 배치도 함께 본문으로 옮긴다.

### MENU_CODE_DB_ENUMERATION

메뉴 코드의 전수는 **한 곳에서 나오지 않는다.** 관리자 콘솔의 메뉴는 운영 데이터베이스가 소스라 저장소에서 값을 고정할 수 없고, 영업대리점과 기업 담당자의 메뉴는 화면 코드 안의 상수 배열이라 저장소에서 100% 확정된다.

저장소가 확보한 것은 운영 데이터베이스 2단계 메뉴 전수 중 일부다. 나머지는 **값을 지어내지 않고 미확보로 둔다.** 확보분과 미확보분의 수치는 아래 수치 출처 표가 정본 키와 함께 싣는다.

이 정책은 메뉴 코드가 **무엇인가**만 다룬다. 그 코드가 어느 권한 그룹에 배분되는가는 `../02-access/04-authz-db-menu.md` 소관이며, 그 축의 미확보 범위는 이 문서가 판정하지 않는다.

#### 수치 출처

아래 표는 **이 문서가 세어서 쓴 값과 그 값을 동결한 정본 키의 대응**이다. 각 행의 키를 `../_meta/extraction-manifest.yaml` 에서 해석한 값이 값 열과 같아야 하며, 계획서 게이트 `#5` 가 그 대조를 돌린다.

**대응 규칙은 이 표 자체다.** 표 밖의 숫자는 그 대조를 받지 않는다 — 문서 안의 숫자 리터럴을 자동으로 정본 키에 짝지을 규칙이 정의돼 있지 않기 때문이다. 그래서 정본이 동결하지 않은 갈래(에러 코드 · 도메인 상태 코드 · 벤더 코드)는 개수를 **적지 않는** 쪽을 택했고, 그 갈래들의 전수는 `../_meta/index/codes/` 의 파일로 링크만 건다. 표 밖에 남는 숫자는 화면 문구에 들어 있는 기간 표기처럼 **세어서 얻은 값이 아닌 것**뿐이며, 그 구별은 기계가 아니라 리뷰가 판정한다.

| 값 | manifest 키 |
|---|---|
| 18 | `code_namespaces.menu_codes.hardcoded.code_count` |
| 104 | `code_namespaces.menu_codes.db.row_count` |
| 81 | `code_namespaces.menu_codes.db.second_level` |
| 10 | `code_namespaces.menu_codes.db.enumerated` |
| 282 | `code_namespaces.screen_codes.route_count` |

## 연혁

릴리스 태그가 존재하지 않는다. 릴리스 열은 `—` 로 두고 커밋 SHA 로 추적한다.

| 릴리스 | 날짜 | SHA | 변경 요약 |
|---|---|---|---|
| — | 2026-01-19 | `b8ed533e` | 기업 담당자 라우터 신설 — 콘솔 주소 묶음이 셋이 되어 화면 코드 파생 입력이 3벌로 확정 |
| — | 2026-03-17 | `5920d06b` | 분석 상세 탭 분리 — `ANS003A`/`ANS003B` 서브레벨 접미 등장 |
| — | 2026-05-20 | `8be772db` | 기업↔기업상품 1:N 개편 — 같은 파일 안 코드값 중복이 다섯 종으로 늘어남 |
| — | 2026-07-31 | `b753586b` | 기업조직관리 메뉴 신설 — `CRP_` 접두 메뉴 코드가 다섯 종으로 확정 |
| — | 2026-08-05 | `4d798f55` | 실손분석 메뉴 증분 등록 — DB 축 메뉴 코드에 가변 길이 접두 형태 2건 추가 |
