Conversation
| import org.library.core.presentation.Pagination | ||
| import org.springframework.stereotype.Service | ||
|
|
||
| @Service |
There was a problem hiding this comment.
[MEDIUM] SearchBooksService에 읽기 전용 트랜잭션 경계가 없습니다
Problem: 이 서비스는 순수 조회(검색/목록) 유스케이스인데 @Transactional이 전혀 선언되어 있지 않습니다. 같은 모듈의 동일 성격 유스케이스인 GetBookService는 클래스 레벨에 @Transactional(readOnly = true)를 명시하고 있어, 이 PR만 그 관례에서 벗어납니다.
Evidence: GetBookService는
@Transactional(readOnly = true)를 선언합니다. 트랜잭션 경계·readOnly 여부는 엔티티/영속성 컨벤션에서 명시적으로 점검 대상입니다. 지금은 Spring Data JPA의 기본 트랜잭션에 암묵적으로 의존하고 있어, 조회 로직이 향후 지연 로딩 연관을 다루게 되면 트랜잭션 경계가 서비스가 아닌 리포지토리/어댑터에 암묵적으로 걸리는 구조가 됩니다.
Fix direction: GetBookService와 동일하게 클래스 레벨에 @Transactional(readOnly = true)를 추가해 주세요.
@Service
@Transactional(readOnly = true)
class SearchBooksService(
private val bookSearchPort: BookSearchPort,
) {
...
}There was a problem hiding this comment.
RdbBookSearchAdapter에 @Transactional 반영하였습니다.
SearchBooksService 는 BookSearchPort 만 의존해 DB의 존재를 모르는 유스케이스라 @Transactional 을 붙이면 JPA 트랜잭션 선언이 유스케이스로 올라와 포트를 둔 목적과 어긋난다고 판단
| import org.library.core.presentation.Pagination | ||
|
|
||
| @Schema(description = "도서 목록·검색 응답") | ||
| data class BookSearchResponse( |
There was a problem hiding this comment.
[LOW] BookSearchResponse가 단일 유스케이스 전용인데 모듈 dto/에 위치합니다
Problem: BookSearchResponse는 SearchBooksService 한 곳에서만 사용되는데, 여러 유스케이스가 공유하는 응답을 모아두는 book/dto/ 패키지에 최상위 클래스로 추출되어 있습니다. 프로젝트 컨벤션상 Request/Response는 단일 유스케이스 전용이면 서비스 내부 nested data class여야 하고, 2개 이상 유스케이스가 공유할 때만 dto/로 추출합니다.
Evidence: 같은 패키지의 BookResponse는 CreateBookService, GetBookService, UpdateBookService 세 곳에서 공유되기 때문에 dto/에 위치하는 것이 맞지만, BookSearchResponse는 SearchBooksService 전용입니다.
Fix direction: SearchBooksService 내부의 nested data class로 옮겨주세요.
@Service
class SearchBooksService(
private val bookSearchPort: BookSearchPort,
) {
fun execute(query: String?, params: PageRequestParams): Response { ... }
@Schema(description = "도서 목록·검색 응답")
data class Response(
val books: List<BookDocument>,
val pagination: Pagination,
)
}
연관 이슈
작업 사항
GET /books/search?q=&page=&pageSize=q가 없거나 공백이면 전체 조회, 값이 있으면 제목·저자 부분 일치 검색search.engine값만 바꿔 RDB / OpenSearch를 번갈아 확인할 수 있어 MVP 전후 테스트 가능한 구조로 설계테스트
주의 사항 및 참고사항
멀티모듈 전면 적용이 아니라 변동성이 큰 검색에만 부분 적용