Skip to content

fix: 연계 추천이 연 나이를 개월 단위 쿼리에 넘기고 있었다 - #143

Merged
RosieOh merged 2 commits into
mainfrom
refactor/child-queries-to-user
Oct 6, 2026
Merged

RosieOh merged 2 commits into
mainfrom
refactor/child-queries-to-user

Conversation

@RosieOh

@RosieOh RosieOh commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Refs #132 (5b 단계) · #142 다음에 머지해 주세요 (5a 위에 올라가 있습니다)

HealthService 의 아이 조회 네 개를 user 도메인으로 옮기려고 읽다가, 그 옆의 연계 추천이 여섯 번째 월령 계산을 들고 있는 것을 봤습니다. 그리고 이 하나만 단위가 달랐습니다.

.map(b -> Period.between(b, LocalDate.now()).getYears())   // 연 나이
...
policyRepository.findByChildAge(childAge)                   // targetAgeMin/Max 는 개월

정책의 대상 연령은 개월입니다 — 시드 데이터가 부모급여(0세) 0~11, 아동수당 0~95, 영유아 건강검진 0~71 로 넣습니다. 연 나이를 넘기므로 세 살 아이(36개월)가 "3" 으로 들어가 0~11개월 대상 정책(부모급여·첫만남이용권·산후조리비)이 추천됐습니다. 돌 지난 아이 전부가 영향을 받습니다.

테스트로 먼저 확인했습니다.

개월로 와야 한다. 3 이면 연 나이를 그대로 넘긴 것이다
expected: 36
 but was: 3

자녀가 없을 때도 같은 문제였습니다. .orElse(0) 이 0개월로 바꿔 신생아 정책을 추천했고, 사용자는 그것을 "내 아이 기준 추천" 으로 읽습니다. 이제 월령을 모르면 childAge: null 이고 추천 목록은 비어 있으며, 안내 문구가 "아이를 등록하면 …" 으로 바뀝니다.

이것이 4a 에서 월령 계산을 한 곳으로 모은 이유입니다. 나머지 다섯 곳을 봐서는 이 하나가 틀렸다는 걸 알 수 없습니다. 복제의 비용은 "고칠 곳이 많다" 가 아니라 "틀린 곳을 못 찾는다" 입니다.

함께: /health/children/* 네 개를 지웠습니다

GET /health/children/{age-range,gender,special-needs,search}

GET /children 이 birthDate·gender·specialNeeds·name 을 모두 주고 자녀는 보통 1~3명입니다. 서버가 그 목록을 걸러 줄 이유가 없습니다. 넷 다 필수 userId 파라미터를 받아서 무시하고 있었고(컨트롤러는 인증 주체의 PK 를 넘깁니다), 프런트는 쓰지 않습니다. AccessControlContractTest.duplicateMappingsRemoved 에 네 경로를 추가했습니다.

고치지 않고 적어 둔 것

시설 추천은 연령 기반이 아닙니다. 시설의 AGE_RANGE_MIN/MAX 를 어떤 동기화도 채우지 않아 대부분 비어 있고, 연령 조건이 비면 전부 일치로 봅니다. 즉 recommendedFacilities 는 사실상 "운영 중인 시설 세 곳" 입니다. 단위를 고쳐도 달라지지 않으므로(그 값을 채우는 일이 먼저입니다) 응답 DTO 에 한계를 적어 두었습니다.

프런트 영향

childAge 가 null 일 수 있게 됩니다. FE 스키마는 이미 z.number().nullish() 라 그대로 동작하고, 그동안 받던 값이 틀렸던 것이라 화면의 숫자가 3 → 36 처럼 바뀝니다(개월 표기). 지운 네 경로는 FE 가 부르지 않습니다.

숫자

  • HealthService 715 → 688줄 (ChildMapper 의존도 함께 빠졌습니다)
  • OpenAPI: 232 → 228 경로
  • ArchUnit baseline 362 → 357 (도메인 경계 247 → 242)
  • 전체 테스트 639개, 실패 0

baseline: 생성자에서 ChildMapper 가 빠져 기존 위반 5건이 새 위반으로 보였습니다. refreeze 를 한 번 켜고 규칙별 숫자가 늘지 않은 것을 확인한 뒤 되돌렸습니다.

HealthService 1011줄을 책임별로 쪼개려고 읽다 보니 상당 부분이 아무도 부르지 않는
코드였다. 부르는 곳이 없는 코드를 옮기는 건 옮긴 만큼만 일이 늘어난다. 컨트롤러에서
거꾸로 따라가 도달 가능한지 확인하고 지웠다.

HealthService / HealthFacade
- analyzeHealthStatus, generateHealthReport: 파사드에는 있는데 컨트롤러가 부르지
  않는다. healthScore·riskLevel 같은 값을 만들어 내는데 공개된 적이 없다.
- getHealthGoals: 고정 문자열("모든 예방접종 완료")을 돌려준다. 도달 불가.
- getHealthChart: 도달 불가. 성장 곡선은 GrowthChartService 가 따로 한다.
- checkSystemHealth: {status: UP, version: 1.0.0} 하드코딩. Actuator 의
  /actuator/health 와 중복이고 도달 불가.
- getHealthRecords, getHealthRecordsByDateRange: 파사드에도 없다.
- 위 메서드들만 쓰던 private 헬퍼 11개와 상수 3개.

CareFacilityService
- saveCareFacilitiesFromPublicData, countCareFacilities 와 헬퍼 5개는 #137 에서 지운
  CareFacilityApiController 가 쓰던 잔재였다. 입구를 지우면 그 뒤에 남는 코드가
  생기는데, 그때 같이 지우지 않으면 "쓰이는 코드" 처럼 보인다.

크기
- HealthService 1011 → 715줄
- CareFacilityService 580 → 411줄
- HealthFacade 338 → 309줄

- ArchUnit baseline 364 → 362
- 전체 테스트 632개, 실패 0
- OpenAPI 스펙 변화 없음 — 공개 API 를 하나도 건드리지 않았다. 지운 것은 전부 밖에서
  부를 수 없던 코드다.

남은 분해(5b): HealthService 715줄은 아직 건강 기록 CRUD, 아이 조회, 접종·검진 일정,
알림, 통계·추천을 함께 들고 있다. 이 중 아이 조회 4개는 user 도메인 일이라 4a 의
입구로 옮기는 것이 다음 자리다.

Refs #132
HealthService 의 아이 조회 네 개를 user 도메인으로 옮기려고 읽다가, 그 옆의 연계
추천이 여섯 번째 월령 계산을 들고 있는 것을 봤다. 그리고 이 하나만 단위가 달랐다.

  .map(b -> Period.between(b, LocalDate.now()).getYears())  // 연 나이
  policyRepository.findByChildAge(childAge)                  // targetAge 는 개월

정책의 대상 연령은 개월이다(시드: 부모급여(0세) 0~11, 아동수당 0~95, 영유아 건강검진
0~71). 연 나이를 넘기므로 세 살 아이(36개월)가 "3" 으로 들어가 0~11개월 대상 정책
— 부모급여·첫만남이용권·산후조리비 — 이 추천됐다. 돌 지난 아이 전부가 영향을 받는다.

테스트로 먼저 확인했다:
  개월로 와야 한다. 3 이면 연 나이를 그대로 넘긴 것이다
  expected: 36 but was: 3

자녀가 없을 때도 같은 문제였다. .orElse(0) 이 0개월로 바꿔 신생아 정책을 추천했고
사용자는 그것을 "내 아이 기준 추천" 으로 읽는다. 이제 월령을 모르면 childAge 가 null
이고 추천 목록은 비어 있으며, 안내 문구가 "아이를 등록하면 …" 으로 바뀐다.

이것이 4a 에서 월령 계산을 한 곳으로 모은 이유다. 나머지 다섯 곳을 봐서는 이 하나가
틀렸다는 걸 알 수 없다. 복제의 비용은 "고칠 곳이 많다" 가 아니라 "틀린 곳을 못 찾는다" 다.

함께: /health/children/* 네 개를 지웠다

  GET /health/children/{age-range,gender,special-needs,search}

GET /children 이 birthDate·gender·specialNeeds·name 을 모두 주고 자녀는 보통 1~3명이다.
서버가 그 목록을 걸러 줄 이유가 없다. 넷 다 필수 userId 파라미터를 받아서 무시하고
있었고(컨트롤러는 인증 주체의 PK 를 넘긴다), 프런트는 쓰지 않는다.
AccessControlContractTest.duplicateMappingsRemoved 에 네 경로를 추가했다.

고치지 않고 적어 둔 것: 시설 추천은 연령 기반이 아니다. 시설의 AGE_RANGE_MIN/MAX 를
어떤 동기화도 채우지 않아 대부분 비어 있고, 연령 조건이 비면 전부 일치로 본다. 즉
recommendedFacilities 는 사실상 "운영 중인 시설 세 곳" 이다. 단위를 고쳐도 달라지지
않으므로 응답 DTO 에 한계를 적었다.

- HealthService 715 → 688줄 (ChildMapper 의존도 함께 빠졌다)
- OpenAPI 232 → 228 경로
- ArchUnit baseline 362 → 357 (도메인 경계 247 → 242)
- 전체 테스트 639개, 실패 0

생성자에서 ChildMapper 가 빠져 기존 위반 5건이 새 위반으로 보였다. refreeze 를 한 번
켜고 규칙별 숫자가 늘지 않은 것을 확인한 뒤 되돌렸다.

Refs #132
@RosieOh
RosieOh merged commit 03058ff into main Oct 6, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant