Skip to main content

프로젝트: 상품 추천 시스템

Views 18약 11분생성형 AI 활용

추천 시스템 프로젝트는 겉으로 보면 꽤 멋집니다. 사용자가 앱을 열면 알아서 좋아할 만한 상품이 나타나니까요. 하지만 실제로 만들어 보면, 이 프로젝트의 본질은 '취향을 읽는 마법'이 아니라 '수많은 상품 중 지금 보여 줄 몇 개를 뽑는 운영 시스템'에 더 가깝습니다. 모델은 그중 한 부품일 뿐입니다. 어떤 로그를 남길지, 어떤 화면에서 어떤 추천을 할지, 무엇을 성공이라고 볼지, 성능과 비용을 어떻게 맞출지까지 함께 설계해야 비로소 추천이 제품이 됩니다.

이 장에서는 전자상거래 서비스를 예로 들어 상품 추천 시스템을 처음부터 설계해 봅니다. 홈 화면 추천, 상품 상세 페이지의 연관 상품 추천, 장바구니 옆 추천처럼 실제 화면을 떠올리면서 진행할 것입니다. 중요한 것은 알고리즘 이름을 많이 아는 것이 아닙니다. 추천 문제를 데이터 구조로 바꾸고, 가장 단순한 기준선부터 출발해, 점진적으로 더 똑똑한 시스템으로 키워 가는 감각을 익히는 것입니다.

프로젝트: 상품 추천 시스템

추천 프로젝트는 화면에서 시작한다

처음 추천 시스템을 만들 때 많은 팀이 바로 협업 필터링이나 임베딩 모델을 떠올립니다. 하지만 실제 프로젝트의 출발점은 모델이 아니라 화면입니다. 추천이 어디에 들어가는지에 따라 정답이 달라지기 때문입니다.

예를 들어 홈 화면 추천은 사용자가 무엇을 좋아할지 넓게 탐색하게 만드는 역할이 큽니다. 반면 상품 상세 페이지의 추천은 지금 보고 있는 상품과 자연스럽게 이어지는 대안을 보여 주는 것이 중요합니다. 장바구니 옆 추천은 이미 구매 의도가 생긴 사람에게 함께 살 만한 상품을 제안하는 문제에 가깝습니다. 같은 추천이라도 목적이 완전히 다릅니다.

그래서 프로젝트를 시작할 때는 먼저 이렇게 적는 편이 좋습니다.

"우리는 전자상거래 앱의 홈 화면과 상품 상세 페이지에서 개인화 추천을 제공한다. 1차 목표는 클릭과 장바구니 담기 증가이고, 2차 목표는 구매 전환과 재방문율 개선이다."

이 한 문장만 있어도 많은 것이 정리됩니다. 추천 대상이 상품이라는 점, 추천 위치가 홈과 상세 페이지라는 점, 단기 목표와 장기 목표가 다르다는 점이 분명해집니다. 추천 시스템은 늘 '누구에게 무엇을 보여 줄까'와 함께 '어느 순간에 보여 줄까'를 같이 묻는 문제라는 사실을 여기서부터 체감하게 됩니다.

먼저 수집할 데이터를 정하지 않으면 추천은 자라지 못한다

추천 프로젝트에서 가장 흔한 실패는 모델이 약해서가 아니라 로그가 부족해서 생깁니다. 특히 입문 팀은 클릭 로그만 있으면 될 것 같다고 생각하기 쉽습니다. 하지만 추천에서는 클릭보다 더 중요한 로그가 있습니다. 바로 노출 로그입니다. 사용자가 클릭하지 않았다는 사실은, 그 상품이 실제로 화면에 보였을 때만 의미가 있기 때문입니다. 아예 보여 주지도 않았는데 클릭이 없었다고 기록하면, 모델은 현실과 다른 세상을 배우게 됩니다.

전자상거래 추천 시스템이라면 최소한 다음 다섯 종류의 데이터를 구조적으로 수집해야 합니다. 사용자 정보, 상품 정보, 노출 로그, 클릭 로그, 구매 로그입니다. 여기에 세션 정보나 장바구니, 찜, 검색어 같은 행동까지 붙으면 훨씬 좋아집니다.

아래는 추천 프로젝트에서 자주 쓰는 기본 스키마 예시입니다.

테이블핵심 컬럼의미
usersuser_id, signup_at, gender, age_group, region, membership_level사용자 기본 정보
itemsitem_id, category_id, brand_id, price, discount_rate, created_at, stock_status상품 메타데이터
impressionsimpression_id, user_id, item_id, page_type, position, request_id, exposed_at어떤 화면에서 어떤 순서로 노출됐는지
clicksclick_id, impression_id, user_id, item_id, clicked_at노출된 상품을 실제 클릭했는지
cartscart_id, user_id, item_id, added_at장바구니 담기 행동
purchasesorder_id, user_id, item_id, quantity, amount, purchased_at실제 구매와 매출
sessionssession_id, user_id, device_type, app_version, referrer, started_at현재 맥락 정보

겉으로는 단순한 표 같지만, 여기에는 추천 설계의 핵심이 숨어 있습니다. 먼저 user_id와 item_id가 모든 로그를 연결하는 공통 키가 되어야 합니다. 다음으로 각 이벤트에는 반드시 시간이 있어야 합니다. 추천은 순서가 중요한 문제이기 때문입니다. 어제 본 상품과 방금 본 상품의 의미는 다릅니다. 또 impressions 테이블에 page_type과 position이 있어야, 같은 클릭이라도 어디에서 어떤 자리에서 일어난 반응인지 구분할 수 있습니다. 첫 번째 슬롯은 원래 클릭을 많이 받기 때문에, 이를 모르면 모델이 자리 효과와 상품 효과를 헷갈리게 됩니다.

여기서 특히 자주 빠뜨리는 것은 request_id입니다. 추천 결과 한 묶음을 한 번의 요청으로 묶어 두는 식별자입니다. 이 값이 있으면 같은 추천 세트 안에서 어떤 아이템이 몇 위에 노출되었고, 그중 무엇이 클릭되었는지 추적할 수 있습니다. 추천 시스템을 디버깅할 때 이 정보는 거의 블랙박스를 열어 주는 열쇠처럼 작동합니다.

좋은 추천 데이터는 행동만이 아니라 맥락도 담고 있다

추천은 단순히 "이 사용자는 이 상품을 샀다"만으로는 충분하지 않습니다. 같은 사용자도 출근길에는 간단한 상품을 보고, 밤에는 오래 비교하며 고가 상품을 볼 수 있습니다. 맥락이 바뀌면 추천도 바뀌어야 합니다.

그래서 가능하다면 세션과 화면 문맥을 함께 저장하는 것이 좋습니다. 예를 들어 홈 화면인지, 검색 결과인지, 상세 페이지인지에 따라 사용자의 기대가 다릅니다. 모바일 앱인지 웹인지, 할인 행사 기간인지 아닌지, 유입 채널이 광고인지 자연 유입인지도 반응에 영향을 줍니다.

예를 들어 어떤 사용자가 운동화를 자주 산다고 해도, 선물 시즌에는 전혀 다른 카테고리를 볼 수 있습니다. 이때 과거 전체 구매 이력만 붙잡고 있으면 추천이 둔해집니다. 반대로 최근 세션에서 본 상품군, 현재 보고 있는 상품의 카테고리, 현재 시간대 같은 문맥을 함께 넣으면 추천이 훨씬 자연스러워집니다.

추천 시스템은 결국 사람의 취향만 읽는 것이 아니라, 취향이 어느 순간 어떤 맥락에서 행동으로 바뀌는지를 읽는 기술입니다.

가장 먼저 만들 것은 똑똑한 모델이 아니라 인기도 기반 추천이다

입문 프로젝트에서 가장 중요한 규칙 하나를 꼽자면 이것입니다. 추천 시스템의 첫 버전은 대개 인기도 기반 추천이어야 합니다. 왜냐하면 기준선이 없으면 개선도 없기 때문입니다.

인기도 기반 추천은 생각보다 강력합니다. 전체 인기 상품, 최근 7일 인기 상품, 카테고리별 인기 상품, 성별이나 지역별 인기 상품처럼 간단한 규칙만으로도 꽤 쓸 만한 결과가 나옵니다. 특히 신규 사용자에게는 이 방식이 매우 유용합니다. 아직 취향 데이터가 거의 없으니, 모두에게 무난하게 잘 팔리는 상품을 보여 주는 것이 오히려 가장 합리적일 수 있습니다.

예를 들어 홈 화면 첫 번째 추천 블록은 이렇게 만들 수 있습니다.

  • 최근 7일간 구매 수가 높은 상품

  • 재고가 충분하고 반품률이 낮은 상품

  • 특정 카테고리에 과도하게 치우치지 않도록 다양성 보정이 들어간 상품

이 방식의 장점은 분명합니다. 구현이 쉽고, 설명하기 쉽고, 운영이 안정적입니다. 무엇보다 추천 시스템의 최소 기능을 빠르게 배포할 수 있습니다. 많은 팀이 이 단계를 건너뛰고 바로 복잡한 모델로 뛰어들다가, 오히려 무엇이 좋아졌는지 설명하지 못하는 상황을 맞습니다.

인기도 기반 추천은 단순해서 초라한 출발처럼 보일 수 있습니다. 하지만 사실은 추천 시스템의 안전한 바닥입니다. 개인화 모델이 실패하더라도 서비스는 최소한 이 바닥으로 돌아올 수 있어야 합니다. 실전에서는 이 '안전한 기본값'이 매우 중요합니다.

인기도 기반 추천을 잘 만들면 이미 절반은 배운 셈이다

인기도 추천이라고 해서 무조건 전체 판매량 순으로만 나열하면 되는 것은 아닙니다. 이 단계에서도 이미 제품 감각이 필요합니다.

가장 먼저 생각해야 할 것은 시간 창입니다. 지난 2년 누적 판매량으로 인기 상품을 정하면, 과거의 히트 상품만 계속 남을 수 있습니다. 반대로 하루치 데이터만 쓰면 노이즈가 심해집니다. 그래서 최근 1일, 7일, 30일 같은 창을 섞어서 보는 경우가 많습니다.

다음으로는 품질 필터가 필요합니다. 클릭은 많지만 품절이 잦거나 반품률이 높은 상품을 추천하면 사용자는 실망합니다. 추천 시스템은 관심을 끄는 능력뿐 아니라 실망을 줄이는 능력도 있어야 합니다. 따라서 재고 상태, 반품률, 배송 지연 여부 같은 운영 데이터도 추천 대상 필터에 들어가야 합니다.

마지막으로 다양성을 생각해야 합니다. 같은 브랜드 운동화만 10개 보여 주면 클릭률은 잠깐 오를 수 있어도, 사용자는 곧 피로해집니다. 그래서 카테고리, 브랜드, 가격대가 너무 한쪽으로 몰리지 않도록 규칙을 넣는 경우가 많습니다. 추천은 정확도 경기이기도 하지만, 동시에 진열의 기술이기도 합니다.

이제 협업 필터링으로 한 단계 개인화를 시작한다

기준선이 준비되면 그다음은 협업 필터링으로 넘어갈 수 있습니다. 여기서 핵심은 "나와 비슷한 사람들이 본 것"이라는 직관을 실제 데이터 구조로 바꾸는 것입니다.

전자상거래에서는 별점보다 암묵적 행동이 훨씬 많습니다. 클릭, 장바구니, 구매, 찜, 재구매 같은 신호가 대표적입니다. 따라서 사용자-상품 행렬을 만들 때도 단순한 평점 대신 행동 강도를 반영한 점수를 구성하는 경우가 많습니다. 예를 들어 클릭은 1점, 장바구니는 3점, 구매는 5점처럼 가중치를 둘 수 있습니다. 물론 이 숫자가 정답은 아닙니다. 서비스 특성에 따라 조정해야 합니다. 중요한 것은 모든 행동을 똑같은 신호로 보지 않는다는 점입니다.

이 단계에서 가장 쉽게 시작할 수 있는 것은 아이템 기반 협업 필터링입니다. 사용자가 본 상품 A와 함께 자주 본 상품 B, 같이 구매된 상품 C를 연결하는 방식입니다. 이 방법은 사용자 기반 접근보다 운영이 안정적인 경우가 많습니다. 사용자는 계속 들어오고 나가지만, 상품 간 관계는 비교적 오래 유지되기 때문입니다.

예를 들어 러닝화를 본 사람들이 스포츠 양말을 자주 클릭하고, 특정 노트북을 산 사람들이 무선 마우스를 함께 구매한다면, 이 패턴은 꽤 직접적으로 추천에 쓸 수 있습니다. 상품 상세 페이지의 "이 상품을 본 고객이 함께 본 상품"이나 장바구니 옆의 "함께 구매하면 좋은 상품"은 이런 아이디어에서 출발하기 좋습니다.

협업 필터링은 데이터셋을 어떻게 만들지가 더 중요하다

초보자가 협업 필터링에서 자주 헷갈리는 부분은 '정답 데이터'를 어떻게 만들지입니다. 추천에서는 사용자가 좋아한 상품만 양성 예제로 보이고, 싫어한 상품은 명확하지 않은 경우가 많습니다. 클릭하지 않았다고 싫어한 것인지, 아예 못 본 것인지 알 수 없기 때문입니다.

그래서 추천 프로젝트에서는 음성 예제를 만들 때 특히 주의해야 합니다. 가장 안전한 출발은 '노출됐지만 클릭되지 않은 상품'을 약한 음성으로 보는 것입니다. 적어도 사용자가 볼 기회는 있었기 때문입니다. 반면 전혀 노출되지 않은 상품을 무작정 음성으로 넣으면, 모델이 현실과 다른 판단을 학습할 수 있습니다.

또 시간 기준 분할도 중요합니다. 추천은 미래를 맞히는 일이므로, 학습 데이터와 평가 데이터를 시간순으로 나누는 편이 자연스럽습니다. 예를 들어 1월부터 3월까지의 로그로 학습하고, 4월의 행동으로 평가하는 식입니다. 무작위 분할을 해 버리면 같은 사용자의 미래 행동 정보가 학습에 섞여 들어가 성능이 실제보다 좋아 보일 수 있습니다.

추천 시스템에서 데이터 누수는 생각보다 교묘합니다. 구매 후에 생긴 파생 정보가 학습 특성에 들어가기도 하고, 품절된 상품이 평가 시점에는 존재하지 않는데도 후보에 남아 있기도 합니다. 프로젝트를 진행할수록 "이 피처는 추천 시점에 정말 알 수 있었나?"를 습관처럼 묻는 것이 좋습니다.

후보 생성과 랭킹은 반드시 나눠서 생각해야 한다

추천 프로젝트가 본격적으로 실전 느낌을 내는 순간은 바로 여기입니다. 수십만 개 상품 전체를 매번 정교한 모델로 점수화하는 것은 너무 느리고 비쌉니다. 그래서 대부분의 서비스는 두 단계 구조를 씁니다. 후보 생성과 랭킹입니다.

후보 생성 단계는 말 그대로 보여 줄 만한 상품 후보를 빠르게 추리는 단계입니다. 여기서는 속도가 가장 중요합니다. 거칠어도 괜찮으니, 전체 상품 50만 개 중에서 500개 정도만 뽑아 오면 성공입니다. 인기도 추천, 최근 본 상품과 비슷한 상품, 함께 본 상품, 같은 카테고리의 인기 상품, 최근 세션 기반 추천 같은 여러 소스를 섞어 후보를 만듭니다.

랭킹 단계는 그 후보들 사이의 순서를 정하는 단계입니다. 여기서는 좀 더 비싼 계산을 써도 괜찮습니다. 어차피 500개만 다시 보면 되기 때문입니다. 사용자의 최근 행동, 선호 카테고리, 가격 민감도, 현재 페이지 맥락, 상품 속성, 할인 여부, 재고 상태 등을 함께 넣어 점수를 계산할 수 있습니다.

이 구조가 중요한 이유는 성능과 비용을 동시에 관리할 수 있기 때문입니다. 후보 생성이 너무 약하면 좋은 상품이 애초에 결승전에 못 올라옵니다. 반대로 후보는 좋아도 랭킹이 허술하면 화면 맨 위가 어색해집니다. 추천 시스템이 모델 하나가 아니라 흐름 전체라는 말이 바로 이 지점에서 실감납니다.

후보 생성 단계에서는 여러 소스를 섞는 편이 좋다

실전 추천 시스템에서 후보 생성은 한 가지 알고리즘만으로 해결되지 않는 경우가 많습니다. 오히려 여러 개의 단순한 소스를 조합하는 쪽이 더 강합니다.

예를 들어 상품 추천 프로젝트의 후보 생성은 이런 식으로 구성할 수 있습니다.

  • 전체 인기 상품 후보

  • 최근 급상승 상품 후보

  • 사용자가 최근 본 카테고리 기반 후보

  • 함께 조회된 상품 후보

  • 함께 구매된 상품 후보

  • 같은 브랜드나 유사 가격대의 콘텐츠 기반 후보

이 소스들을 섞으면 콜드 스타트와 데이터 부족 문제에도 더 잘 버팁니다. 신규 사용자는 인기 상품과 맥락 기반 후보가 버텨 주고, 오래된 사용자에게는 협업 신호가 더 강하게 작동합니다. 신규 상품은 콘텐츠 기반 후보를 통해 기회를 얻을 수 있습니다.

추천 시스템은 종종 거대한 단일 모델보다, 여러 개의 무난한 신호를 영리하게 합치는 쪽이 더 실용적입니다. 제품을 만들 때는 특히 그렇습니다. 단일 모델은 멋져 보이지만, 한 군데가 흔들리면 전체가 같이 흔들릴 수 있습니다.

랭킹 모델은 클릭만 볼지, 구매까지 볼지 먼저 정해야 한다

후보를 만든 뒤에는 순서를 매겨야 합니다. 이때 가장 먼저 정해야 할 것은 목표 신호입니다. 클릭 확률을 높이고 싶은지, 장바구니 담기를 높이고 싶은지, 구매 전환을 높이고 싶은지에 따라 모델이 배우는 방향이 달라집니다.

많은 팀이 처음에는 클릭 예측으로 시작합니다. 데이터가 많고 반응이 빠르기 때문입니다. 하지만 클릭만 최적화하면 제목이 자극적이거나 썸네일이 화려한 상품이 과하게 올라올 수 있습니다. 실제 구매나 만족으로는 이어지지 않는 추천이 늘어날 위험이 있습니다.

그래서 실전에서는 두 가지 방법이 자주 쓰입니다. 하나는 클릭 모델과 구매 모델을 따로 만들고, 두 점수를 섞는 방식입니다. 다른 하나는 구매 가능성이 높은 행동에 더 큰 가중치를 준 하나의 목적 함수를 만드는 방식입니다. 어떤 방법을 쓰든 중요한 것은 추천의 목적이 단기 반응인지, 매출인지, 장기 만족인지 명확해야 한다는 점입니다.

랭킹 모델에 들어갈 특성도 이런 목표에 맞춰 고릅니다. 사용자의 최근 클릭 수, 최근 구매 카테고리, 평균 구매 가격대, 마지막 방문 시각 같은 사용자 특성과, 상품의 가격, 할인율, 브랜드, 재고, 최근 인기 추세 같은 아이템 특성, 그리고 현재 페이지 유형, 슬롯 위치, 디바이스 종류 같은 문맥 특성을 함께 사용할 수 있습니다.

추천 시스템에서는 설명 가능한 단순 특성이 의외로 오래 살아남는다

입문자는 랭킹 모델이라고 하면 곧바로 깊은 신경망을 떠올리기 쉽습니다. 물론 큰 서비스에서는 복잡한 모델이 강력할 수 있습니다. 하지만 많은 전자상거래 프로젝트에서는 비교적 단순한 트리 기반 모델이나 선형 모델도 충분히 강합니다. 이유는 데이터의 구조가 명확하기 때문입니다.

예를 들어 "사용자가 최근 7일간 본 카테고리와 현재 상품의 카테고리가 일치하는가", "이 사용자의 평균 구매 가격대와 이 상품 가격이 얼마나 가까운가", "이 상품은 최근 일주일간 얼마나 많이 장바구니에 담겼는가" 같은 특성은 직관적이면서도 실제로 쓸모가 큽니다. 이런 특성은 운영팀과 대화할 때도 설명이 쉽습니다.

실전에서는 복잡한 모델 하나가 모든 문제를 해결해 주기보다, 이런 해석 가능한 특성들이 추천 품질을 꾸준히 떠받치는 경우가 많습니다. 특히 제품 초기에는 더욱 그렇습니다. 모델이 왜 그런 순서를 만들었는지 설명할 수 있어야 디버깅도 가능하고, 비즈니스 팀도 신뢰합니다.

오프라인 평가는 빠른 실험장이고, 온라인 평가는 현실 검증장이다

추천 프로젝트를 진행하다 보면 점점 성능표가 예뻐집니다. Recall@K도 오르고 NDCG도 좋아집니다. 그런데 막상 서비스에 넣으면 클릭률이 기대만큼 오르지 않거나, 오히려 구매 전환이 떨어지는 경우가 있습니다. 추천 시스템에서는 아주 흔한 일입니다.

오프라인 평가에서는 보통 과거 로그를 기준으로, 사용자가 실제로 반응한 상품을 상위 K개 안에 얼마나 잘 올렸는지를 봅니다. 이때 자주 쓰는 지표는 Recall@K, Precision@K, MAP, NDCG 같은 랭킹 지표입니다. 이름은 조금 딱딱하지만 직관은 단순합니다. 사용자가 좋아했던 상품을 추천 목록의 앞쪽에 잘 올렸는지를 보는 것입니다.

이 지표들은 모델 비교에 매우 유용합니다. 빠르게 실험할 수 있고, 명백히 나쁜 아이디어를 걸러내는 데 좋습니다. 다만 과거 로그에는 이미 이전 추천 시스템의 편향이 들어 있습니다. 사용자가 한 번도 보지 못한 상품을 좋아했을 가능성은 오프라인 로그만으로는 알기 어렵습니다. 그래서 오프라인 성능이 곧바로 온라인 성능을 보장하지는 않습니다.

온라인 평가에서는 실제 사용자에게 추천을 노출하고 반응을 측정합니다. 여기서는 클릭률, 장바구니 담기율, 구매 전환율, 객단가, 재방문율 같은 제품 지표가 중요해집니다. A/B 테스트가 대표적인 방식입니다. 실제 환경에서 강하지만, 비용이 들고 실수하면 사용자 경험을 해칠 수 있습니다.

결국 추천 시스템은 오프라인에서 빠르게 배우고, 온라인에서 겸손하게 검증하는 흐름으로 가야 합니다.

오프라인 지표가 좋아도 실제 클릭률이 안 오르는 이유

이 부분은 추천 프로젝트에서 꼭 한 번은 겪어 봐야 감이 잡힙니다. 오프라인에서 모델이 더 좋아졌는데 실제 클릭률이 오르지 않는 이유는 여러 가지입니다.

첫째, 오프라인 데이터가 과거 노출 편향을 품고 있기 때문입니다. 과거 시스템이 자주 보여 준 상품은 로그가 풍부하고, 안 보여 준 상품은 데이터가 거의 없습니다. 그러면 새 모델이 사실은 같은 인기 상품을 더 잘 맞힌 것처럼 보일 수 있습니다.

둘째, 오프라인 지표와 온라인 목표가 다를 수 있습니다. 예를 들어 클릭을 잘 맞히는 모델이 구매를 잘 만든다는 보장은 없습니다. 클릭은 가볍고 빠른 행동이지만, 구매는 가격과 재고, 배송, 심리적 망설임까지 얽힌 더 무거운 행동입니다.

셋째, 실제 화면에서는 위치 효과가 큽니다. 같은 상품도 1번 슬롯에 있느냐 8번 슬롯에 있느냐에 따라 클릭 확률이 크게 달라집니다. 오프라인 평가가 이 차이를 충분히 반영하지 못하면, 온라인 결과와 어긋날 수 있습니다.

넷째, 너무 비슷한 상품만 올리면 단기 클릭은 나와도 장기 만족이 떨어질 수 있습니다. 사용자는 처음에는 익숙한 상품에 반응하지만, 계속 같은 것만 보이면 탐색 재미가 사라집니다. 추천 시스템이 사용자를 지루하게 만들기 시작하는 순간입니다.

이 차이를 이해하는 것이 중요합니다. 추천은 시험지 채점처럼 한 번에 맞고 틀리고가 끝나는 문제가 아닙니다. 시스템이 무엇을 더 자주 보여 주기 시작하면, 그다음 데이터 자체가 바뀝니다. 추천은 현실을 관찰하는 동시에 현실을 다시 만들어 냅니다.

장기 만족도는 클릭보다 늦게 보이지만 훨씬 중요하다

좋은 추천 시스템은 종종 클릭률보다 더 긴 시간을 봅니다. 전자상거래라면 재구매율, 반품률, 리뷰 만족도, 브랜드 신뢰, 재방문 같은 신호가 여기에 해당합니다. 클릭은 입구지만, 만족은 관계입니다.

예를 들어 클릭률이 높은 추천이 있다고 합시다. 그런데 그 추천으로 들어온 상품들의 반품률이 높고, 구매 후 리뷰가 나쁘다면 어떨까요. 이 추천은 겉으로는 활발하지만 실제로는 고객을 피곤하게 만드는 추천일 수 있습니다. 반대로 클릭률은 조금 덜해도, 장바구니 담기와 구매 전환, 재방문이 꾸준히 좋아지는 추천은 훨씬 건강한 시스템일 가능성이 큽니다.

그래서 실전에서는 단일 지표만 보지 않고, 짧은 지표와 긴 지표를 함께 둡니다. 예를 들어 1차 지표는 CTR, 2차 지표는 CVR, 보호 지표는 반품률과 숨김 비율처럼 둘 수 있습니다. 어떤 추천이 단기 반응은 좋지만 장기 만족을 해치고 있는지 이런 구조로 감지할 수 있습니다.

추천 시스템은 사람을 한 번 움직이게 만드는 기술이 아니라, 계속 다시 오고 싶게 만드는 기술이어야 합니다.

콜드 스타트는 설계로 버텨야 한다

상품 추천 프로젝트를 실제로 돌리면 가장 먼저 부딪히는 현실 중 하나가 콜드 스타트입니다. 새 사용자는 아직 행동 이력이 없고, 새 상품은 아직 노출과 구매 이력이 없습니다. 협업 필터링만 믿고 있으면 이 순간 시스템이 갑자기 멍해집니다.

새 사용자에게는 인기 상품, 온보딩에서 고른 관심 카테고리, 유입 채널, 지역, 현재 세션 행동 같은 초기 신호를 활용해야 합니다. 예를 들어 첫 세션에서 사용자가 캠핑 용품을 두 번 연속 봤다면, 아직 구매 이력이 없어도 취향의 방향은 어느 정도 읽을 수 있습니다.

새 상품에게는 상품 메타데이터가 중요합니다. 카테고리, 브랜드, 가격대, 설명 텍스트, 이미지 임베딩 같은 속성을 이용해 기존 상품과 비슷한 후보군에 들어가게 해야 합니다. 추천 시스템은 행동 데이터만으로 강해지는 것이 아니라, 상품 카탈로그가 얼마나 잘 정리되어 있는지에 따라 실력 차이가 크게 납니다.

콜드 스타트는 피할 수 없는 문제가 아닙니다. 오히려 시스템이 얼마나 다양한 신호를 준비해 두었는지 보여 주는 시험대에 가깝습니다.

추천 결과를 운영하려면 모델보다 규칙이 더 필요할 때가 많다

노트북에서 추천 점수를 잘 뽑는 것과 실제 서비스를 운영하는 것은 다른 문제입니다. 현실에서는 추천하면 안 되는 상품도 있습니다. 품절 상품, 판매 중지 상품, 특정 연령에 부적절한 상품, 지나치게 낮은 평점의 상품, 배송 불가 지역 상품 등이 대표적입니다.

그래서 추천 시스템의 최종 출력 직전에는 보통 비즈니스 규칙 레이어가 하나 더 있습니다. 모델이 점수를 잘 매겨도, 이 레이어에서 실제 노출 가능한 상품만 남깁니다. 또 브랜드 편중을 완화하거나, 같은 상품이 지나치게 반복 노출되지 않게 하거나, 시즌 프로모션 상품에 제한적으로 가중치를 주는 작업도 이 단계에서 이뤄집니다.

이것을 두고 '모델이 충분히 똑똑하지 않아서 규칙을 넣는다'고 생각하면 아쉽습니다. 실제로는 반대인 경우가 많습니다. 추천은 모델과 운영 규칙이 협업하는 시스템입니다. 모델은 취향을 예측하고, 규칙은 서비스 품질을 지킵니다. 둘 중 하나만으로는 오래 버티기 어렵습니다.

이 프로젝트를 실제로 진행한다면 이렇게 만든다

상품 추천 프로젝트를 처음 맡았다면, 다음과 같은 순서로 진행하는 것이 현실적입니다.

첫째 주에는 추천 위치와 목표를 정의합니다. 홈 화면인지, 상세 페이지인지, 장바구니인지 정하고, 클릭·장바구니·구매 중 무엇을 1차 성공으로 볼지 정합니다. 동시에 로그 스키마를 점검합니다. 특히 노출 로그가 제대로 남는지 확인해야 합니다.

둘째 주에는 인기도 기반 추천을 만듭니다. 최근 인기, 카테고리별 인기, 신규 사용자용 인기 추천을 구현하고, 품절과 반품률 같은 필터를 붙입니다. 이 단계에서 이미 서비스에 붙일 수 있는 첫 버전이 나옵니다.

셋째 주에는 아이템 기반 협업 필터링을 붙입니다. 함께 본 상품, 함께 구매한 상품, 최근 세션과 연결되는 상품을 중심으로 상세 페이지 추천을 강화합니다. 이 시점부터 개인화의 느낌이 살아납니다.

넷째 주에는 후보 생성과 랭킹 구조를 분리합니다. 여러 후보 소스에서 상품을 모은 뒤, 사용자 특성·상품 특성·문맥 특성으로 랭킹 모델을 학습합니다. 오프라인 랭킹 지표를 보며 후보 품질과 순위 품질을 동시에 확인합니다.

다섯째 주에는 온라인 실험을 합니다. CTR만 보지 말고 장바구니 담기율, 구매 전환율, 반품률, 재방문율을 함께 봅니다. 여기서 결과가 애매하면 모델보다 먼저 로그 품질과 추천 위치, 슬롯 수를 다시 의심해 보는 것이 좋습니다.

이 흐름의 장점은 매 단계마다 서비스 가치가 생긴다는 점입니다. 추천 프로젝트는 마지막에 완성되는 거대한 탑이 아니라, 작은 블록을 차례로 쌓아 가는 과정에 더 가깝습니다.

초보 팀이 추천 프로젝트에서 자주 하는 실수

상품 추천은 화려해 보여서 오히려 기본을 놓치기 쉽습니다. 초보 팀이 특히 자주 하는 실수는 몇 가지 패턴으로 반복됩니다.

첫 번째는 노출 로그 없이 클릭 로그만 모으는 것입니다. 이러면 사용자가 무엇을 싫어했는지 이전에, 무엇을 볼 기회가 있었는지도 알 수 없습니다. 두 번째는 인기도 기준선 없이 곧바로 복잡한 모델로 가는 것입니다. 그러면 좋아진 이유를 설명하지 못합니다. 세 번째는 후보 생성과 랭킹을 한 번에 해결하려는 것입니다. 이러면 느리고 비싸고 디버깅도 어렵습니다. 네 번째는 클릭률 하나만 보고 성공했다고 판단하는 것입니다. 추천은 장기 만족과 전환까지 이어져야 진짜 가치가 생깁니다.

또 하나 자주 보이는 실수는 추천을 너무 순수한 알고리즘 문제로 보는 것입니다. 실제 전자상거래에서는 재고, 가격, 반품, 시즌성, 마케팅 일정이 모두 추천 품질에 영향을 줍니다. 추천 엔지니어가 숫자만 잘 본다고 해결되지 않는 이유가 바로 여기에 있습니다. 추천 시스템은 데이터 과학과 제품 운영이 만나는 가장 현실적인 분야 중 하나입니다.

이 프로젝트의 핵심은 알고리즘보다 흐름이다

이 장에서 만든 상품 추천 시스템을 다시 한 번 정리해 봅시다. 먼저 어떤 화면에서 어떤 목적의 추천을 할지 정했습니다. 다음으로 사용자, 상품, 노출, 클릭, 구매 로그를 연결할 수 있는 스키마를 설계했습니다. 그 위에 가장 단순하지만 강력한 인기도 기반 추천을 기준선으로 만들고, 협업 필터링으로 개인화를 확장했습니다. 그리고 후보 생성과 랭킹을 분리해 성능과 비용을 동시에 관리하는 구조를 세웠습니다.

평가에서는 오프라인 지표로 빠르게 실험하고, 온라인에서는 클릭률뿐 아니라 장바구니, 구매, 재방문, 장기 만족까지 함께 봐야 한다는 점도 확인했습니다. 이 과정 전체를 지나고 나면, 추천은 더 이상 "좋아할 상품 맞히기" 같은 단순한 문제로 보이지 않습니다. 추천은 데이터 수집, 후보 탐색, 순위 결정, 운영 규칙, 제품 지표 해석이 한 몸처럼 움직이는 시스템 설계 문제로 보이기 시작합니다.

이 감각이 중요합니다. 추천 시스템의 진짜 실력은 특정 알고리즘 이름에서 나오지 않습니다. 어떤 로그를 남겨야 하는지, 언제는 인기 상품으로 버티고 언제는 개인화를 강화해야 하는지, 어디서 비용을 아끼고 어디서 정교함을 써야 하는지 판단하는 데서 나옵니다. 상품 추천 프로젝트는 바로 그 판단력을 훈련하는 최고의 연습장입니다.

좋은 추천은 사용자의 마음을 완벽히 읽는 시스템이 아닙니다. 지금 이 순간, 너무 많은 선택지 앞에서 조금 더 쉽고, 조금 더 만족스러운 다음 선택을 도와주는 시스템입니다. 그리고 그 시스템은 모델 하나가 아니라, 제품 전체의 흐름으로 만들어집니다.

책 목록

머신러닝 설계 수업: 데이터를 모델로, 모델을 제품으로 바꾸는 실전 감각

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기