책 읽는 즐거움을 공유하고, 지식과 감상을 나누는 책 덕후들의 커뮤니티 서비스 주요 기능 : 대시보드, 알림 관리, 사용자 관리, 도서 관리, 리뷰 관리, 댓글 관리
DB 관리 : ERD 통합 리뷰 관리 구현 : 도메인 설계 및 CRUD, API 구현, 고도화
정보
- 리뷰는 다음의 정보를 가집니다.
- 각 정보의 적절한 유효성 검사가 이루어져야 합니다.
등록
- 도서 별 1개의 리뷰만 등록할 수 있습니다.
수정
- 본인이 작성한 리뷰만 수정할 수 있습니다.
삭제
관련된 정보(좋아요, 댓글, 활동 점수 등)가 유지되도록 논리 삭제를 기본 원칙으로 하세요.
<aside> 💡
인기 도서, 파워 유저 점수를 산출할 때 논리 삭제된 데이터도 포함합니다.
</aside>
단, 물리 삭제 시 관련된 정보도 모두 삭제되도록 하세요.
<aside> ⚠️
물리 삭제 기능은 UI로 제공하지 않습니다. 테스트 코드를 통해 검증하세요.
</aside>
목록 조회
- 키워드로 다음의 속성 중 하나라도 부분일치 하는 데이터를 검색할 수 있습니다.
- 리뷰 작성자 닉네임, 내용, 도서 제목
- 다음의 조건을 통해 조회할 수 있으며, 완전 일치 조건입니다.
- 작성자 ID, 도서 ID
- 조회 조건이 여러 개인 경우 모든 조건을 만족한 결과로 조회합니다.
- 다음의 조건으로 정렬 및 페이지네이션을 구현합니다.
- 시간(
createdAt), 평점(rating)- 여러 개의 정렬 조건 중 선택적으로 1개의 정렬 조건만 가질 수 있습니다.
- 정확한 페이지네이션을 위해 내부적으로 **{이전 페이지의 마지막 요소 생성 시간}**을 두번째 정렬 조건으로 활용합니다.
after- 헤더의 요청자 정보를 통해 좋아요 여부를 같이 포함하세요.
likedByMePPT 제작 팀원 2명 PR 리뷰 담당
사용한 기술 스택
- JAVA
- H2
- PostgreSQL 17
- Flyway
- Junit
- Spring
- Spring Boot
- Spring Boot Actuators
- Spring Data JPA
- Swagger API
- Lombok
- Mapstruct
- Query DSL
주요 기술 기능
- 검색 조건이 있을 경우 Query DSL 사용해 동적 쿼리 고도화, 타입 안정성 확보
- MapStruct을 사용해 보일러플레이트 코드 제거, 타입 안전성 향상
- Swagger API를 사용해 API 명세화
- Caffeine을 사용해서 성능 향상
- 비관적 락을 사용해 정합성 확보
- EntityGraph를 사용해 N+1 문제 해결
MapStruct의 @InheritConfiguration를 사용해 매핑을 재사용하던 중 도서랑 유저 정보가 제대로 매핑이 되지 않는 문제가 발생했습니다. 매개변수가 2개 이상인 경우에는 MapStruct는 source parameter가 여러 개가 되므로 어떤 객체에서 값을 가져올지 지정하지 않아서 생긴 문제였습니다. 그래서 각 필드를 명시적으로 지정하는 방식으로 해결했습니다.
리뷰를 등록하고 삭제한 뒤 다시 리뷰를 작성이 안되는 문제가 발생했습니다. DDL 작성할 때 사용자는 책별 1개의 리뷰만 작성하도록 하기 위해서 책ID, 유저ID를 복합 유니키로 한 것이 문제였습니다. 물리 삭제일 경우 문제가 없지만 논리 삭제일 경우에는 관련 정보가 남아있어 DB에서 이미 있는 정보로 인식해서 재등록이 안되는 것이었습니다. 그래서 복합 유니키를 제거하고 복합키를 deleted_at이 null 인 경우만 적용이 되도록 조건부 인덱스를 적용했습니다. 로컬에서는 실행이 됐지만 테스트코드에서는 에러가 떴습니다. PostgreSQL에는 조건부 인덱스가 적용이 되지만 H2를 사용하는 테스트코드에서는 해당 기능을 지원하지 않아 생긴 문제였습니다. 그래서 복합 유니크 키를 제거하고 서비스에서 BookId, UserId의 deleteAt이 null일 때는 리뷰 생성을 막는 방법으로 바꿔서 해결했습니다.
구현한 코드를 설명하면서 생각하지 못한 부분들을 많이 알게 되었습니다. 또한 새로운 CodeRabbit, Flyway, Caffeine 등 다양한 기술과 도구를 사용해보면서 새로운 경험을 할 수 있었습니다. https://github.com/sb08-deokhugam-redhorse/sb08-deokhugam-teamRedHorse/pull/98 https://github.com/sb08-deokhugam-redhorse/sb08-deokhugam-teamRedHorse/pull/90