01 / 05 · PRODUCT ENGINEERING
295개 메뉴 데이터에서 설명 가능한 추천까지
‘따뜻하고 든든한 한식’을 고르면 어떤 메뉴가 나와야 할까요. 점심먹개는 295개 메뉴의 속성을 입력 조건과 비교해 점수를 매깁니다. 매번 같은 1등만 나오지 않도록 상위 후보 안에서 결과를 고르고, 카드에는 어떤 조건이 맞았는지 한 줄로 덧붙입니다.
- 메뉴 데이터
- 295개
- 비교 기준
- 1~5 정도값 7종·분류값 4종
- 점수 비중
- 선택형 55·게이지 45
- 결과 구성
- 대표 1개·주요 4개·보강 2개
DATA MODEL
메뉴 이름 목록을 비교 가능한 데이터로 바꿨습니다
처음의 메뉴 이름 목록은 사람이 훑어보기에는 충분했지만 ‘따뜻하고 든든한 한식’처럼 여러 조건을 함께 적용할 수 없었습니다. 김치찌개와 샌드위치는 이름과 조리법이 다르더라도 추천 과정에서는 같은 질문에 답할 수 있어야 했습니다.
그래서 매운맛, 든든함, 국물, 따뜻함처럼 연속적으로 느껴지는 특성은 1~5 정도값으로, 음식 스타일·주재료·형태·조리법은 문자열 분류값으로 나눴습니다. 이 값은 영양 성분이나 객관적인 음식 등급이 아니라 일반적인 점심 1인분을 메뉴끼리 비교하기 위한 서비스 내부 기준입니다.
숫자를 더 세밀하게 만들면 정확해 보이지만 식당과 조리법에 따른 차이를 감출 수 있고 운영자가 일관되게 검수하기도 어려워집니다. 사용자가 실제로 선택할 수 있는 필터의 세밀함과 사람이 반복 검토할 수 있는 범위 사이에서 현재 척도를 정했습니다.
FIELD EVIDENCE
데이터 비교부터 추천 이유까지 이어지는 흐름
현재 일반 추천은 활성 조건만 비교하고 점수를 정규화한 뒤 3·9·20 후보 정책으로 결과를 구성합니다. 이유 문구도 같은 메뉴 속성과 사용자 입력에서 만듭니다.
SCORING DECISION
완전한 무작위와 고정된 1등을 모두 피했습니다
완전한 무작위 선택은 빠르지만 사용자가 고른 조건을 반영하지 못합니다. 반대로 점수가 가장 높은 메뉴 하나만 반환하면 같은 조건에서 결과가 고정되고, 근소한 점수 차이를 절대적인 품질 차이처럼 다루게 됩니다.
일반 추천은 사용자가 활성화한 조건만 계산합니다. 선택형 필터와 게이지 필터를 각각 55와 45의 기본 비중으로 정규화하고, 사용자가 중요하다고 표시한 조건에는 1.7배를 적용합니다. 선택하지 않은 항목은 서비스가 임의로 취향을 추측하지 않도록 계산에서 제외합니다.
예를 들어 매운맛 3을 ‘중요’, 음식 스타일을 ‘한식’으로 고르면 가능한 점수는 9×1.7과 18을 더한 33.3점입니다. 매운맛 3이고 한식인 김치찌개는 33.3점을 모두 얻어 100점이 됩니다. 매운맛이 한 단계 높은 제육볶음은 매운맛 항목에서 75%인 11.475점을 받고 한식 18점을 더해 약 88.51점이 됩니다. 이 계산은 두 메뉴의 맛을 평가하는 점수가 아니라 현재 입력과 속성값 사이의 거리를 비교한 결과입니다.
이 방식은 개인을 학습하는 AI 모델보다 단순하지만 입력과 결과의 관계를 추적할 수 있습니다. 값이 어색한 메뉴가 발견되면 추천 코드를 임시로 바꾸는 대신 원본 메뉴 속성과 판정 기준까지 되돌아가 확인할 수 있다는 점을 우선했습니다.
점수 순서는 지키되 후보 안에서 다양성을 남겼습니다
대표 메뉴는 상위 3개 풀에서 하나를 고르고, 주요 후보는 대표를 제외한 상위 9개에서 4개, 보강 후보는 상위 20개 중 11~20위 구간에서 2개를 선택합니다. 점수가 다른 메뉴의 순서를 무작정 섞지 않고 같은 점수 그룹만 먼저 섞습니다.
대표만 보면 현재 조건과 가까운 선택을 얻고, 주요 후보에서는 비슷한 대안을 비교할 수 있습니다. 보강 후보는 최고 점수에만 갇히지 않도록 조금 더 넓은 선택지를 제공합니다. 결과는 최대 일곱 개지만 화면에서는 대표와 후보의 시각적 위계를 나눠 한꺼번에 같은 무게로 읽히지 않게 했습니다.
이 후보 수가 모든 서비스에 맞는 정답은 아닙니다. 현재 메뉴 규모와 모바일 결과 화면을 함께 검토해 정한 운영 정책이며, 메뉴 수나 화면 구조가 바뀌면 다시 확인해야 하는 값으로 관리합니다.
추천 이유는 계산 결과를 짧게 번역합니다
메뉴 이름만 표시하면 사용자는 자신의 선택이 반영됐는지 알기 어렵고, 계산에 사용된 모든 값을 나열하면 점심을 고르는 화면이 설명서처럼 복잡해집니다. 점심먹개는 사용자가 중요하게 표시한 조건과 메뉴를 구분하는 데 도움이 되는 일치를 우선해 최대 두 항목만 한 줄로 보여줍니다.
내부 속성 이름을 그대로 노출하지 않고 ‘따뜻하게 먹기 좋아요’처럼 선택 상황에서 이해되는 문구로 바꿉니다. 점수와 설명은 같은 원본 메뉴 데이터를 사용하므로 메뉴 속성을 수정하면 추천 결과뿐 아니라 이유도 함께 달라집니다.
‘따뜻하게 먹기 좋아요’라는 이유를 보고도 차가운 메뉴가 당긴다면 따뜻함 조건을 바꿔 다시 고를 수 있습니다. 짧은 이유는 다음 추천에서 손댈 조건을 찾는 단서가 됩니다.
VERIFICATION
구현 수치와 화면을 함께 검증했습니다
메뉴 수와 속성 정의는 메뉴 원본과 데이터 작업 절차에서, 점수 비중과 후보 정책은 추천 코드와 알고리즘 문서에서 대조했습니다. 추천 이유의 우선순위와 최대 표시 개수는 실제 구현 및 390×844 운영 화면에서 확인했습니다.
여기서 확인한 것은 데이터와 계산, 카드 표시가 맞물리는 범위입니다. 실제로 먹고 싶었던 메뉴가 나왔는지는 별도의 사용자 조사가 필요합니다. 메뉴 속성이나 후보 정책이 달라지면 이 글의 계산 예도 다시 확인해야 합니다.
- 메뉴 값은 객관적 영양 평가가 아닌 내부 비교 기준으로 설명하기
- 활성 조건만 계산하고 중요 조건의 비중을 명시적으로 구분하기
- 점수 차이와 결과 다양성을 후보군 단계에서 분리하기
- 추천 이유와 점수가 같은 원본 데이터를 바라보게 하기
추천을 설명으로 남긴 이유
김치찌개의 100점과 제육볶음의 88.51점은 맛의 우열이 아니라 입력 조건과의 차이입니다. 이 구분이 흐려지면 점수와 추천 이유도 오해를 낳습니다. 속성값을 고칠 때 계산 결과와 카드 문구를 함께 확인하는 이유입니다.