feat: 비로그인 사용자를 위한 공개 게시글 조회 API 구현#133
Conversation
- PublicPostController: /api/public/posts/{id} 엔드포인트 구현
- PostService.getPostForPublic(): 인증 없는 게시글 조회 메서드 추가
- 비로그인 사용자도 게시글 정보 조회 가능 (좋아요 상태는 false로 설정)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- PostServiceTest: getPostForPublic 메서드 단위 테스트 추가 - PublicPostControllerTest: 공개 게시글 조회 API 통합 테스트 추가 - 정상 조회, 예외 상황, 잘못된 파라미터 케이스 테스트 커버 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Walkthrough비로그인(공개) 사용자가 게시글을 조회할 수 있도록, 새로운 공개용 게시글 조회 서비스 메서드와 REST API 엔드포인트가 추가되었습니다. 이에 대한 서비스 로직, 컨트롤러, 그리고 단위 및 통합 테스트가 함께 구현되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant PublicPostController
participant PostService
participant PostRepository
participant PostLikeService
Client->>PublicPostController: GET /api/public/posts/{id}
PublicPostController->>PostService: getPostForPublic(id)
PostService->>PostRepository: findById(id)
PostService->>PostLikeService: getLikeCount(id)
PostService-->>PublicPostController: GetPostResponse (liked=false)
PublicPostController-->>Client: 200 OK + AppResponse<GetPostResponse>
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~15 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes(해당 변경사항 내에서는 명확히 요구사항과 무관한 기능적 코드 변경이 발견되지 않았습니다.) Suggested reviewers
Poem
Note 🔌 MCP (Model Context Protocol) integration is now available in Early Access!Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (8)
src/main/java/hanium/modic/backend/domain/post/service/PostService.java (2)
121-123: 주석과 구현 불일치(null vs false) 정정 필요주석은 “null로 설정”이라고 되어 있으나 실제 코드는
false를 설정합니다. 문서-구현 일관성 유지가 필요합니다.- // 비로그인 사용자이므로 좋아요 여부는 null로 설정 + // 비로그인 사용자이므로 좋아요 여부는 false로 설정
105-126: 중복 로직 정리 제안(getPost vs getPostForPublic)두 메서드에서 조회/매핑 로직이 상당 부분 중복됩니다. 공통 매핑을 담당하는 private 헬퍼(예: assembleResponse(postId, currentUserIdOpt))로 추출하면 가독성과 유지보수성이 향상됩니다.
src/main/java/hanium/modic/backend/web/post/controller/PublicPostController.java (1)
18-19: 생성자 접근 수준 PROTECTED 사용 검토Spring이 리플렉션으로 주입하긴 하나, 컨벤션상 컨트롤러의 필수 생성자는 public이 일반적입니다.
@RequiredArgsConstructor에서access옵션 제거(=public) 고려 바랍니다.src/test/java/hanium/modic/backend/domain/post/service/PostServiceTest.java (2)
204-246: 공개 조회 서비스 단위 테스트 케이스: 전반적으로 적절합니다
- 공개 조회에서
isLikedByUser미호출 검증이 명확합니다.- likeCount, 이미지 매핑까지 검증되어 신뢰성이 좋습니다.
추가 제안:
- 작성자 조회 실패(
USER_NOT_FOUND_EXCEPTION) 케이스도 하나 추가하면 방어적 커버리지가 더 좋아집니다.
254-263: 예외 시 사이드이펙트 없는지 검증 충실 — 좋습니다POST_NOT_FOUND 시 이미지/좋아요 카운트 호출이 일어나지 않음을 검증한 점 좋습니다. 동일 패턴으로 USER_NOT_FOUND 시에도 호출이 없음을 검증하는 케이스를 고려해 보세요.
src/test/java/hanium/modic/backend/web/post/controller/PublicPostControllerTest.java (3)
85-86: 주석 수정 필요(null 언급 불일치)검증은
false를 기대하고 있으나 주석은 “null 값 확인”으로 되어 있습니다. 혼동 방지 차원에서 주석을false 값 확인으로 수정하세요.- .andExpect(jsonPath("$.data.isLikedByCurrentUser").value(false)) // null 값 확인 + .andExpect(jsonPath("$.data.isLikedByCurrentUser").value(false)) // false 값 확인
30-33: 테스트 단순화: BaseControllerTest 상속 불필요 가능성
@WebMvcTest+@AutoConfigureMockMvc(addFilters = false)조합에서는 보안 필터가 비활성화되므로,BaseControllerTest상속이 불필요할 수 있습니다. 테스트 격리를 위해 상속 제거를 고려하세요.
74-96: 입력 검증 케이스 보강 제안(@positive 도입 시)컨트롤러에 @Validated/@positive를 적용한다면, 음수/0 ID에 대한 400 응답 테스트를 추가하면 좋습니다. 현재는 비숫자 문자열 케이스만 있습니다.
추가 예시(메서드 추가):
@Test @DisplayName("공개 게시글 조회 - 음수 ID는 400 반환") void getPost_NegativeId_ShouldReturnBadRequest() throws Exception { mockMvc.perform(get("/api/public/posts/{id}", -1)) .andExpect(status().isBadRequest()); verify(postService, never()).getPostForPublic(any()); } @Test @DisplayName("공개 게시글 조회 - 0 ID는 400 반환") void getPost_ZeroId_ShouldReturnBadRequest() throws Exception { mockMvc.perform(get("/api/public/posts/{id}", 0)) .andExpect(status().isBadRequest()); verify(postService, never()).getPostForPublic(any()); }Also applies to: 116-126
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/java/hanium/modic/backend/domain/post/service/PostService.java(1 hunks)src/main/java/hanium/modic/backend/web/post/controller/PublicPostController.java(1 hunks)src/test/java/hanium/modic/backend/domain/post/service/PostServiceTest.java(1 hunks)src/test/java/hanium/modic/backend/web/post/controller/PublicPostControllerTest.java(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/test/java/hanium/modic/backend/domain/post/service/PostServiceTest.java (2)
src/test/java/hanium/modic/backend/domain/user/factory/UserFactory.java (1)
UserFactory(9-29)src/test/java/hanium/modic/backend/domain/image/entityfactory/ImageFactory.java (1)
ImageFactory(16-63)
src/test/java/hanium/modic/backend/web/post/controller/PublicPostControllerTest.java (3)
src/test/java/hanium/modic/backend/base/BaseControllerTest.java (1)
BaseControllerTest(13-49)src/test/java/hanium/modic/backend/domain/post/entityfactory/PostFactory.java (1)
PostFactory(10-36)src/test/java/hanium/modic/backend/domain/user/factory/UserFactory.java (1)
UserFactory(9-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (1)
src/main/java/hanium/modic/backend/web/post/controller/PublicPostController.java (1)
1-32: 보안 설정 확인 완료:/api/public/posts/**접근 허용됨
SecurityConfig.java38번째 줄의.anyRequest().permitAll()설정으로 모든 엔드포인트가 비로그인 상태에서도 접근 가능함을 확인했습니다.추후 보안 정책 강화 시, public API 경로만 별도 permitAll 처리하고 나머지 요청은 인증을 요구하도록 세부 권한 설정을 고려해보세요.
| final String userName = userEntity.getName(); | ||
| final String userImage = userEntity.getUserImageUrl(); | ||
| final boolean hasUserImage = userImage != null; | ||
| final String userEmail = userEntity.getEmail(); | ||
|
|
||
| List<PostImageEntity> postImages = postImageEntityRepository.findAllByPostId(id); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
공개 API에서 사용자 이메일 노출은 PII 위험 — 반환에서 제거/마스킹을 권장
비로그인 공개 엔드포인트에서 userEmail을 그대로 노출하는 것은 개인정보(PII) 유출 리스크가 있습니다. 기존 로그인 전용 응답 DTO를 재사용하더라도, 공개용 서비스에서는 이메일을 제거하거나 마스킹하는 편이 안전합니다.
- 권장안 A(간단/안전): 공개 API에서는
userEmail을 null로 반환 - 권장안 B(대안): 마스킹 처리(예: a***@example.com). 별도 유틸 추가 필요
테스트(PublicPostControllerTest)에서 이메일을 검증하고 있으므로, 정책상 비노출이 맞다면 해당 검증을 제거/수정해야 합니다.
적용 예시(간단 비노출):
- final String userEmail = userEntity.getEmail();
+ // 공개 API: 이메일 비노출(PII 보호)
+ final String userEmail = null;Also applies to: 121-126
🤖 Prompt for AI Agents
In src/main/java/hanium/modic/backend/domain/post/service/PostService.java
around lines 111 to 116 and 121 to 126, the userEmail is exposed in the public
API response, which risks leaking personally identifiable information (PII). To
fix this, modify the code to either set userEmail to null before returning it in
the public API or apply masking to the email address. Additionally, update or
remove any tests in PublicPostControllerTest that validate the presence of
userEmail to align with this new policy.
src/main/java/hanium/modic/backend/web/post/controller/PublicPostController.java
Show resolved
Hide resolved
| .andExpect(jsonPath("$.data.userName").value(mockUser.getName())) | ||
| .andExpect(jsonPath("$.data.userEmail").value(mockUser.getEmail())); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
PII 보호 정책을 따른다면 이메일 검증 제거 필요
공개 엔드포인트에서 이메일 비노출로 변경(권장)하는 경우, 해당 검증은 제거 또는 null 기대값으로 수정되어야 합니다.
- .andExpect(jsonPath("$.data.userName").value(mockUser.getName()))
- .andExpect(jsonPath("$.data.userEmail").value(mockUser.getEmail()));
+ .andExpect(jsonPath("$.data.userName").value(mockUser.getName()));
+ // 공개 API에서는 userEmail 비노출(PII 보호). 필요 시 마스킹으로 변경 가능.
+ // .andExpect(jsonPath("$.data.userEmail").doesNotExist());📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .andExpect(jsonPath("$.data.userName").value(mockUser.getName())) | |
| .andExpect(jsonPath("$.data.userEmail").value(mockUser.getEmail())); | |
| @@ src/test/java/hanium/modic/backend/web/post/controller/PublicPostControllerTest.java | |
| - .andExpect(jsonPath("$.data.userName").value(mockUser.getName())) | |
| - .andExpect(jsonPath("$.data.userEmail").value(mockUser.getEmail())); | |
| + .andExpect(jsonPath("$.data/userName").value(mockUser.getName())); | |
| + // 공개 API에서는 userEmail 비노출(PII 보호). 필요 시 마스킹으로 변경 가능. | |
| + // .andExpect(jsonPath("$.data.userEmail").doesNotExist()); |
🤖 Prompt for AI Agents
In
src/test/java/hanium/modic/backend/web/post/controller/PublicPostControllerTest.java
at lines 91-92, the test currently verifies the user's email in the JSON
response, which may expose PII against policy. To fix this, remove the email
verification assertion or change it to expect a null or absent value for the
email field to comply with PII protection guidelines for public endpoints.
- @validated 어노테이션 추가로 파라미터 검증 활성화 - @positive 어노테이션으로 ID 파라미터 양수 검증 - API 문서 설명 개선: likeCount 포함, isLikedByCurrentUser 고정값 명시 - 400 에러 응답 문서화 추가 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Summary
Closes #130
GitHub Issue #130을 해결하기 위해 비로그인 사용자도 게시글을 조회할 수 있는 공개 API를 구현했습니다.
/api/public/posts/{id}GET 요청/api/posts/{id}- 로그인된 사용자용 (좋아요 정보 포함)구현 내용
Backend Changes
주요 차이점
/api/posts/{id})/api/public/posts/{id})Test Plan
추가 작업 필요
사용자는
application.yml에 다음 설정을 추가해야 합니다:🤖 Generated with Claude Code
Summary by CodeRabbit
신규 기능
테스트