공통코드 설계를 처음에 안 한 죄 — enum→숫자코드 대장정
상태값을 코드에 enum으로 박았습니다. 편했고, 깔끔했고, 빨랐습니다. 그런데 새 상태 하나를 추가하려면 배포를 해야 했고, 한글·영문 라벨을 담을 곳이 없었고, 같은 "01"이 모듈마다 다른 뜻이라 충돌했습니다. 결국 굴러가는 시스템 위에서, 전 시스템의 분류값을 숫자 공통코드로 갈아엎는 몇 주짜리 대장정을 치렀습니다.
01 OFFICE 사무직·02 PRODUCTION 생산직처럼 숫자 코드 + 영문명 + 한글명으로 저장됩니다 — enum으로 박았다면 라벨을 담을 칸조차 없었을 자리입니다. 이제 새 상태 추가는 배포가 아니라 이 화면에서 한 줄을 더하는 일입니다.용어부터 — enum과 공통코드
섹션 제목: “용어부터 — enum과 공통코드”enum은 편했습니다, 처음에는
섹션 제목: “enum은 편했습니다, 처음에는”문서 상태를 DRAFT, APPROVED 같은 enum으로 다뤘습니다. 타입 안정성도 있고 코드도 깔끔했습니다. 결재선 단계 상태, 자재 이동 유형, 휴가 종류, 근태 상태 — 분류값마다 enum이 하나씩 생겼습니다. 빠르게 짜기엔 이만한 게 없었습니다. 초기 몇 주 동안은 이 선택이 분명히 시간을 벌어 줬습니다.
균열은 요구가 늘면서 드러났습니다. 세 갈래로 동시에요.
- 새 값 = 배포 사건. 분류값 하나를 추가하려면 코드를 고치고 빌드해서 배포해야 했습니다. 운영자가 직접 넣을 길이 없었습니다.
- 라벨 둘 곳이 없다. 화면에 한글로 “승인됨”을 보여 주고, 어딘가엔 영문도 필요했습니다. enum에는 그 라벨을 담을 칸이 없어, 또 다른 매핑표를 손으로 만들어 동기화해야 했습니다.
- 같은 코드, 다른 뜻. 근태의
"01"과 휴가의"01"이 서로 다른 의미인데, 코드에는 그 둘을 격리할 장치가 없었습니다. 도메인이 충돌하기 시작했습니다.
| 요구 | enum 방식 | 공통코드 방식 |
|---|---|---|
| 새 분류값 추가 | 코드 수정 + 빌드 + 배포 | 데이터 한 줄 입력 |
| 한글·영문 라벨 | 담을 칸 없음 → 별도 매핑 손관리 | 코드 행에 라벨 칸 내장 |
| 같은 “01”의 충돌 | 격리 장치 없음 | domain으로 격리 |
| 정본 개수 | 코드+라벨맵 여럿 → 동기화 부담 | 코드그룹 테이블 하나 |
그림으로 보기 — enum vs 공통코드
섹션 제목: “그림으로 보기 — enum vs 공통코드”대장정 — 굴러가는 시스템 위에서 전부 갈아엎기
섹션 제목: “대장정 — 굴러가는 시스템 위에서 전부 갈아엎기”방향은 명확했습니다. 모든 분류값을 enum이 아니라 숫자 문자열 코드값으로 저장하고, 코드 정의는 코드 그룹(도메인 격리) 테이블을 단일 출처로 둡니다. 백엔드와 프론트는 그 출처에서 생성된 상수를 공유합니다. 같은 "01"의 충돌은 코드 그룹의 domain으로 격리합니다.
문제는 이걸 이미 굴러가는 시스템 위에서 했다는 점입니다. 한 번에 다 바꾸면 모든 게 동시에 깨지므로, 모듈별로 슬라이스를 떠서 순차적으로 이관해야 했습니다. 실제 작업도 그렇게 단계로 쪼개 진행됐습니다.
- 인프라 정비 — 코드 그룹·코드 테이블과 도메인 격리 구조를 먼저 세웁니다. 갈아엎을 토대를 만드는 단계입니다.
- 문서 유형 이관 — 문서의 유형값을 영문 키에서 숫자코드로 본 치환. (2026-06-03)
- 근태 상태 이관 — 근태 상태를 숫자코드로 정의하고 백엔드·프론트를 함께 옮깁니다. (2026-06-03)
- 휴가 상태 이관 — 휴가 신청 상태를 숫자코드 단일 출처로 이관. 모바일까지 포함된 여러 표면을 동시에 맞춥니다. (2026-06-06)
- 상태전이 검증 — 문서·단계 상태가 “허용된 전이”만 따르도록 검증 장치를 둡니다.
- 채번 규칙 통일 — 여러 종의 번호 채번을 한 서비스로 모으고 형식도 공통코드로 통일. (2026-06-10)
이관이 부른 잠복 버그
섹션 제목: “이관이 부른 잠복 버그”대규모 이관에는 “절반만 옮겨진 상태”라는 위험한 중간 구간이 있습니다. 백엔드는 이미 숫자코드인데 프론트는 아직 영문 키를 보고 있으면, 화면은 멀쩡히 떠도 항상 잘못된 라벨을 보여 줍니다. 더 나쁜 경우는 라벨 매핑이 실패해 사용자에게 raw 코드("01" 같은)가 그대로 노출되는 것입니다. 실제로 휴가 종류 라벨이 숫자 "01"로 노출되던 것을 잡아 정본화하는 수정이 따로 있었습니다(2026-06-10).
| 증상 | 겉보기 | 실제 원인 |
|---|---|---|
| 잘못된 라벨이 일관되게 뜸 | ”기능은 되는데 글자가 이상” | 프론트가 옛 영문 키로 매핑, 백엔드는 이미 숫자 |
화면에 "01" 같은 raw 코드 노출 | ”왜 숫자가 보이지?” | 라벨 매핑 누락 — 코드값이 라벨로 변환 안 됨 |
| 특정 화면만 빈 목록 | ”데이터가 없나?” | 옛 영문 값으로 필터링 → 숫자 데이터와 영영 안 맞음 |
이런 버그들의 공통점은 단위 테스트로는 잘 안 잡힌다는 것입니다. 백엔드 따로, 프론트 따로 테스트하면 각자는 통과합니다. 어긋남은 둘이 만나는 화면에서만 드러나기 때문에, 디버깅이 유난히 까다로웠습니다.
처음부터 했다면 무엇이 달랐나
섹션 제목: “처음부터 했다면 무엇이 달랐나”공통코드 테이블과 코드 그룹 구조를 첫 설계에 넣었다면, 새 상태는 코드가 아니라 데이터로 추가됐을 것입니다. 한글·영문 라벨도, 도메인 충돌 격리도 그 안에서 처음부터 해결됐을 것입니다. 무엇보다 enum으로 박힌 수십 곳을 다시 찾아 갈아엎는 대장정 자체가, 그리고 “절반만 옮겨진 상태”가 부른 잠복 버그들이 통째로 없었을 것입니다.
그 첫 설계에 드는 시간은 길지 않습니다. 코드 그룹 한 테이블과 “분류값은 코드에 박지 않는다”는 규칙 하나면 됩니다. 그 30분이 나중의 몇 주를 아낍니다.
이 글은 SL.AIMS를 만들며 겪은 현장 회고 중 하나입니다. 전체 그림은 〈사례연구: SL.AIMS〉에, 이어지는 이야기는 〈공통 관리(어드민) 메뉴를 초기 설계에 안 넣은 것〉에 있습니다.