2025-12-04

오늘 배운 것

  • 검색 기능 구현시 극한의 성능 어캐 낼껀지
    • 검색 기능 성능 최적화 전체 구조
      1. SQL 최적화
      2. 인덱스 설계
      3. 캐싱 전략
      4. 전문 검색 엔진 도입(Elasticsearch)
      5. 아키텍처/데이터 모델 최적화
    • SQL 자체 성능 최적화
      • 가장 중요한 5가지
        • WHERE 조건에 인덱스 컬럼 사용
        • LIKE %keyword% → 인덱스 절대 못탐
          • LIKE ‘keyword%’ → 인덱스 사용가능
          • LIKE ‘%keyword%’ 는 전문 검색 엔진 필요
        • 정렬 → 인덱스 없으면 전체 정렬
        • LIMIT + OFFSET 시 뒤로 갈수록 느려짐
        • 불필요한 JOIN 제거
    • 인덱스 설계
      • B+Tree 인덱스
        • 가장 기본적이고 가장 많이 사용되는 인덱스
        • 속도
          • 동등 비교(=) → 매우 빠름
          • 범위 검색 (≥, ≤, BETWEEN) → 빠름
      • 복합 인덱스
        • 예 : (category_id, created_at)
        • 정렬 + 필터링을 동시에 빠르게 만들 수 있음
          • categori_id로 필터링
          • created_at 으로 정렬
        • 정렬 + LIMIT 조회는 인덱스로 하면 거의 메모리급 속도
      • 커버링 인덱스
        • SELECT하는 모든 컬럼이 인덱스에 있으면 테이블로 안 내려가고 인덱스만 읽음
    • 캐싱
      • 검색 기능은 보통 동일한 키워드로 반복 검색되는 경우가 많음
      • Redis 캐싱
        • 검색 결과를 Redis 에 저장 → 즉시 응답
        • TTL(만료시간) 설정해서 최신성 유지
      • Local Cache (Caffeine)
        • API 서버 메모리에 저장
        • 네트워크 타지 않아 속도 더 빠름
        • 단, 서버가 여러대면 일관성 깨짐
      • 쿼리 캐시 전략
        • 핫한 키워드 캐시
        • Top N 조회수 높은 문서 캐시
        • 최근 검색 기록 캐시
      • 실제 서비스에서는 검색은 70% 캐시, 30% 실쿼리
    • 전문 검색 엔진
      • SQL LIKE로는 ‘%word%’ 전체 문자열 검색을 절대 빠르게 할 수 없음
      • 대규모 서비스는 반드시 Elasticsearch 같은 검색 엔진을 사용
      • 빠른 이유
        • 역 인덱스
          • 문서 → 단어, 가 아닌 단어 → 해당 문서 리스트 구조로 저장
          • 검색할 때 테이블 전체 스캔이 아니라 단어 사전에서 바로 문서를 찾음

            “안녕 나는 수아야” → 안녕: [문서1] → 나는: [문서1] → 수아야: [문서1]

        • 형태소 분석기
          • 한국어는 띄어쓰기만으로는 검색 성능이 안 나오기 때문에 형태소 분석으로 단어를 쪼갬
          • 검색 정확도와 속도 엄청 증가

            “네이버에서 실시간 검색” → 네이버 / 실시간 / 검색

        • 스코어링
          • ES는 단순 필터링이 아니라 연관도 점수를 계산해서 정렬까지 해줌
    • 데이터 모델링 / 구조 최적화
      • 테이블 분리(샤딩 / 파티셔닝)
        • 검색 대상이 많으면
          • 날짜 기반 파티셔닝
          • 카테고리 기반 분리
          • Elasticsearch에 색인 분산
        • 비정규화
          • 조인 비용을 줄이기 위해 읽기 전용 필드를 중복 저장
            • 게시글 검색에 user.name 조인이 느리면 게시글 테이블에 user_name을 아예 둠
    • 실제 서비스에서 공통으로 사용
      • AND/OR 조합 최소화
        • 복잡한 조합은 필터 스플릿/리팩터링
        •   WHERE (category = 1 AND tags LIKE '%A%')
               OR (category = 1 AND tags LIKE '%B%')
          
          • 이런 쿼리는 인덱스를 못탐
          • 조건을 쪼개서

              WHERE category = 1
                AND (tags LIKE '%A%' OR tags LIKE '%B%')
              //혹은
              WHERE category = 1
              ///으로 먼저 필터링 하여 검색 범위를 대폭 줄임
              //또는 태그를 역 정규화 해서 검색 엔진에 넣음 -> 쿼리가 단순
            
      • LIMIT + OFFSET 위주라면 Cursor 기반 페이징
        • OFFSET이 커질수록 느려짐
        • Cursor 방식으로 즉시 점프 가능
          • 몇개 버리고 조회가 아니라 뭐 특정 필드의 값 이후 전체를 조회해서 무한 스크롤 상화에서도 빠르게 조회가능
          • 쿼리로 구현하는 것
      • 캐시 앞단에 CDN 사용(정적 검색 결과)
        • 자동완성, 추천 검색어 같은 건 CDN 에도 가능
      • 실시간 인덱싱 vs 배치 인덱싱 전략 분리
        • 실시간으로 인덱스 업데이트하기엔 너무 비싸므로 변경사항만 파이프라인으로 색인

results matching ""

    No results matching ""