데이터로 Deep Dive

데이터 분석과 개발 경험을 공유합니다.

프로젝트 꾸러미

요식업 매출 베이스로 제주 맛집 추천 웹앱 만들기(feat. Streamlit)

Marlangcow 2025. 3. 17. 18:31

작년 말 즈음에 

빅콘테스트 주최로 '제주 맛집'을 추천하는 'LM활용 제주도 맛집 추천 대화형 AI서비스 개발'에 참여한 적이 있다. 

 

이때, 첫 공모전이기도 하고

LLM에 막 발을 담가봤던 시기이기도 해서

굉장히 재미있지만서도 어려워서 밤을 새어 가며

내 친구 Cursor와 함께 뚝딱뚝딱 만들어보았던 시기가 있었다. 

 

이때, 다른 친구 한 명과 같이 참여했는데, 

다행스럽게도 둘 다 LLM이란 기술에 매료되어서 고군분투하며 어떻게든 Streamlit까지 만들고, 영상도 찍었었다. 

 

결론적으론, 

입상은 하지 못했다. 

 

아이디어는 좋았으나, 

우리의 기술력 한계로 인해 영상도, 제출 코드도 엉망인 채로 제출해 버렸다. 

왜냐하면.. 우린 LLM구현이 잘 된 줄 알았으나 

알고 봤더니 LLM 이 자체적으로 답변을 생성하고 있었다. 

우리가 의도한 FAISS DB에서의 서치를 전혀 못하고 있었는데 

우린 그 사실을 제출 전날 알게 되었고, 다음날 코드를 뒤엎다가

결국... 각자의 한계와 시간적 한계를 처절히 느끼고선 마음을 접고 

진짜로 생성형 AI, Gemini가 자유롭게 생성하는 그대로의 결과물을 제출했다. 

 

이후, 다시 도전해 봐야지 하고 기억 저편에 잠시 미뤄놨다가 

드디어.. 다시 꺼내어 왔다. 

대신, 이번에는 

 

그때보다 전반적인 스코프를 확 줄였다. 

 

프로젝트 배경

크게는 웹사이트 조회수와 리뷰 평점, 그리고 요식업 매출 데이터가 주어졌으나 

이번엔 EDA에 초점을 맞춰서 

'요식업 가맹점 데이터'만 사용했다. 

 

프로젝트 목표

그리고 세운 프로젝트 목표는 '제주 관광 수요를 예측하여 맞춤형 추천 맛집을 제공하는 머신러닝 기반 프로토타입 서비스 개발'이다. 

 

프로젝트 목표를 왜 이렇게 세웠냐 하면, 

아래와 같은 문제점들은 실제로 '제주' 지역에서 겪는 문제점이었고, 

여러 상황과 맞물려 관광객 수요 예측이 중요하단걸 발견했기 때문이다. 

  • 제주 관광객 감소 및 소비 패턴 변화 → 경기 침체·고물가로 관광객 감소, 맛집·로컬 경험 중심 소비 증가
  • 관광 수요 분산 및 맞춤형 추천 필요 → 특정 지역·업종 쏠림 완화, 데이터 기반 맞춤 추천으로 관광 편의성 증대

이러한 문제점과 목표에 따라 기대하는 효과는 User와 Business로 나눠서 생각해 보았다. 

기대 효과

  • User end
    • 개인화된 맞춤 관광지 및 맛집 추천: 사용자 선호도(방문 지역, 업종, 방문 시간, 요일 등)를 반영한 맞춤형 추천 시스템 제공
    • 유사도 기반 관광지 및 맛집 추천: TF-IDF 및 Cosine Similarity 알고리즘을 활용하여 유사한 관광지 및 맛집 추
  • Business end
    • 관광 사업 활성화를 위한 데이터 기반 정책 수립: 관광객 유입이 많은 지역과 저조한 지역을 분석하여 관광산업 균형 발전 도모
    • 지역 특성별 맞춤형 관광 상품 개발: 비인기 지역의 특성을 반영한 신규 관광 콘텐츠 개발 (예: 로컬 푸드 투어, 한적한 여행지 추천)
    • 관광 수요 과밀화 방지를 통한 지속 가능한 환경 보호 정책 지원: 환경 보호 및 지역 균형 발전을 위한 데이터 기반 관광 정책 마련 가능

이렇게 프로젝트의 개괄을 잡았다. 

 

이제 본격적으로 분석할 준비를 시작해 보자. 

 

개념 설계

  • 카드사 요식업 가맹점 데이터 EDA, Feature Engineering
  • 제주 관광 수요를 예측하는 분류모델 (Random Forest, LightGBM) 및 hyperparameter tuning
  • 애플리케이션 개발 및 ML모델 배포(Streamlit / Github)

모델 파이프라인

모델 파이프라인은 다음과 같으며, 

Random Forest로 수요예측을 했고, 

TF-IDF, Cosine Similarity로 추천 시스템을 개발했다. 

 

그리고 이를 다 엮어서 Streamlit으로 배포하여 간단하게 

여러 조건에 따른 맛집을 확인해 볼 수 있도록 해보았다. 

 

데이터는 S카드사의 제주 가맹점 중 요식업 월별 매출 상위 30% 가맹점 데이터를 사용했다.

데이터셋 N
제주도 요식업 가맹점 매출 상위 30%의 ‘매출 데이터 67,864

 

그리고 모델링을 위해 다양한 파생변수도 사용했는데, 그중

요식업 데이터에서 ’ 현지인 이용 비중’ 칼럼을 이용해 ’ 관광객 이용 비중 = 1 - 현지인 이용 비중’ 파생변수를 생성하여 결과 변수로 활용했다.

또, 

모델 성능 및 메모리 효율성을 위해 raw 데이터에서 주요 칼럼만 추출하여 테이블 생성하여 최종표본 추출은 n=67,864이다. 

 

데이터 정제 및 전처리(Cleansing & Preprocessing)

결측치는 '주소' 부분에서만 발생해서 약 1.9% 정도로 발견돼서 이건 대체하기보단 실제 '지역 정보'를 확인하여 실제 값으로 대체했다. 

그런 후에 '시' 단위로 필터링하기 위해 '제주시'와 '서귀포시'로 구분했다. 

요식업은 업종(eg. 가정식, 기사식당, 구내식당 등)이 다양해서 One-hot encodinng으로 범주화했고, 

월별 데이터를 3개월씩 구분하여 '봄/여름/가을/겨울'로 Label encoding을 진행했다. 

 

그리고 핵심 Feature Engineeriing으로는

featuure 칼럼에 '업종, 지역, 주소, 계절 정보'를 결합하여 가게별 특징을 벡터화했다.

'방문 패턴 분석'을 위해서 요일별/시간대별 이용 비중을 기반으로 선호도를 도출했고, 주중/주말 선호도(WEEKEND_PREFERENCE)를 계산했다.

고객 특성 분석을 위해 '연령대, 성별'에 따른 분석을 진행했으며, 관광객과 현지인간 비교를 위해 각각의 이용 비율을 생성했다.

마지막으로 각 업장의 인기도 점수 계산을 위해 '이용 빈도(40%) + 결제 금액(20%) + 관광객 비율(20%) + 영업 기간(20%)'으로 가중치를 주어 변수를 만들었는데, 계절에서는 해당 계절이면 1.2배의 가중치를 더 두었다. 

 

탐색적 데이터 분석(EDA) 핵심 인사이트

이번에 EDA를 진행하면서 

정말 하나하나 다 뜯어보고, 다방면으로 익히는 시간이 되었다. 

그리고 실제로 상관관계가 있어 보이는 부분에서는 실제로는 크게 관계가 없는 부분이 확인되는 것도 신기했고, 

EDA 하기 전의 단순했던 생각이 이걸 통해 데이터에 대한 더 심도 있는 이해가 가능해졌다. 

 

그리고 한편으론, 이래서 '도메인'이 중요하다고 하는구나 싶었는데 

관련 '도메인'에 대한 지식이 어느 정도 있으면 변수나 가설을 보다 더 효과적으로 설계할 수 있겠다는 생각이 들었다. 

 

그래서 분석한 내용은 다음과 같다. 

모델링

모델링은 '관광 수요 예측'이다 보니 'RandomForest, GradientBoosting, LinearRegression, Ridge, Lasso'를 함께 돌려보았다.

 

 


RMSE 성능 평가
RandomForest 0.12 0.83 가장 좋음
GradientBoosting 0.19 0.60 보통
LinearRegression 0.22 0.44 보통 이하
Ridge 0.22 0.44 보통 이하
Lasso 0.30 -0.00 매우 낮음

 

이후

Feature Importance 상위 20개 추출하여 모델링 진행했는데, 

기존  RMSE: 0.1233, R²: 0.8300 -> 상위 20개 특성 모델링 RMSE: 0.1226, R²: 0.8319으로 엄청 소폭 향상되었다. 

 

성능을 더 올리수 없을까 싶어서 
하이퍼파라미터 튜닝(RandomizedSearchCV)도 진행했으나 RMSE: 0.2254로 성능이 더 낮아지는 결과가 나왔다. 

 

이에, 기존 모델이 이미 ‘분석 목적(관광객 예측 정확성)’에 부합하는 성능을 달성했으므로 기존 모델을 유지하기로 했다. 

 

다음은 Streamli에서 고객 맞춤형 맛집을 추천하기 위해 

추천 시스템을 개발해 보았다. 

 

추천 시스템

추천 시스템을 Streamilt에 올리기 위해선 먼저 앞에서 EDA 했던 데이터를

서버에 올려야 했는데, 

여러 방법을 찾아보다가 Google Drive에 올려서 불러오는 방법으로 진행했더니 아주 손쉽게 불러와졌다. 

그리고 Streamlit loading 속도에도 크게 영향을 미치지 않았다..!

# Streamlit Secret에 저장한 후, 아래처럼 불러올 수 있다. 
file_url = st.secrets["google_drive"]["csv_url"]

 

이후 구현한 추천 시스템은, 

맞춤형 추천, 인기 맛집 추천, 콘텐츠 기반 유사 관광지 추천으로 나니는데 

 

'맞춤형'과 '인기 맛집'은 '필터링'과 '인기도 기반'으로 이미 계산된 결과에 따라 추천을 해주는 방법이고, 

 

'콘텐츠 기반 유사 관광지 추천'은 TF-IDF와 코사인 유사도를 바탕으로

유저가 입력한 '키워드'에 따라 가게들의 유사도와 비교 분석하여 추천하는 방법이다. 

 

필터에는 맛집 검색에서 유용하게 이용될 내용들을 모두 필터링화 했는데, 

'사용자의 다중 기준 선호도(지역, 업종, 방문 요일, 방문 시간대, 계절, 주중/주말, 성별, 연령대)'과 '지역, 업종, 계절'에 따라 필터링된다. 필터링된 데이터는 '인기도 점수'를 기준으로 정렬하여 상위의 맛집들을 추천하는 시스템이다.

필터링 + 인기도 기반 추천 시스템

콘텐츠 기반 유사 관광지 추천에는 TF-IDF와 코사인 유사도를 사용했는데, 

먼저 'TfidfVectorizer'를 사용하여 관광지 특성을 벡터화한 다음, 

'cosine_similarity'로 맛집 간 유사도를 계산했다. 

 

작동 방식은 

먼저 각 가게의 'features' 칼럼을 5000차원의 벡터로 변환한 다음 각 단어의 중요도를 계산한다. 

그리고 사용자가 입력한 키워드에 대해 키워드 매칭을 하는데, 결과가 충분하지 않을 경우, TF-IDF 벡터 기반 유사도를 검색하는데 KNN으로 코사인 유사도가 가장 높은 가게를 서치 한다. 

참고로, 중복된 가게가 여럿 나오지 않도록 검색된 상위 1개의 가게만 보여주도록 했다. 

 

위와 같이

인터랙티브 필터링을 통해 사용자 맞춤 장소를 추천하고, 추천 결과를 카드 형식으로 시각화하여 직관적인 UI 제공했다. 그리고 관광지 및 가맹점별 방문 패턴 분석을 통한 인사이트 제공할 수 있도록 했다. 

 

아래는 배포한 최종 Stremalit 모델이다. 

제주도 맛집 추천 Streamilt

결론

결론을 내보자면,

비즈니스 전략을 위해 데이터 기반의 접근을 시도해 보았다는 의미가 있는데, 
탐색적 데이터 분석, 머신러닝 알고리즘을 활용해 관광 수요를 예측하여 이러한 수요에 대응할 수 있는 정보를 제공하고자 했다.ㅇ

그리고
비즈니스 관점에서 여러 인사이트 도출해 볼 수 있는데, 
최적의 타겟팅으로 고효율 마케팅 전략 도출도 가능하고, 이를 발판 삼아 관광 활성화 위한 공공 정책 제안도 할 수 있을 뿐 아니라 
수요 예측을 통한 관광지 보존 정책 수립도 가능할 것으로 기대한다. 

물론, 위에서 꽤나 고도화가 되어야겠지만

결론적으로는 '관광 수요 예측'이 여러 비즈니스 관점에서 도움이 된다는 것이다. 

 

회고

앞에서도 약간의 회고를 하였으나

이 포스팅의 제일 마지막 부분이니만큼 조금 더 이야기하자면

주어진 데이터 외에도 '비짓제주'라는 제주관광공사 사이트의 여러 관광지에 대한 조회수 데이터도 함께 분석했었다. 

특이하게 조회수는 주말보다 '주중' 비중이 훨씬 높았으며, 

맛집보다는 '관광지', 예를 들어 성산일출봉, 한라산 등의 비중이 압도적이었다.

 

그리고 리뷰 평점 데이터는 대부분 '숙소'와 관련 있었는데, 

리뷰가 많은 숙소는 평점이 높은 리뷰도, 낮은 리뷰도 많았으며 

대부분의 핵심 키워드는 리뷰마다 공통적인 부분들이 많았다. 

 

이를 통해 개선점도 도출해 보았는데, 

위의 프로젝트 포폴에는 포함하지 않았지만 인사이트를 계속 발견해 나가는 재미가 꽤 쏠쏠했다. 

그리고

금전적으로 여유가 더 있었다면

LLM도 다시 한번 시도해보고 싶은 (살짝쿵) 바람도 있다. 

(*공모전 당시에는 Gemini가 무료였다)

 

 

아, 그리고 Streamlit은 장기간 접속이 없으면 백업되어 창이 뜨지 않을 수 있다. 

그리고 아무래도 가볍게 만들어본 작업이다보니, 중간 중간 필터에 오류가 있을 수 있다. 

이 부분 참고 부탁드린다. 🥲

< 프로젝트 관련 링크 >
- 프로젝트 관련 Github
- 제주 맛집 추천 Streamlit