Action 3/3

CPU 추론 인프라 구축

사내 시니어 엔지니어가 설계한 아키텍처를 기반으로, 상품 벡터를 인덱싱하는 배치 구현임베딩 API 구현을 담당했습니다. 구현 과정에 참여하며 각 컴포넌트의 선택 근거를 이해했고, 세부 내용을 아래에 정리했습니다.

상품 벡터 인덱싱 배치

sequenceDiagram
    autonumber
    participant Dev as 개발자<br/>(CI/CD)
    participant ECR
    participant Airflow as Airflow<br/>(MWAA)
    participant SM as SageMaker
    participant RT as SageMaker<br/>Training Job
    participant PDB as 상품 DB
    participant VDB as 벡터 DB

    rect rgb(245, 245, 245)
        Note over Dev,ECR: 배치 코드 변경 시 1회
        Dev->>ECR: 배치 이미지 build & push
    end

    rect rgb(245, 245, 245)
        Note over Airflow,VDB: 매 시간 반복
        Airflow->>SM: CreateTrainingJob<br/>(image URI, job code)
        SM->>ECR: 이미지 pull
        ECR-->>SM: 이미지
        SM->>RT: 컨테이너 실행
        activate RT
        RT->>PDB: 추천가능상품 fetch
        PDB-->>RT: 상품 목록
        RT->>RT: 상품을 벡터로 변환
        RT->>VDB: 벡터 upsert 및 delete
        deactivate RT
    end
          

번개장터 상품 DB에 등록된 전체 판매 상품들 중 대부분은 오랫동안 클릭되지 않고 방치된 상품입니다 (수요가 있는 상품들은 신속히 판매 완료됨). 따라서, 판매 상품 DB를 실질적으로 추천 가능한 상품들의 카탈로그로 정의하는 내부 로직을 구현하고, 이 중 신규 등록되거나 수정된 상품들을 상품 벡터로 변환해 벡터 DB에 인덱싱하는 배치 task를 구현했습니다. 이를 매 시간마다 SageMaker Training Job 형태로 트리거하는 Airflow DAG를 정의했습니다. 모델 학습이 아닌 배치 작업임에도 SageMaker Training Job을 사용한 이유는, 이미지·파라미터·인스턴스 스펙을 지정해 컨테이너를 실행하는 용도로 팀에서 이를 관행적으로 활용하고 있었기 때문입니다.

이 카탈로그를 저장하고 실시간 유사도 검색을 지원할 벡터 DB 서비스를 선택하기 위해, 팀에서는 Aurora PostgreSQL (pgvector), Milvus, S3 Vectors 세 가지 옵션을 비교했습니다. 필터링을 거친 추천 가능 상품 카탈로그 크기가 수백만 단위였기 때문에, 세 옵션의 성능은 사실상 동등한 수준이었습니다. 이 조건에서는 성능 외의 축인 운영 부담 및 비용 측면에서 옵션들을 비교하게 되었고, 그 결과 Aurora를 선택하는 의사결정이 내려졌습니다.

Aurora vs Milvus — 같은 성능이면 관리가 쉬운 옵션

Milvus를 프로덕션에서 운영하려면 여러 종류의 노드와 스토리지를 쿠버네티스 클러스터 위에서 관리해야 했습니다. 이를 도입하는 것은 데브옵스 팀에게 각 컴포넌트의 배포, 모니터링, 버전 업그레이드 등의 새로운 관리 포인트들을 추가하는 선택지였습니다. 반면, 이미 표준으로 운영중이었던 RDS 클러스터에 pgvector 익스텐션을 추가하면 추가 learning curve 없이 벡터 검색 기능을 확보할 수 있었고, 이 편의성이 Aurora 선택의 근거였습니다. 물론 카탈로그의 크기가 지속적으로 커진다면 벡터 인덱스가 클러스터 메모리에 담기지 않는 시점에 Milvus 등의 대안을 검토해야 하겠지만, 예측 가능한 미래 시점까지는 Aurora로 충분하다는 판단이었습니다.

Aurora vs S3 Vectors — 같은 관리 난이도면 저렴한 옵션

두 옵션 모두 완전관리형 서비스이기 때문에 별도 인프라 구축이 필요 없다는 점에서 관리 난이도가 동일하게 낮았습니다. 하지만 이 추천 시스템은 홈 추천 및 상품상세 추천 지면 모두에서 호출하기 때문에 요청 수가 많았습니다. S3 Vectors의 요금 구조(요청 수 + 요청당 scan 데이터 크기)는 인스턴스 시간당 고정 요금인 Aurora 대비 높은 QPS 워크로드에서 비용이 빠르게 증가할 위험이 있었습니다. 이 위험을 검증하기 위해 S3 Vectors가 출시된 이후 동일한 벡터 카탈로그를 S3 Vectors에 구축하고 추천 시스템 트래픽의 10%를 라우팅하는 PoC가 2주 동안 진행되었습니다. PoC 기간 동안 두 서비스의 검색 latency 및 추천 CTR은 유사한 수준이었지만, 10% 트래픽 기준 실측 비용을 100%로 환산한 결과 S3 Vectors의 월 예상 비용이 Aurora 대비 3배 수준으로 산출되었습니다. 이를 근거로 Aurora를 유지하는 원안이 확정되었습니다.

상품 벡터 임베딩 API

sequenceDiagram
    autonumber
    participant Client
    participant RecAPI as 추천 API
    participant EmbAPI as 임베딩 API
    participant VectorDB as 벡터 DB

    Client->>RecAPI: 클릭한 상품 정보<br/>(ex. 상품명, 카테고리 등)
    RecAPI->>EmbAPI: 임베딩 요청
    EmbAPI-->>RecAPI: 임베딩 반환
    RecAPI->>VectorDB: 유사 벡터 검색
    VectorDB-->>RecAPI: 검색 결과 반환
    RecAPI-->>Client: 추천 결과 응답
          

사내 백엔드 표준 스택은 Kotlin 기반의 Spring Boot 프레임워크였지만, 임베딩 API는 상품 feature들을 벡터로 변환하기 위해 PyTorch, transformers 등 Python ML 스택이 필요한 컴포넌트라 별도 서비스로 구현했습니다. FastAPI로 구현된 임베딩 API를 uvicorn 워커 프로세스 1개로 실행하고 gunicorn이 관리하는 표준 구성으로 이미지를 만들어 ECR에 업로드했고, 사내 EKS 클러스터를 관리하는 데브옵스 팀이 이 이미지와 추천 영역에서 발생하는 예상 최대 RPS를 기반으로 HPA 스케일링 정책을 튜닝했습니다. 경량 인코더를 개발하고 개선하는 과정에서 동일 CPU 노드 풀에서 처리 가능한 처리량이 증가했고, 이는 프로덕션 서빙에 필요한 replica 수와 인스턴스 규모의 감소로 이어졌습니다. 이를 통해 알고리즘 개선의 이점을 프로덕션 운영 비용 절감으로 연결할 수 있었습니다.