Conversation
Neibce
left a comment
There was a problem hiding this comment.
수고하셨습니다 다 잘 구현해주셨네요! 코멘트 몇 개 달아뒀으니 확인해보시면 될 거 같습니다
무조건 코멘트 대로 고치는 게 좋다는 건 아니고, 참고 정도로 보시면 될 거 같습니다..!
| enabled: true | ||
|
|
||
| jwt: | ||
| secret: zwKNCyglJK435Wj0ylqi/KF5xubUPnzYOQj8Jkl9QWxea4xj100mCRA9tNXjldjvDaQWo9neQCutSAjNd+N4uw== |
There was a problem hiding this comment.
지금은 문제 없지만, 실제 서비스 개발 시에는 보안 문제로 인해 jwt secret을 깃에 올리지 않고, 환경변수 등으로 관리해야 합니다!
| Post created = svc.create( | ||
| req.memberId(), | ||
| req.title(), | ||
| req.content() | ||
| ); | ||
| return PostResponse.from(created); |
There was a problem hiding this comment.
인증/인가까지 시큐리티로 잘 구현해주신 거 같은데, 이 부분에도 로그인된 유저를 자동으로 가져오도록 해보면 좋을 거 같습니다
| @PutMapping("/{id}") | ||
| public PostResponse update(@PathVariable Long id, @Valid @RequestBody PostUpdateRequest req) { | ||
| Post updated = svc.update(id, req.title(), req.content()); | ||
| return PostResponse.from(updated); | ||
| } | ||
|
|
||
| @ResponseStatus(HttpStatus.NO_CONTENT) | ||
| @DeleteMapping("/{id}") | ||
| public void delete(@PathVariable Long id) { | ||
| svc.delete(id); | ||
| } |
There was a problem hiding this comment.
수정, 삭제에도 자신이 쓴 게시글인지 검증하는 로직을 한번 추가해보시면 좋을 거 같습니다
| /** PostController.list 에서 쓰는 메서드 */ | ||
| @Transactional(readOnly = true) | ||
| public List<Post> findAll() { | ||
| return postRepository.findAll(); |
There was a problem hiding this comment.
postRepository.findAll() 호출 후, 필터링을 하도록 구현하셨는데, 이럴 경우 일단 DB에서 모든 데이터를 가져온 뒤 필터링을 진행하기 때문에 데이터가 많을 경우 자원 소모가 심하고 OOM 발생 가능성도 있어 보입니다..!
|
|
||
| public interface PostRepository extends JpaRepository<Post, Long> { | ||
|
|
||
| List<Post> findByAuthorIdOrderByIdDesc(Long memberId); |
There was a problem hiding this comment.
이 부분에서 n+1 문제가 발생할 거 같은데, n+1 문제와 해결방법에 대해 알아보시면 좋을 거 같습니다!
| public record MemberCreateRequest( | ||
| @NotBlank String username, | ||
| @NotBlank String password, | ||
| String nickname, | ||
| String bio | ||
| ) {} |
There was a problem hiding this comment.
여기에 vaildation을 좀 더 걸어보는 것도 좋을 거 같습니다
변경점 👍
Member엔티티 /MemberRepository/MemberService/MemberController구현GET /members?q=) 기능 추가Post,Comment엔티티에author(Member) 연관관계 추가PostCreateRequest,CommentCreateRequest에memberId필드 추가PostService,CommentService에서 생성 시memberId로Member조회 후author설정GET /members/{memberId}/posts: 해당 멤버가 작성한 게시글 목록 조회GET /members/{memberId}/comments: 해당 멤버가 작성한 댓글 목록 조회GET /members/{memberId}/likes: 해당 멤버가 좋아요한 게시글 목록 조회PostRepository,CommentRepository,PostLikeRepository에 member 기준 조회 메서드 추가PostLike엔티티 /PostLikeRepository/PostLikeService/PostLikeController구현POST /posts/{postId}/likes: 좋아요 추가DELETE /posts/{postId}/likes: 좋아요 취소GET /posts/{postId}/likes/count: 게시글 좋아요 수 조회Follow엔티티 /FollowRepository/FollowService/FollowController구현POST /members/{memberId}/follow/{targetId}: 팔로우DELETE /members/{memberId}/follow/{targetId}: 언팔로우GET /members/{memberId}/followers: 팔로워 목록 조회GET /members/{memberId}/followings: 팔로잉 목록 조회버그 해결 💊
PostService에findAll,findById메서드 추가 및 사용하도록 정리CommentService에list메서드 추가 및 컨트롤러와 일치하도록 시그니처 정리테스트 💻
다음 시나리오를 기준으로 로컬에서 수동 테스트 수행했습니다. (
localhost:8080)멤버 생성 및 조회
POST /members로 멤버 2명(user1, user2) 생성id기준으로GET /members/{id}및GET /members?q=user호출해 검색 동작 확인게시글 생성 및 멤버별 게시글 조회
POST /posts요청 시 body에memberId(user1) 포함하여 게시글 생성GET /members/{memberId}/posts호출 시 해당 멤버가 작성한 게시글만 조회되는지 확인댓글 생성 및 멤버별 댓글 조회
POST /posts/{postId}/comments요청 시memberId(user2) 포함하여 댓글 생성GET /members/{memberId}/comments호출 시 해당 멤버가 작성한 댓글만 조회되는지 확인게시글 좋아요 및 멤버별 좋아요 조회
POST /posts/{postId}/likes로 user2가 게시글 좋아요GET /posts/{postId}/likes/count으로 좋아요 수가 1 증가했는지 확인GET /members/{memberId}/likes로 user2가 좋아요한 게시글 목록 조회 확인팔로우/언팔로우
POST /members/{followerId}/follow/{targetId}로 user2 → user1 팔로우GET /members/1/followers,GET /members/2/followings로 관계 반영 여부 확인DELETE /members/{followerId}/follow/{targetId}이후 다시 조회해 언팔로우 처리 확인4주차 내용도 같이 올립니다.
변경점 👍
JWT 기반 인증/인가 도입
application.yml에 H2 / JPA / JWT 설정 추가회원 도메인 확장
Member엔티티에password필드 추가 및usernameunique 제약 설정MemberRepository에findByUsername,existsByUsername메서드 추가MemberCreateRequest)에password필드 추가MemberService.create()에서 아이디 중복 체크 및 비밀번호 BCrypt 인코딩 후 저장인증 API 추가
POST /auth/signup: 회원가입 엔드포인트 추가 (AuthController)POST /auth/login: 로그인 + JWT Access Token 발급 엔드포인트 추가JWT 인프라 구성
JwtTokenProvider: 토큰 생성/검증 및 Authentication 생성JwtAuthenticationFilter:Authorization: Bearer ...헤더에서 토큰 추출 후SecurityContext에 인증 정보 주입SecurityConfig:/auth/**,/h2-console/**, 모든GET요청은 허용POST / PUT / DELETE요청은 인증 필요PasswordEncoder빈 등록버그 해결 💊
테스트 💻
./gradlew bootRun으로 서버 기동Invoke-RestMethod를 사용해 다음 시나리오 수동 검증POST /auth/signupusername,password,nickname,bio로 회원가입 요청id,username확인POST /auth/loginaccessToken,tokenType,memberId,username수신 확인POST /postsaccessToken을Authorization: Bearer {token}헤더에 설정memberId,title,content를 담아 게시글 생성 요청id,title,content확인GET /posts