diff --git a/src/main/java/com/hansung/leafly/domain/book/entity/enums/BookGenre.java b/src/main/java/com/hansung/leafly/domain/book/entity/enums/BookGenre.java index 384b05b..d2c3e0a 100644 --- a/src/main/java/com/hansung/leafly/domain/book/entity/enums/BookGenre.java +++ b/src/main/java/com/hansung/leafly/domain/book/entity/enums/BookGenre.java @@ -5,22 +5,29 @@ @RequiredArgsConstructor public enum BookGenre { - FICTION("소설/시/희곡"), - ESSAY("에세이"), - SELF_IMPROVEMENT("자기계발"), - SCIENCE("과학"), - HISTORY("역사"), - ECONOMY("경제경영"), - ART("예술/대중문화"), - HUMANITIES("인문학"), - HOME("가정/요리/뷰티"), - TRAVEL("여행"), - HEALTH("건강/취미/레저"); + FICTION("소설/시/희곡", "1"), + ESSAY("에세이", "55889"), + SELF_IMPROVEMENT("자기계발", "336"), + SCIENCE("과학", "987"), + HISTORY("역사", "74"), + ECONOMY("경제경영", "170"), + ART("예술/대중문화", "517"), + HUMANITIES("인문학", "656"), + HOME("가정/요리/뷰티", "1230"), + TRAVEL("여행", "1196"), + HEALTH("건강/취미/레저", "55890"), - private final String value; + ALL("전체", null); + + private final String value; // 한글 노출 이름 + private final String categoryId; // Aladin CategoryId @JsonValue public String getValue() { return value; } + + public String getCategoryId() { + return categoryId; + } } diff --git a/src/main/java/com/hansung/leafly/domain/book/service/BookService.java b/src/main/java/com/hansung/leafly/domain/book/service/BookService.java index 092539c..e79ecd7 100644 --- a/src/main/java/com/hansung/leafly/domain/book/service/BookService.java +++ b/src/main/java/com/hansung/leafly/domain/book/service/BookService.java @@ -1,5 +1,6 @@ package com.hansung.leafly.domain.book.service; +import com.hansung.leafly.domain.book.entity.enums.BookGenre; import com.hansung.leafly.domain.book.web.dto.BookFilterReq; import com.hansung.leafly.domain.book.web.dto.BookInfoRes; import com.hansung.leafly.domain.book.web.dto.SearchRes; @@ -14,4 +15,6 @@ public interface BookService { BookInfoRes details(Long isbn, Member member); BookInfoRes ocr(MultipartFile file, Member member); + + List category(BookGenre genre, Member member); } diff --git a/src/main/java/com/hansung/leafly/domain/book/service/BookServiceImpl.java b/src/main/java/com/hansung/leafly/domain/book/service/BookServiceImpl.java index 8351eac..f746450 100644 --- a/src/main/java/com/hansung/leafly/domain/book/service/BookServiceImpl.java +++ b/src/main/java/com/hansung/leafly/domain/book/service/BookServiceImpl.java @@ -15,6 +15,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.util.HashSet; @@ -25,6 +26,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) @Slf4j public class BookServiceImpl implements BookService { private final AladinClient aladinClient; @@ -101,6 +103,35 @@ public BookInfoRes ocr(MultipartFile file, Member member) { return details(isbn, member); } + @Override + public List category(BookGenre genre, Member member) { + AladinSearchRes response; + + if (genre == BookGenre.ALL) { + // 전체 → 인기 도서 탐색 + response = aladinClient.bestSeller(); + } else { + // 장르 검색 + response = aladinClient.searchByCategory(genre.getCategoryId()); + } + + if (response == null || response.item() == null) { + return List.of(); + } + + Set bookmarkedSet = new HashSet<>( + bookmarkRepository.findIsbnsByMemberId(member.getId()) + ); + + return response.item().stream() + .filter(item -> item.isbn13() != null && !item.isbn13().isBlank()) + .map(item -> SearchRes.from( + item, + bookmarkedSet.contains(Long.parseLong(item.isbn13())) + )) + .toList(); + } + //카테고리 필터링 private boolean matchesGenre(AladinBookItem item, List targetGenres) { String middle = extractMiddleCategory(item.categoryName()); diff --git a/src/main/java/com/hansung/leafly/domain/book/web/controller/BookController.java b/src/main/java/com/hansung/leafly/domain/book/web/controller/BookController.java index 097c8f0..4731536 100644 --- a/src/main/java/com/hansung/leafly/domain/book/web/controller/BookController.java +++ b/src/main/java/com/hansung/leafly/domain/book/web/controller/BookController.java @@ -1,5 +1,6 @@ package com.hansung.leafly.domain.book.web.controller; +import com.hansung.leafly.domain.book.entity.enums.BookGenre; import com.hansung.leafly.domain.book.service.BookService; import com.hansung.leafly.domain.book.web.dto.BookFilterReq; import com.hansung.leafly.domain.book.web.dto.BookInfoRes; @@ -54,4 +55,12 @@ public ResponseEntity> ocr( return ResponseEntity.status(HttpStatus.OK).body(SuccessResponse.from(res)); } + @GetMapping("/category") + public ResponseEntity>> category( + @RequestParam BookGenre genre, + @AuthenticationPrincipal CustomMemberDetails memberDetails + ){ + List res = bookService.category(genre, memberDetails.getMember()); + return ResponseEntity.status(HttpStatus.OK).body(SuccessResponse.from(res)); + } } diff --git a/src/main/java/com/hansung/leafly/infra/aladin/AladinClient.java b/src/main/java/com/hansung/leafly/infra/aladin/AladinClient.java index 9b3aa41..b39b150 100644 --- a/src/main/java/com/hansung/leafly/infra/aladin/AladinClient.java +++ b/src/main/java/com/hansung/leafly/infra/aladin/AladinClient.java @@ -66,5 +66,19 @@ public AladinSearchRes searchByCategory(String categoryId) { return restTemplate.getForObject(uri, AladinSearchRes.class); } + + public AladinSearchRes bestSeller() { + String uri = UriComponentsBuilder.fromHttpUrl(SEARCH_URL) + .queryParam("ttbkey", TTB_KEY) + .queryParam("QueryType", "Bestseller") + .queryParam("SearchTarget", "Book") + .queryParam("MaxResults", 20) + .queryParam("output", "js") + .queryParam("Version", "20131101") + .build() + .toUriString(); + + return restTemplate.getForObject(uri, AladinSearchRes.class); + } }