Skip to content

fix: 프런트-백엔드 API 계약 불일치와 보안 결함 정리 - #111

Merged
RosieOh merged 1 commit into
mainfrom
fix/api-contract-alignment
Sep 22, 2026
Merged

RosieOh merged 1 commit into
mainfrom
fix/api-contract-alignment

Conversation

@RosieOh

@RosieOh RosieOh commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Closes #110

프런트가 부르는 API 전체를 서버 매핑·DTO 와 필드 단위로 대조해 드러난 문제를 고친다. 세부는 이슈에 있다.

변경

영역 내용
시설 @AuthenticationPrincipal → CurrentUserFacade (리뷰·예약 500 해소), 남의 예약 403, 시설 전체 예약·상태 변경 ADMIN 전용, 상세·리뷰·검색 공개, facilityType 필터, REJECTED 상태
공통 @ValidateLocation 을 좌표 파라미터 검사로 재작성 (항상 400 이던 4개 API)
커뮤니티 isAnonymous JSON 키, 익명 작성자 가리기, 좋아요 수 동기화, isLiked/isBookmarked, @Valid
건강 접종 완료 IDOR, 기록 유형 추가·400, 수정 시 필드 보존, 다음 접종 표시 이름, zScore 키
정책·알림·사용자 검색 응답 모양, isRead 키, 빈/하이픈 없는 휴대폰 번호

스키마 변경 없음 (예약 상태·기록 유형 컬럼은 VARCHAR).

호환성

  • 익명 글은 비작성자에게 authorId 를 빈 문자열로 준다 (프런트 스키마가 필수 문자열이라 null 대신).
  • 정책 검색 응답의 totalCount 는 totalElements 와 같은 값으로 남겨 둔다.
  • 요청의 예전 키 anonymous 도 계속 받는다.

테스트

실제 JWT 로 필터를 통과시키는 통합 테스트를 추가했다. @WithMockUser 는 principal 을 UserDetails 로 넣어 이 결함을 재현하지 못한다.

  • FacilityBookingContractTest — 리뷰·예약 수명주기, 남의 예약 403, ADMIN 전용 경로, 공개 조회, 유형 필터, 위치 검증
  • CommunityPolicyContractTest — 익명 저장·가리기, 좋아요 반영, 본문 검증, 정책 검색 모양
  • JsonFieldNameContractTest, VaccinationScheduleServiceOwnershipTest, UserUpdateRequestDtoTest

./gradlew test jacocoTestCoverageVerification — 511 tests, 실패 0, skip 0 (스키마 정합성 포함)

프런트 호출 전체를 서버 매핑과 대조해 드러난 문제들이다. 대부분 에러 없이
빈 화면이나 틀린 값으로 조용히 실패하고 있었다.

시설
- 리뷰 작성·수정·삭제, 예약 생성·조회·취소가 전부 500 이던 문제.
  JWT 필터의 principal 은 이메일 문자열이라 @AuthenticationPrincipal UserDetails
  가 늘 null 이었다. CurrentUserFacade 로 바꾸고, 예약 소유 확인은 403 으로 준다.
- 시설 전체 예약 목록·오늘 예약(보호자 이름·연락처 포함)이 로그인만 하면 열려 있었고,
  본인이 자기 예약을 CONFIRMED 로 바꿀 수 있었다. 세 경로를 ADMIN 전용으로.
- 시설 상세·리뷰·검색·예측을 비로그인에 연다 (공공데이터, 프런트가 로그인 전 노출).
- 검색이 facilityType 을 무시하던 문제, size 누락 시 예외.
- @ValidateLocation 이 인자 toString 에 "latitude" 글자가 있는지를 봐서 반경 검색·
  지역별 조회·시설 검색이 입력과 무관하게 항상 400 이었다. 좌표 파라미터만 검사하도록.
- 관리자 화면이 쓰는 REJECTED(반려) 상태를 추가. 겹침 계산에서 제외.

커뮤니티
- 익명 글이 실명으로 올라가던 문제. primitive boolean isAnonymous 의 JSON 키가
  anonymous 라 프런트가 보낸 값이 버려졌다.
- 익명 글 응답에 실명과 작성자 ID 가 그대로 실려 있었다. 이름은 가리고 ID 는 본인에게만.
- 좋아요 수가 갱신되지 않고, isLiked/isBookmarked 가 늘 false 이던 문제.
- 요청 본문 @Valid 적용. 길이 제한은 DB 컬럼(TEXT, VARCHAR(200))에 맞춘다.

건강·정책·알림·사용자
- 예방접종 완료 처리에서 일정이 경로의 아이 것인지 확인하지 않아 남의 기록을 바꿀 수 있었다.
- 기록 유형 MEDICATION/SYMPTOM 이 서버에 없어 저장이 실패. 모르는 유형은 400.
- 건강 기록 수정이 수정 화면에 없는 필드(완료 여부 등)를 null 로 덮던 문제.
- 형제 요약의 다음 접종이 코드(HEP_B)로 나가던 문제.
- 정책 검색 응답을 다른 목록과 같은 PolicyDto 로, 페이지 필드는 프런트가 읽는 이름으로.
- 알림 isRead, 성장 곡선 zScore 의 JSON 키 이름.
- 프로필 수정에서 빈 휴대폰 번호(지우기)와 하이픈 없는 번호를 받는다.
@RosieOh
RosieOh merged commit 9ed9b28 into main Sep 22, 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.

[ API ] 프런트-백엔드 계약 불일치로 시설 예약·리뷰 500, 익명 글 실명 노출, 검색 400

1 participant