[일정 관리 앱] 리팩토링(5)

2024. 10. 16. 16:06내일배움캠프/Schedule Management

 마지막으로 댓글 관련 CRUD 를 리팩토링을 진행해 보려 한다. 댓글의 경우 댓글에 관련된 모든 요청에 인증이 필요하다. 하지만 그 외 요구사항에 크게 없어 스스로 판단해 반영한 내용이 다수 존재한다. 이번에 리팩토링한 코드는 여기서 확인이 가능하다.

 

0. Comment 엔티티 필드 변경

 기존에는 작성자명(String author)을 사용했지만 이제는 작성자 ID(Long authorId) 를 저장하도록 수정하였다. 이렇게 변경한 이유는 댓글 삭제 및 수정시 대상 댓글을 작성한 회원만이 해당 댓글을 삭제/수정 할 수 있게 구현하다 보니 작성 회원이 맞는지 '검증' 이 필요했다. '검증' 에는 댓글 작성자의 'id' 와 요청 회원의 'id' 를 비교하는 방식을 사용하는 것이 적절하다 생각 필드를 수정하게 되었다. 아무래도 작성자 이름은 '동명인' 의 경우도 있기에 적절하지 않다 생각했다.

 

 

1. 댓글 생성

 댓글 생성시 기존에는 RequestBody 에 작성자명을 RequestBody 로 전달받아 Comment 엔티티를 생성했다면 이제는 필터에서 인증된 회원의 정보(작성자 정보)를 활용하면 되기에 RequestBody 에는 댓글 본문(body)만을 담아 요청하도록 수정하였다.

댓글 생성 요청

 

댓글을 작성할 게시글의 정보는 쿼리 파라미터로 전달받고 댓글 내용은 RequestBody 를 통해 전달 받는다. 그리고 작성자(요청자)의 정보는 필터에서 조회한 회원의 정보를 활용하게 된다.

 

예외의 경우 이전과 동일하다 작성할 게시글이 존재하지 않는 경우 '404 Not Found' 와 예외 코드및 메시지를 반환하는 응답을 하며, 댓글 작성 내용이 유효하지 않는다면 '400 Bad Request' 와 예외 코드및 메시지를 반환하는 응답이 이루어진다.

 

 

2. 댓글 조회 및 댓글 목록 조회

 다른 엔티티와는 다르게 꽤나 수정을 거쳐야 했다. 그 이유는 Comment 엔티티와 Member 엔티티 간의 연관관계가 존재하지 않는 방식으로 구현되어 있기 때문이다. 이러한 방식을 사용한 이유는 이미 연관관계의 흐름이 'Member - Schedule - Comment' 순으로 구성되어 있는데, 이런 표현이 맞는지 모르겠지만 여기서 Comment 와 Member 연관관계를 맺게 되면 Member 엔티티의 연관관계가 너무 무거워(?) 진다 생각했다.

 

2-1. 댓글 조회(단건)

 댓글 조회의 경우 쿼리 파라미터로 조회할 댓글의 'id' 를 전달받도록 구현했다.

댓글 조회 요청

 

댓글 조회의 경우 아래와 같은 과정으로 수행된다.

  1. 요청 파라미터와 같은 'id' 를 갖는 댓글 정보를 조회
  2. 댓글 작성자 이름을 알기 위해 댓글 작성자 ID(Comment.authorId)와 같은 'id' 를 갖는 회원 조회
  3. 응답 DTO 에 조회한 댓글 정보(authorId 제외)와 작성자 이름(Member.name)을 담아 반환

Comment 와 Member 사이에 연관관계를 설정하지 않았기 때문에 2번의 조회를 통해 원하는 값을 얻을 수 있었다.

 

2-2. 댓글 목록 조회

 기존에 댓글 목록 조회시 댓글 작성자의 이름을 검색 조건으로 사용할 수 있도록 구현해 두었다. 검색 조건을 만족(LIKE, 유사일치)하는 댓글들을 반환하며, 검색 조건에 만족하는 댓글이 없다면 빈 목록을 반환한다. 만약 검색 조건이 없는 경우 전체 댓글 목록을 반환한다.

댓글 목록 조회 요청

 

댓글 목록은 아래와 같은 과정을 통해 수행된다.

  1. 검색 조건(작성자명)에 해당하는 모든 회원의 정보를 조회한다.
  2. Map 객체에 조회한 회원들의 정보를 'key = 회원 ID, value = 회원 이름' 형태로 저장한다.
  3. Map 객체의 모든 'key' 값들에 해당하는 모든 댓글들을 조회한다.
  4. 응답 DTO 에 조회한 댓글 정보(authorId 제외)와 Map 객체에서 조회한 작성자명(댓글의 authorId 에 해당하는)을 담아 반환한다.

와...연관관계를 안 맺었다고 (2) ~ (3) 의 과정이 추가되었다. 새삼 연관관계 매핑이 얼마나 편한 기능이었는지 느낄 수 있었다.

 

 

3. 댓글 수정 및 삭제

 맨 처음 말했던 것 처럼 댓글의 수정 및 삭제는 작성자만이 사용할 수 있는 기능으로 구현하고 싶었기 때문에 아래와 같은 과정으로 수행되도록 구현하였다.

  1. 수정/삭제 대상 댓글 조회
  2. 요청 회원이 조회한 댓글을 작성했는지 검증(요청 회원 ID 와 댓글 작성자 ID 를 비교)
  3. 댓글 수정/삭제

만약 (2)의 과정에서 두 데이터가 불일치한다면 요청이 수행되지 않고, 예외 코드 및 메시지와 '403 Forbidden' 응답을 반환한다. API 테스트를 통해 위의 내용대로 기능이 잘 수행되는지 확인해 보았다.

 

3-1. 작성자가 아닌 회원의 요청

댓글 수정 요청 - 작성자가 아닌 경우
댓글 삭제 요청 - 작성자가 아닌 경우

 

댓글 작성자가 아닌 경우 수정/삭제 요청에 대한 권한이 없다는 예외 코드 및 메시지와 '403 Forbidden' 응답이 반환되는 것을 확인할 수 있다.

 

3-2. 작성자인 회원의 요청

 우선 작성자인 회원이 댓글 수정/삭제를 요청하게 되면 요청이 수행되고 수행 결과가 DB 에 반영될 것이다. 수정전 COMMENT 테이블의 상태는 아래와 같다.

댓글 수정전 COMMENT 테이블 상태

 

댓글 수정을 요청한 회원이 댓글 작성자이기에 요청이 정상적으로 수행된 것을 확인할 수 있었다.

댓글 수정 요청 - 작성자인 경우

 

API 테스트 응답만으로는 요청이 제대로 수행됬는지 확인할 수 없으므로 COMMENT 테이블 또한 확인해,  수정 요청대로 댓글 본문이 수정되었으며 수정일 또한 수정시기로 바뀐 것을 확인할 수 있었다.

댓글 수정 후 COMMENT 테이블 상태

 

댓글 삭제 또한 요청 회원이 댓글 작성자이기에 요청이 아래와 같이 정상적으로 수행되었다.

댓글 삭제 요청 - 작성자인 경우

 

삭제 요청 또한 API 테스트 결과만으로는 요청이 정상적으로 수행되었는지 알수 없어 COMMENT 테이블을 확인해, 요청 대상인 댓글이 잘 삭제된 것을 확인할 수 있었다.

댓글 삭제 후 COMMENT 테이블

 

 

4. 마무리

 이렇게 리팩토링을 진행하고 나니 "어? 댓글 수정/삭제에 대한 권한 검증(인가)도 필터에처 처리해야 하나?" 라는 생각이 문득 들었다...해당 내용은 과제 제출후 받은 피드백과 함께 반영해야 할 것 같다. 후...