크롤링 시 확보할 상품 정보는 다음과 같다.
| 항목 | 예시 | 비고 |
|---|---|---|
| 상품명(original) | [무아스] 마카롱 3구 USB 고용량 큐브 멀티탭 | 원본 그대로 저장 |
| 상품명(display) | 마카롱 USB 멀티케이블 | 노출용 가공 이름 |
| 가격 | 29,000 | 정수(원 단위) |
| 이미지 링크 | https://...jpg | 대표 이미지 |
| 상품 링크 | https://10x10.co.kr/... | 상세 페이지 URL |
| 카테고리 | 가전 > PC주변기기 | 다단계 가능 |
| 키워드(해시태그) | #USB #멀티탭 #책상정리 | 검색 최적화용 |
| 리뷰수 | 120 | 별점과 함께 점수 계산에 사용 |
| 별점 | 4.8 | JSON-LD 또는 이미지 파싱 |
| 판매자명 | 무무샵 | 출처 표기 |
| 플랫폼명 | 텐바이텐, 네이버 | 수집처 표기 |
단순히 크롤링 스크립트를 실행하는 방식으로도 데이터를 수집할 수 있지만, 이 접근법은 여러 가지 문제가 있었다. 우선 관리자가 현재 어떤 페이지까지 수집되었는지, 중복이 발생했는지 알 수 있는 방법이 없다. 또한 여러 페이지를 동시에 크롤링하면 충돌이나 중복 저장 문제가 발생할 수 있다.
추가로 운영 환경에서는 관리자가 직접 수집을 트리거하고 상태를 확인할 수 있는 구조가 필요했다. 프론트엔드 담당자와 논의한 결과 관리자가 대시보드에서 버튼을 눌러 수집을 시작하고 상태를 확인할 수 있는 흐름이 이상적이라고 판단했다.
예시 흐름
관리자 트리거 클릭 → GitHub Actions 실행 → 크롤링 완료 후 DB 저장
관리자 페이지와 서비스 API의 요구사항이 다르기 때문에 설계를 고민했다. 관리자용은 상품 컨펌 여부, 키워드, 가격대 등 다양한 조건으로 필터링과 정렬이 필요하다. 반면 서비스용 API는 사용자의 성별·연령대 조건과 점수를 기반으로 추천 리스트를 제공해야 한다. 두 용도를 같은 API로 처리하면 로직이 지나치게 복잡해지고 유지보수가 어려워질 우려가 있었다.
CRUD: 상품 생성/수정/삭제/조회
필터링/정렬
GET /admin/products?isConfirmed=false&minPrice=10000&maxPrice=1000000&searchKeyword=건강
상품 추천에는 두 가지 점수가 필요했다.
관리자가 직접 부여한 점수(수동)와 리뷰·별점 기반의 자동 점수를 합산해야 한다. 단순히 score 값만으로 필터링하거나 score >= 5를 adminCheck = true와 동일하게 간주하려 했지만 이 방식은 정책 변경 시 혼란을 초래할 가능성이 컸다. 또한 관리자가 컨펌한 상품을 명시적으로 구분하지 못해 운영에서 불편함이 예상됐다.
총점 = (관리자 점수) + (자동 점수)
+10, +20 단위로 부여score += 10과 adminCheck = true 동시 적용리뷰 100개 이상 → +1
별점 4점 이상 → +1
리뷰 1만개 이상 → 추가 가점adminCheck boolean을 모두 유지이번 설계에서는 데이터 수집 → 점수화 → 필터링 → 추천의 전체 흐름을 명확히 정의할 수 있었다. 크롤링을 단순 스크립트로만 처리하면 충돌과 중복 문제가 발생하고 관리자가 상황을 파악하기 어렵다는 한계를 확인했다. 이를 해결하기 위해 GitHub Actions와 큐 기반 단일 실행 구조를 설계하여 안정성과 가시성을 동시에 확보했다.
API 설계에서는 관리자용과 서비스용 API를 명확히 분리함으로써 복잡도를 줄이고 확장성을 확보했다. 점수 설계에서는 단일 score만으로 운영하려던 초기 설계의 모호함을 깨닫고 점수와 adminCheck를 분리해 관리자가 명시적으로 컨펌할 수 있는 구조를 도입했다. 이 과정을 통해 운영·확장·정책 변경에 유연한 시스템을 설계하는 사고방식을 배웠으며 데이터 품질과 추천 신뢰성을 확보하려면 기술적 구조와 관리 전략이 함께 고려되어야 한다는 점을 체감했다.