Repository navigation
refactor: 자녀 조회에 입구를 만들고 소유권 답을 하나로 맞춘다 - #141
Merged
Merged
Conversation
도메인 경계 위반 268건 중 자녀·사용자 리포지토리 직접 참조가 가장 큰 덩어리였다.
자녀는 user 도메인에 속하는데 쓰는 쪽은 health·policy·facility 다. 그 도메인들이
ChildRepository 를 그냥 주입해 쓰면서 두 가지가 복제됐다.
1) 소유권 검증이 세 벌이었고, 같은 질문에 답이 셋으로 갈렸다
/children/... → 404 (맞는 동작)
HealthService.assertChildOwnedByUser → 403
/health/{vaccines,checkups}/schedule → 500
403 은 그 자녀가 존재한다는 사실을 알려준다. ID 를 훑으면 "이 번호는 누군가의
자녀" 목록을 만들 수 있다. 500 은 그 403 이 catch (Exception e) 에 걸려
CareServiceException 으로 덮인 결과다. 권한 거부가 서버 장애로 집계되고,
클라이언트는 자기가 잘못 보냈다는 걸 알 수 없다.
ChildOwnershipContractTest 로 여섯 경로를 두드려 404 를 확인한다. 테스트를 먼저
쓰니 500 두 건이 바로 드러났다(expected: 404 but was: 500).
함께: HealthService 의 catch (Exception e) 10곳 중 8곳에 우리 예외를 그대로
통과시키는 catch (CareCodeException e) { throw e; } 를 넣었다. 없으면 404·403 이
전부 500 으로 덮인다. Slack 알림까지는 가지 않았다 — 알림은 최후 핸들러에서만
울리고 CareServiceException 은 자기 핸들러가 있다(테스트로 확인).
2) 월령 계산이 다섯 벌이었고, 생일이 없을 때 처리가 곳마다 달랐다
정책 추천·지원금 비교·마감 알림·제보 요청·대기 등록이 각자
ChronoUnit.MONTHS.between(...) 을 들고 있었고 null 처리가 제외/0/통과로 갈렸다.
월령은 추천 결과를 좌우하는 입력이라 하나만 어긋나면 같은 아이에게 다른 정책이
나온다. ChildView.ageMonths(기준일) 한 곳으로 모았다. 생일이 없으면 null 이고
0 으로 바꾸지 않는다 — 0개월은 "갓 태어난 아이" 로 읽혀 신생아 정책이 추천된다.
판단은 여전히 호출하는 쪽이 한다. 마감 알림만 "생일을 모르면 배제하지 않는다" 로
다른데, 놓친 손해가 성가심보다 크다는 판단이라 의도된 차이다. 계산은 하나, 판단은 각자.
입구는 엔티티가 아니라 ChildView(읽기 전용 값)를 돌려준다. 쓰는 쪽이 자녀 정보를
고치거나 child.getUser() 로 사용자 정보까지 타고 들어가는 일이 없다.
곁에서 드러난 것
- FacilityWaitlist.child 가 @manytoone Child 였는데 읽는 곳이 없었다. CHILD_ID 를
채우는 용도뿐이라 바로 위 facilityId 와 같은 방식(Long childId)으로 맞췄다.
DB 외래키와 중복 등록 제약은 그대로다.
- 자녀 미등록·생일 없음·남의 대기 기록 수정이 500 이었다. 각각 400·400·403 으로 고쳤다.
생성자 서명이 바뀌어 기존 위반 10건이 새 위반으로 보였다. 1단계와 같은 상황이라
freeze.refreeze 를 한 번 켜고 규칙별 숫자가 늘지 않은 것을 확인한 뒤 되돌렸다.
- ArchUnit baseline 383 → 364 (도메인 경계 268 → 249)
- ChildRepository 를 쓰는 도메인: policy 5곳·facility 1곳 → 0 (health 5곳은 엔티티가
필요해 남겨 둠)
- 전체 테스트 624개, 실패 0. OpenAPI 스펙 변화 없음 — 응답 모양을 바꾸지 않았다
Refs #132
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #132 (4a 단계)
도메인 경계 위반 268건 중 자녀·사용자 리포지토리 직접 참조가 가장 큰 덩어리였습니다. 자녀는
user도메인에 속하는데 쓰는 쪽은 health·policy·facility 입니다. 그 도메인들이ChildRepository를 그냥 주입해 쓰면서 두 가지가 복제됐습니다.1. 소유권 검증이 세 벌이었고, 같은 질문에 답이 셋으로 갈렸다
/children/…HealthService.assertChildOwnedByUser/health/vaccines/schedule,/health/checkups/schedulecatch (Exception e)에 걸려CareServiceException으로 덮였다. 권한 거부가 서버 장애로 집계되고, 클라이언트는 자기가 잘못 보냈다는 걸 알 수 없다ChildOwnershipContractTest가 여섯 경로를 전부 두드려 404 를 확인합니다. 테스트를 먼저 쓰니 500 두 건이 바로 드러났습니다(expected: 404 but was: 500).함께 고친 것:
HealthService의catch (Exception e)10곳 중 8곳에 우리 예외를 그대로 통과시키는catch (CareCodeException e) { throw e; }를 넣었습니다. 없으면 404·403 이 전부 500 으로 덮입니다.2. 월령 계산이 다섯 벌이었고, 생일이 없을 때 처리가 곳마다 달랐다
정책 추천·지원금 비교·마감 알림·제보 요청·대기 등록이 각자
ChronoUnit.MONTHS.between(child.getBirthDate(), today)를 들고 있었고null처리가 제외 / 0 / 통과로 갈렸습니다. 월령은 추천 결과를 좌우하는 입력이라 하나만 어긋나면 같은 아이에게 다른 정책이 나옵니다.ChildView.ageMonths(기준일)한 곳으로 모았습니다. 생일이 없으면null이고 0 으로 바꾸지 않습니다 — 0개월은 "갓 태어난 아이" 로 읽혀 신생아 정책이 추천됩니다.판단은 여전히 호출하는 쪽이 합니다. 마감 알림만 "생일을 모르면 배제하지 않는다" 로 다른데, 놓친 손해가 성가심보다 크다는 판단이라 의도된 차이입니다. 계산은 하나, 판단은 각자.
입구의 모양
엔티티가 아니라
ChildView(읽기 전용 값)를 돌려줍니다. 쓰는 쪽이 자녀 정보를 고치거나child.getUser()로 사용자 정보까지 타고 들어가는 일이 없습니다.곁에서 드러난 것
FacilityWaitlist.child가@ManyToOne Child였는데 읽는 곳이 없었습니다. CHILD_ID 를 채우는 용도뿐이라 바로 위facilityId와 같은 방식(Long childId)으로 맞췄습니다. DB 외래키와 중복 등록 제약은 그대로입니다.baseline 재생성
생성자에
ChildDirectory가 추가되면서 위반 설명에 박힌 생성자 서명이 바뀌어, 기존 위반 10건이 새 위반으로 보였습니다. 1단계와 같은 상황이라freeze.refreeze를 한 번 켜고 규칙별 숫자가 늘지 않은 것을 확인한 뒤 되돌렸습니다.숫자
ChildRepository를 쓰는 도메인: policy 5곳·facility 1곳 → 0. health 5곳은 엔티티가 필요해 남겼습니다(4b)