From 58247537c18c8bbb2b66b55ce29e9dfbc9447a25 Mon Sep 17 00:00:00 2001 From: RosieOh Date: Thu, 22 Oct 2026 17:46:46 +0900 Subject: [PATCH] =?UTF-8?q?fix:=202023=EB=85=84=20=EC=A7=80=EC=9B=90?= =?UTF-8?q?=EA=B8=88=20=EA=B8=88=EC=95=A1=EC=9D=B4=20=EB=82=A8=EC=95=84=20?= =?UTF-8?q?=EC=9E=88=EC=97=88=EA=B3=A0,=20=EC=97=B0=EB=A0=B9=20=EB=8B=A8?= =?UTF-8?q?=EC=9C=84=EA=B0=80=20=ED=95=9C=20=EA=B3=B3=EB=A7=8C=20=EB=8B=AC?= =?UTF-8?q?=EB=9E=90=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 초기 데이터의 금액을 운영으로 올리려다 값이 낡은 것을 발견했다. 올렸으면 첫 화면에 틀린 금액이 확정치로 떴을 것이다. 금액 (2026-10-22 보건복지부 페이지로 확인) - 부모급여(0세) 70만 -> 100만원. 2023년 값이 그대로 남아 있었다. - 부모급여(1세) 35만 -> 50만원. 같은 건이다. mohw.go.kr/menu.es?mid=a10711030600 - 아동수당 10만원은 수도권 기준임을 밝힌다. 실제로는 거주지별 10~13만원이다. - 첫만남이용권 200만원은 첫째 기준임을 밝힌다. 둘째 이상은 300만원이다. - 확인하지 못한 5건(육아휴직급여·아빠보너스·보육료·임신출산·누리과정)은 "미확인: 개발용 임시값" 으로 표시했다. 표시 없는 숫자는 사실로 읽힌다. 클래스 주석에 "여기 적힌 금액을 운영으로 그대로 옮기지 말 것" 을 남겼다. 조건에 따라 갈리는 금액은 benefitAmount 정수 하나로 담을 수 없다 — 동기화가 금액 추출을 거부하는 이유와 같고, 제보 합의로 채우는 것이 설계다. 연령 단위 - findAdmissionCandidates 만 연 나이(ageYears)를 받고 있었다. 이 저장소의 다른 연령 쿼리는 전부 개월이다. 지금은 AGE_RANGE_MIN/MAX 를 채우는 코드가 없어 드러나지 않지만, 값이 들어오는 순간 이 쿼리만 틀린다. "한 곳만 단위가 달랐다" 는 이미 한 번 겪은 사고다(architecture-rules.md). - 컬럼의 단위가 확정된 바 없다는 사실도 함께 적었다. 채우는 사람이 단위를 정하고 호출부를 같이 고쳐야 한다. 검증: 테스트 647개 통과. --- .../repository/CareFacilityRepository.java | 17 ++++++---- .../service/AdmissionCandidateService.java | 3 +- .../service/PolicyInitializationService.java | 31 +++++++++++++++++-- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/carecode/domain/facility/repository/CareFacilityRepository.java b/src/main/java/com/carecode/domain/facility/repository/CareFacilityRepository.java index f175b89d..87187d75 100644 --- a/src/main/java/com/carecode/domain/facility/repository/CareFacilityRepository.java +++ b/src/main/java/com/carecode/domain/facility/repository/CareFacilityRepository.java @@ -30,16 +30,21 @@ public interface CareFacilityRepository extends JpaRepositoryAGE_RANGE_MIN/MAX 는 연 나이다(V1__baseline.sql 의 '최소 나이'). 아직 어떤 동기화도 이 값을 - * 채우지 않아 대부분 NULL 인데, NULL 은 "연령 제한 없음" 으로 본다. 나중에 값이 들어오면 조건이 - * 저절로 살아난다. + *

연령은 개월로 받는다. 이 저장소의 다른 연령 쿼리와 같은 단위여야 호출부가 헷갈리지 + * 않는다 — 한 곳만 단위가 달랐다가 돌 지난 아이 전부에게 신생아 정책이 추천된 적이 있다 + * (docs/quality/architecture-rules.md). + * + *

다만 AGE_RANGE_MIN/MAX 의 단위는 확정된 바 없다. V1__baseline.sql 주석은 '최소 나이' + * 지만 이 값을 채우는 코드가 아직 없어서(동기화·마이그레이션 모두) 실제 데이터로 확인할 수 없다. + * NULL 은 "연령 제한 없음" 으로 보므로 지금은 조건이 사실상 없는 것과 같다. 이 컬럼을 채우는 + * 사람이 단위를 정하고 호출부를 함께 고쳐야 한다. */ @Query("SELECT cf FROM CareFacility cf WHERE cf.isActive = true " + "AND cf.address LIKE CONCAT('%', :region, '%') " - + "AND (cf.ageRangeMin IS NULL OR cf.ageRangeMin <= :ageYears) " - + "AND (cf.ageRangeMax IS NULL OR cf.ageRangeMax >= :ageYears)") + + "AND (cf.ageRangeMin IS NULL OR cf.ageRangeMin <= :ageMonths) " + + "AND (cf.ageRangeMax IS NULL OR cf.ageRangeMax >= :ageMonths)") List findAdmissionCandidates(@Param("region") String region, - @Param("ageYears") int ageYears, + @Param("ageMonths") int ageMonths, Pageable pageable); // 연령 범위에 해당하는 시설 조회 diff --git a/src/main/java/com/carecode/domain/facility/service/AdmissionCandidateService.java b/src/main/java/com/carecode/domain/facility/service/AdmissionCandidateService.java index e9196740..5741e781 100644 --- a/src/main/java/com/carecode/domain/facility/service/AdmissionCandidateService.java +++ b/src/main/java/com/carecode/domain/facility/service/AdmissionCandidateService.java @@ -73,8 +73,9 @@ public AdmissionCandidateResponse recommend(String region, Integer childAgeMonth int horizon = horizonMonths != null && horizonMonths > 0 ? horizonMonths : DEFAULT_HORIZON_MONTHS; int size = limit != null && limit > 0 ? Math.min(limit, MAX_LIMIT) : DEFAULT_LIMIT; + // 연령은 개월 그대로 넘긴다. 이 저장소의 다른 연령 쿼리와 단위를 맞춘다. List facilities = facilityRepository.findAdmissionCandidates( - region.trim(), childAgeMonths / 12, PageRequest.of(0, MAX_EVALUATED)); + region.trim(), childAgeMonths, PageRequest.of(0, MAX_EVALUATED)); AdmissionCandidateResponse.AdmissionCandidateResponseBuilder response = AdmissionCandidateResponse.builder() diff --git a/src/main/java/com/carecode/domain/policy/service/PolicyInitializationService.java b/src/main/java/com/carecode/domain/policy/service/PolicyInitializationService.java index 4d6c4007..c2c545e6 100644 --- a/src/main/java/com/carecode/domain/policy/service/PolicyInitializationService.java +++ b/src/main/java/com/carecode/domain/policy/service/PolicyInitializationService.java @@ -15,7 +15,20 @@ import java.util.Arrays; import java.util.List; -/** 정책 관련 초기 데이터를 생성하는 서비스 */ +/** + * 정책 관련 초기 데이터를 생성하는 서비스. 개발 환경 전용이다. + * + *

여기 적힌 금액을 운영으로 그대로 옮기지 말 것. 지원금 금액은 해마다 바뀌고, 상당수가 + * 조건에 따라 갈린다. 실제로 이 파일의 부모급여는 2023년 값(70/35만원)인 채로 오래 남아 있었다. + * + *

2026-10-22 기준 보건복지부 페이지로 확인한 것만 고쳤다. 확인한 값에는 출처를 달았고, + * 확인하지 못한 값은 개발용 임시값이라 믿을 수 없다. + * + *

조건에 따라 갈리는 금액은 {@code benefitAmount} 하나로 담을 수 없다 — 아동수당은 거주지별 + * (10~13만원), 첫만남이용권은 출생 순위별(200/300만원)로 다르다. 공공데이터 동기화가 금액을 + * 일부러 추출하지 않는 이유와 같다({@code PolicyUpsertService} 참고). 정확한 금액은 사용자 + * 제보 합의({@code BenefitAmountReportService})로 채우는 것이 설계다. + */ @Slf4j @Service @Profile("dev") @@ -127,6 +140,7 @@ private void createMaternityAndChildcareLeave(PolicyCategory category) { .targetAgeMin(0) .targetAgeMax(96) .targetRegion("전국") + // 미확인: 개발용 임시값. 공식 출처로 확인하기 전에는 사실로 쓰지 말 것. .benefitAmount(1500000) .maxPaymentMonths(12) .benefitType("월급여") @@ -146,6 +160,7 @@ private void createMaternityAndChildcareLeave(PolicyCategory category) { .targetAgeMin(0) .targetAgeMax(96) .targetRegion("전국") + // 미확인: 개발용 임시값. 공식 출처로 확인하기 전에는 사실로 쓰지 말 것. .benefitAmount(2500000) .maxPaymentMonths(3) .benefitType("월급여") @@ -173,6 +188,8 @@ private void createChildcareAllowances(PolicyCategory category) { .targetAgeMin(0) .targetAgeMax(83) .targetRegion("전국") + // 확인: 월 10~13만원(수도권 10만, 비수도권 10.5만, 인구감소지역 11만, 특별 12만). + // 거주지로 갈리므로 수도권 기준값만 둔다. mohw.go.kr/menu.es?mid=a10711030100 (2026-10-22) .benefitAmount(100000) .benefitType("월지급") .applicationUrl("https://www.bokjiro.go.kr") @@ -192,7 +209,9 @@ private void createChildcareAllowances(PolicyCategory category) { .targetAgeMax(11) .exclusionGroup("INFANT_CARE_0") .targetRegion("전국") - .benefitAmount(700000) + // 확인: 월 100만원. 2023년 값 70만원이 그대로 남아 있었다. + // mohw.go.kr/menu.es?mid=a10711030600 (2026-10-22) + .benefitAmount(1000000) .benefitType("월지급") .applicationUrl("https://www.bokjiro.go.kr") .contactInfo("보건복지상담센터 129") @@ -211,7 +230,8 @@ private void createChildcareAllowances(PolicyCategory category) { .targetAgeMax(23) .exclusionGroup("INFANT_CARE_1") .targetRegion("전국") - .benefitAmount(350000) + // 확인: 월 50만원. 2023년 값 35만원이 그대로 남아 있었다. 출처는 0세와 같다. + .benefitAmount(500000) .benefitType("월지급") .applicationUrl("https://www.bokjiro.go.kr") .contactInfo("보건복지상담센터 129") @@ -230,6 +250,7 @@ private void createChildcareAllowances(PolicyCategory category) { .targetAgeMax(71) .exclusionGroup("INFANT_CARE_0") .targetRegion("전국") + // 미확인: 개발용 임시값. 공식 출처로 확인하기 전에는 사실로 쓰지 말 것. .benefitAmount(514000) .benefitType("월지원") .applicationUrl("https://www.bokjiro.go.kr") @@ -248,6 +269,8 @@ private void createChildcareAllowances(PolicyCategory category) { .targetAgeMin(0) .targetAgeMax(12) .targetRegion("전국") + // 확인: 첫째 200만원, 둘째 이상 300만원('24.1.1 이후 출생아). + // 출생 순위로 갈리므로 첫째 기준값만 둔다. mohw.go.kr/menu.es?mid=a10711020100 (2026-10-22) .benefitAmount(2000000) .benefitType("일시지급") .applicationUrl("https://www.bokjiro.go.kr") @@ -367,6 +390,7 @@ private void createHealthcareSupport(PolicyCategory category) { .targetAgeMin(0) .targetAgeMax(0) .targetRegion("전국") + // 미확인: 개발용 임시값. 공식 출처로 확인하기 전에는 사실로 쓰지 말 것. .benefitAmount(1000000) .benefitType("바우처지원") .applicationUrl("https://www.nhis.or.kr") @@ -394,6 +418,7 @@ private void createEducationSupport(PolicyCategory category) { .targetAgeMax(71) .exclusionGroup("PRESCHOOL_EDU") .targetRegion("전국") + // 미확인: 개발용 임시값. 공식 출처로 확인하기 전에는 사실로 쓰지 말 것. .benefitAmount(280000) .benefitType("월지원") .applicationUrl("https://www.childcare.go.kr")