Skip to content

[FEAT] 작가 검색 API #39

@millkk04

Description

@millkk04

작가 검색 API 구현 완료

구현 개요

  • Endpoint: GET /api/v1/search/authors
  • 기능: 검색어에 해당하는 작가 목록과 각 작가의 대표작(최대 2권)을 조회
  • 사용 위치: 검색 화면의 '작가' 탭

주요 특징

1. N+1 문제 해결

  • 2단계 조회 전략 적용
    1. 작가 목록 조회 (페이징)
    2. 작가별 도서 카운트 조회 (GROUP BY)
    3. 작가별 도서 목록 조회 (IN 쿼리)
  • 3개의 쿼리로 모든 데이터 조회
  • @EntityGraph보다 효율적이고 유지보수 용이

2. 페이징 지원

  • 클라이언트 요청에 따라 페이지 단위로 조회
  • 무한 스크롤 UI 지원
  • 최대 페이지 크기: 50

3. 대표작 자동 선정

  • 각 작가당 최대 2권의 대표작 표시
  • 최신 출판일 기준으로 정렬
  • UI 공간 효율성 확보

4. 역할 기반 필터링

  • BookAuthors.role = AUTHOR만 조회
  • 번역가(TRANSLATOR)는 제외
  • 정확한 작가 정보 제공

API 명세

Request

GET /api/v1/search/authors?query={검색어}&page={페이지}&size={크기}
Parameter Type Required Default Description
query String O - 검색 키워드 (작가명)
page int X 1 페이지 번호 (1부터 시작)
size int X 10 페이지 크기 (최대 50)

Response

{
  "page": 1,
  "size": 10,
  "isEnd": true,
  "totalCount": 1,
  "items": [
    {
      "authorId": 42,
      "name": "김영하",
      "profileImageUrl": "https://example.com/authors/kim-younha.jpg",
      "occupation": "소설가",
      "nationality": "한국",
      "bio": "1968년생 한국 소설가...",
      "bookCount": 15,
      "books": [
        {
          "bookId": 1234,
          "title": "살인자의 기억법",
          "thumbnailUrl": "https://example.com/books/1234.jpg",
          "authorNames": ["김영하"],
          "publisherName": "문학동네",
          "publishedAt": "2013-07-15T00:00:00"
        },
        {
          "bookId": 5678,
          "title": "빛의 제국",
          "thumbnailUrl": "https://example.com/books/5678.jpg",
          "authorNames": ["김영하"],
          "publisherName": "문학동네",
          "publishedAt": "2006-11-20T00:00:00"
        }
      ]
    }
  ]
}

예외 처리

1. 검색 결과 없음

{
  "page": 1,
  "size": 10,
  "isEnd": true,
  "totalCount": 0,
  "items": []
}
  • 빈 배열 반환 (404 아님)
  • 프론트엔드에서 "검색 결과가 없습니다" UI 표시

2. 잘못된 입력값

// 빈 검색어
GET /api/v1/search/authors?query=
→ 400 Bad Request: "검색 키워드는 필수입니다."

// 잘못된 페이지 번호
GET /api/v1/search/authors?query=김영하&page=0400 Bad Request: "페이지 번호는 1 이상이어야 합니다."

// 페이지 크기 초과
GET /api/v1/search/authors?query=김영하&size=100400 Bad Request: "페이지 크기는 1~50 사이여야 합니다."

3. 작가는 있지만 도서가 없는 경우

{
  "authorId": 99,
  "name": "신인작가",
  "bookCount": 0,
  "books": []
}
  • 정상 응답
  • UI에서 "등록된 작품이 없습니다" 표시

성능 임계값

  • 작가 수 < 1,000: 현재 전략으로 충분 (응답 시간 < 100ms)
  • 작가 수 1,000~10,000: 인덱스 튜닝 필요
  • 작가 수 > 10,000: Elasticsearch 도입 검토

향후 최적화 예정 후보 목록

  1. 캐싱 전략

    • Redis에 인기 작가 캐싱 (TTL 1시간)
    • 검색 결과 캐싱 (TTL 10분)
  2. Full-Text Search

    • MySQL Full-Text Index 적용
    • 또는 Elasticsearch 도입
    • 한글 형태소 분석기 추가
  3. 비동기 처리

    • 도서 카운트는 비동기로 조회
    • CompletableFuture 활용

주의사항

1. 동명이인 문제

  • 현재 ERD는 authors.name에 UNIQUE 제약이 있음
  • "김영하(소설가)"와 "김영하(시인)"을 구분 불가
  • 단기 해결: shortIntro 또는 bio에 구분 정보 포함
  • 장기 해결: UNIQUE 제약 제거 또는 name_disambiguation 컬럼 추가

2. 부분 검색 성능

  • 현재: LIKE '%keyword%' (전체 검색)
  • 문제: 인덱스를 활용하지 못함
  • 대안: LIKE 'keyword%' (접두사 검색) 또는 Full-Text Search

3. bio 길이 제한

  • DB: LONGTEXT (제한 없음)
  • API: 200자로 자르고 "..." 추가
  • 상세 페이지에서 전체 내용 제공 필요

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions