이호영 이호영 07-28
fix: 운영 DB에 실제로 저장된 공공누리 값을 코드로 등록
배포 전 정합성 점검을 실제 DB에 돌려보니 코드테이블에 없는 값이 1,926건 있었다.
  review_item.kogl_type = 유형 확인 필요  1,858건
  review_item.kogl_type = 제4유형            68건

둘 다 기관 조사표에서 온 값이라 prior(기존 부착 유형) 자리에만 넣고, 변호사가 고르는
판정값(review/process)에는 넣지 않는다. surveyOnly 속성으로 구분하고 그 구분이 새는지를
테스트로 막는다.

등록하지 않았다면 Phase 2에서 이 1,926건이 상세 화면에 선택 안 됨으로 보였을 것이다.

Co-Authored-By: Claude Opus 5 (1M context) 
@60fd607ef427509323ff5e819b1dd207fdfd87ef
 
src/main/resources/db/migration/V14__common_code_orphans.sql (added)
+++ src/main/resources/db/migration/V14__common_code_orphans.sql
@@ -0,0 +1,19 @@
+-- V13 시드를 넣은 뒤 운영 DB에 이미 저장된 값을 훑어보니, 코드테이블에 없는 값이 있었다.
+-- 화면이 코드테이블만 보게 되는 Phase 2 전에 이 값들을 코드로 등록해 둔다.
+-- 등록하지 않으면 아래 1,926건이 상세 화면에서 "선택 안 됨"으로 보인다.
+--
+-- 조사 시점(2026-07-28) 운영 DB 실측:
+--   review_item.kogl_type = '유형 확인 필요'  1,858건
+--   review_item.kogl_type = '제4유형'            68건
+--
+-- 둘 다 기관이 제출한 조사표에서 온 값이라 prior(기존 부착 유형) 자리에만 넣는다.
+-- 변호사가 고르는 판정값(review/process)에는 넣지 않는다.
+--
+-- '제4유형'은 '4유형'과 같은 뜻의 다른 표기다. 값을 통일하는 것은 데이터 변경이라
+-- 여기서 하지 않는다 - 표기 통일 여부는 별도로 확인받는다.
+
+insert into code (group_id, code, label, sort_order, active, attrs) values
+ ('KOGL_TYPE','유형 확인 필요','유형 확인 필요', 8, true,
+   '{"scopes":["prior"],"firstRow":[],"surveyOnly":true}'::jsonb),
+ ('KOGL_TYPE','제4유형',       '제4유형',        9, true,
+   '{"scopes":["prior"],"firstRow":[],"surveyOnly":true,"sameAs":"4유형"}'::jsonb);
src/test/java/kr/itn/itnhub/code/CodeControllerTest.java
--- src/test/java/kr/itn/itnhub/code/CodeControllerTest.java
+++ src/test/java/kr/itn/itnhub/code/CodeControllerTest.java
@@ -31,7 +31,8 @@
                 .andExpect(jsonPath("$.STAGE[12].code").value("13"))
                 .andExpect(jsonPath("$.STAGE[12].label").value("보고서 제출 완료"))
                 .andExpect(jsonPath("$.STAGE[12].attrs.progress").value("done"))
-                .andExpect(jsonPath("$.KOGL_TYPE.length()").value(7))
+                // 0~4유형 + 개방불가 + 보류 + 조사표에서 온 2개(유형 확인 필요, 제4유형)
+                .andExpect(jsonPath("$.KOGL_TYPE.length()").value(9))
                 .andExpect(jsonPath("$.CONTACT_CATEGORY[0].code").value("APPLICANT"))
                 .andExpect(jsonPath("$.CONTACT_CATEGORY[0].label").value("신청기관"));
     }
src/test/java/kr/itn/itnhub/code/CodeSeedTest.java
--- src/test/java/kr/itn/itnhub/code/CodeSeedTest.java
+++ src/test/java/kr/itn/itnhub/code/CodeSeedTest.java
@@ -74,9 +74,29 @@
     @Test
     void 공공누리_유형은_사용처별로_다르게_노출된다() {
         // 세 화면의 목록이 7개/5개/6개로 달랐던 이유는 쓰이는 자리가 달라서다.
-        assertThat(koglScope("review")).hasSize(7);
+        assertThat(koglScope("review")).hasSize(7).doesNotContain("유형 확인 필요");
         assertThat(koglScope("process")).hasSize(6).doesNotContain("보류");
-        assertThat(koglScope("prior")).containsExactly("0유형", "1유형", "2유형", "3유형", "4유형");
+    }
+
+    @Test
+    void 기존_부착유형에는_조사표에서_온_값도_들어간다() {
+        // 운영 DB 실측(2026-07-28): kogl_type에 '유형 확인 필요' 1,858건, '제4유형' 68건이
+        // 저장돼 있었다. 코드로 등록해 두지 않으면 상세 화면에서 선택 안 됨으로 보인다.
+        assertThat(koglScope("prior")).containsExactly(
+                "0유형", "1유형", "2유형", "3유형", "4유형", "유형 확인 필요", "제4유형");
+    }
+
+    @Test
+    void 조사표에서_온_값은_변호사_판정_선택지가_아니다() {
+        Integer leaked = jdbc.queryForObject(
+                "select count(*) from code c "
+                        + "where c.group_id = 'KOGL_TYPE' "
+                        + "  and (c.attrs->>'surveyOnly')::boolean is true "
+                        + "  and exists (select 1 from jsonb_array_elements_text(c.attrs->'scopes') s(v) "
+                        + "    where s.v in ('review', 'process'))",
+                Integer.class);
+
+        assertThat(leaked).isZero();
     }
 
     private List<String> koglScope(String scope) {
src/test/java/kr/itn/itnhub/code/CodeServiceTest.java
--- src/test/java/kr/itn/itnhub/code/CodeServiceTest.java
+++ src/test/java/kr/itn/itnhub/code/CodeServiceTest.java
@@ -58,9 +58,12 @@
         assertThat(service.scoped(Codes.KOGL_TYPE, Codes.SCOPE_PROCESS))
                 .hasSize(6)
                 .noneMatch(c -> c.code().equals("보류"));
+        // prior에는 기관 조사표에서 온 값('유형 확인 필요', '제4유형')까지 들어간다.
+        // 운영 DB에 실제로 저장돼 있는 값이라 등록해 두지 않으면 화면에서 선택 안 됨으로 보인다.
         assertThat(service.scoped(Codes.KOGL_TYPE, Codes.SCOPE_PRIOR))
                 .extracting(Code::code)
-                .containsExactly("0유형", "1유형", "2유형", "3유형", "4유형");
+                .containsExactly("0유형", "1유형", "2유형", "3유형", "4유형",
+                        "유형 확인 필요", "제4유형");
     }
 
     @Test
Add a comment
List