중간 발표를 준비하며 구조화한 기능명세서를 바탕으로
우리는 스타트학기 기말 심층인터뷰 준비를 위해
대표적 기능 구분별로 데모 코드를 작성했다.
1번 "회원가입/로그인"과 4번 로컬 특산물 등록 및 구매/판매"에 대한 코드는
금방 작성했으며 실행되는 것까지 확인했다.
(물론 실제로 통합하여 앱에 반영될라면 추가로 손보긴 해야한다)
근데 문제는..
2번 "사용자 맞춤 여행지 추천"과 3번 "지역 기반 축제 정보 제공"이였다.
이 파트에서 '관광정보API'의 활용이 요구되는데
api 연동 문제 해결에만 일주일 넘게 소요되었다......
그.런.데.
기적적으로!!
지도교수님과 대면 면담을 하기로 한 날
면담 시작 30분? 전에 해결 방법을 찾아 연동에 성공하였다,,,,ㅠㅠ
작업한 데모코드를 살펴보자 →
🔗우리팀 깃허브 레포
https://github.com/CAPSTONEEEEE/NaegaGreen
GitHub - CAPSTONEEEEE/NaegaGreen
Contribute to CAPSTONEEEEE/NaegaGreen development by creating an account on GitHub.
github.com
데모 코드
1. 회원가입/로그인
※ 아래 코드블럭별로 구분된대로 코랩에서의 별도의 셀이라 이해하면 된다.
# 소소행 Colab 초기화 셀
!pip install --quiet numpy pandas
import numpy as np
import pandas as pd
print("✅ 필수 패키지 설치 완료")
# 사용자 입력 기반 로그인/회원가입 데모 with 이름 입력 및 반복 (위젯사용ver)
import ipywidgets as widgets
from IPython.display import display, clear_output
# 사용자 DB
user_db = []
# 회원가입 함수
def sign_up(email, password, name, age, gender):
if any(user["email"] == email for user in user_db):
return False, "⚠️ 이미 존재하는 이메일입니다."
user = {
"email": email,
"password": password,
"name": name,
"age": age,
"gender": gender,
}
user_db.append(user)
return True, f"✅ 회원가입 성공! 환영합니다, {name}님"
# 로그인 함수
def login(email, password):
for user in user_db:
if user["email"] == email and user["password"] == password:
return True, f"🔓 로그인 성공! 환영합니다, {user['name']}님"
return False, "❌ 로그인 실패: 이메일 또는 비밀번호가 틀립니다."
# UI 구성
output = widgets.Output()
menu_buttons = widgets.ToggleButtons(
options=["로그인", "회원가입"],
description="선택:",
button_style="info",
)
# 입력 위젯들
email_input = widgets.Text(description="이메일:")
password_input = widgets.Password(description="비밀번호:")
name_input = widgets.Text(description="이름:")
age_input = widgets.IntText(description="나이:")
gender_input = widgets.Dropdown(options=["남성", "여성"], description="성별:")
submit_button = widgets.Button(description="제출", button_style="success")
# 상태 저장
current_action = {"mode": None}
# 버튼 클릭 처리
def on_menu_change(change):
clear_output()
output.clear_output()
display(menu_buttons)
if change["new"] == "로그인":
current_action["mode"] = "login"
display(email_input, password_input, submit_button, output)
elif change["new"] == "회원가입":
current_action["mode"] = "signup"
display(email_input, password_input, name_input, age_input, gender_input, submit_button, output)
def on_submit_click(b):
output.clear_output()
with output:
if current_action["mode"] == "login":
success, message = login(email_input.value, password_input.value)
print(message)
elif current_action["mode"] == "signup":
success, message = sign_up(
email_input.value,
password_input.value,
name_input.value,
age_input.value,
gender_input.value
)
print(message)
# 성공 시 자동 리셋
if success:
menu_buttons.disabled = True
submit_button.disabled = True
# 이벤트 연결
menu_buttons.observe(on_menu_change, names="value")
submit_button.on_click(on_submit_click)
# 실행
display(menu_buttons)
2. 사용자 맞춤 여행지 추천
※ 해당 코드를 실행하려면 아래 두 사이트를 통해
1. 관광데이터포털에서 '한국관광공사_국문 관광정보 서비스_GW' 활용신청 후 인증키를 받아 servicekey 변수에 입력하고,
https://www.data.go.kr/tcs/dss/selectApiDataDetailView.do?publicDataPk=15101578
2. OpenAI Platform에서 신규 API key를 발급받아 api_key 변수에 입력해야한다.
https://platform.openai.com/api-keys
# 지역 맞춤형 관광지 추천
: 사용자 여행 목적 및 지역에 부합하는 관광지 정보 필터링 및 제공
import openai
import requests
import pandas as pd
# ✅ OpenAI 키 설정
openai.api_key = "" # ⚠️ 본인의 OpenAI 키로 교체하세요!
# ✅ GPT로 연관 키워드 확장
def get_related_keywords(keyword):
try:
prompt = f"""
'{keyword}'라는 여행 목적 키워드와 관련된 유사 키워드를 5개 추천해주세요.
단어만 콤마로 구분해서 출력하세요. 예: 휴식, 자연, 산책, 명상, 힐링
"""
response = openai.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.7
)
raw = response.choices[0].message.content
return [k.strip() for k in raw.split(",") if k.strip()]
except Exception as e:
print(f"❌ GPT 키워드 확장 실패: {e}")
return [keyword]
# ✅ GPT로 간단한 소개 생성
def generate_overview(title):
try:
prompt = f"'{title}'라는 장소에 대해 간단한 관광 소개글을 한글로 2~3문장으로 작성해줘."
response = openai.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.7
)
return response.choices[0].message.content.strip()
except Exception as e:
return f"(GPT 소개 생성 실패: {e})"
# ✅ 관광지 검색 함수 (지역 + 키워드 포함 조건)
def search_places(keywords, region, max_results=10):
url = "http://apis.data.go.kr/B551011/KorService2/searchKeyword2"
servicekey = 'ILgc5Ptzlb9mvXO42jF2hHGHNFwLKB77Fmxz8P79ogO7jdZw4su3pG8faMK+B91LNSFgB6wfsUYjqH5TecGX0A=='
collected = []
for keyword in keywords:
for page in range(1, 6): # 최대 5페이지 조회
params = {
'MobileOS': 'ETC',
'MobileApp': 'Soso',
'serviceKey': servicekey,
'_type': 'json',
'numOfRows': 10,
'pageNo': page,
'keyword': keyword
}
try:
response = requests.get(url, params=params)
data = response.json()
items = data['response']['body']['items']
if isinstance(items, str): # 빈 문자열
break
results = items.get('item', [])
for item in results:
title = item.get('title', '')
addr1 = item.get('addr1', '')
if region in addr1: # 지역명 포함 여부 확인
collected.append({'title': title, 'addr1': addr1})
if len(collected) >= max_results:
return collected
except Exception as e:
print(f"❌ 관광지 API 오류: {e}")
break
return collected
# ✅ 메인 실행 함수
def main():
print("🔍 지역 맞춤형 관광지 추천")
keyword = input("📌 여행 목적 또는 키워드를 입력하세요 (예: 재충전, 문화 체험 등): ").strip()
region = input("🌍 여행하고 싶은 지역을 입력하세요 (예: 전주, 부산, 강릉 등): ").strip()
related = get_related_keywords(keyword)
print("\n🔎 확장된 키워드:", related)
places = search_places(related, region, max_results=10)
if not places:
print(f"❌ '{region}' 지역에 '{keyword}' 관련 관광지를 찾을 수 없습니다.")
return
for i, place in enumerate(places, 1):
overview = generate_overview(place['title'])
print(f"\n{i}. 📍 {place['title']}")
print(f"🗺️ 주소: {place['addr1']}")
print(f"📝 소개: {overview}")
# ✅ 실행
main()
# 사용자 입력 기반 여행지 추천
: 사용자 입력을 프롬프트로 가공하여 GPT 를 통해 관련 여행지 텍스트 정보를 생성
!pip install ipywidgets --quiet
import openai
import ipywidgets as widgets
from IPython.display import display
from datetime import datetime
# ✅ OpenAI API 설정
client = openai.OpenAI(api_key="") # ⚠️ 본인의 OpenAI 키로 교체하세요!
# ✅ 날짜 → 계절 변환 함수
def date_to_season(date_obj):
month = date_obj.month
if month in [3, 4, 5]:
return "봄"
elif month in [6, 7, 8]:
return "여름"
elif month in [9, 10, 11]:
return "가을"
else:
return "겨울"
# ✅ GPT 프롬프트 생성 함수
def build_prompt(info):
prompt = f"""
당신은 사용자에게 딱 맞는 여행지를 추천해주는 똑똑한 여행 플래너입니다.
아래 사용자의 정보를 참고하여 지역 기반 여행지와 활동을 추천해주세요.
📅 여행 시기: {info['date']} ({info['season']})
📍 출발지: {info['start_location']} (선호 거리: {info['distance']}km 이내)
🚗 이동 수단: {info['transport']}
🎯 여행 목적: {info['purpose']}
👥 동반자: {info['companion']}
✈️ 여행 스타일: {info['style_type']} - {info['style_detail']}
위 조건을 반영하여 대한민국 소도시 중에서 2~3곳을 추천해주시고, 각 도시에서 할 수 있는 대표적인 활동, 맛집, 사진 스팟 등을 함께 제안해주세요.
"""
return prompt.strip()
# ✅ GPT 호출 함수
def chat_with_gpt(prompt, model="gpt-4"):
response = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": "You are a helpful and friendly Korean travel assistant."},
{"role": "user", "content": prompt}
],
temperature=0.7,
max_tokens=1000
)
return response.choices[0].message.content.strip()
# ✅ 위젯 생성
date_picker = widgets.DatePicker(description="📅 여행 날짜")
start_location = widgets.Text(description="출발 지역")
# ✅ IntSlider로 거리 조절 (10~500, 10단위)
distance = widgets.IntSlider(
description="이동 거리(km)",
value=100,
min=10,
max=500,
step=10,
style={'description_width': 'initial'},
continuous_update=False
)
transport = widgets.RadioButtons(
options=["자가용", "고속버스", "기차", "미정"],
description="🚗 이동 수단",
)
purpose = widgets.RadioButtons(
options=[
"마음 정리, 재충전",
"특별한 사람과 추억",
"가족과 즐거운 시간",
"친구들과 액티비티",
"SNS용 사진",
"지역 먹거리 체험",
"문화/역사 경험"
],
description="🎯 목적",
layout={'width': 'max-content'}
)
companion = widgets.RadioButtons(
options=["혼자", "연인", "가족", "친구"],
description="👥 동반자"
)
style = widgets.Dropdown(
options=["힐링 여행", "액티비티 여행", "관광 명소 여행"],
description="✈️ 스타일"
)
# 세부 스타일 매핑
style_detail_map = {
"힐링 여행": ["자연 속", "도심 속"],
"액티비티 여행": ["수상 레저", "산악 등산", "자전거/ATV", "이색 체험", "실내 체험"],
"관광 명소 여행": ["역사 유적지", "문화예술 공간", "도시 탐방", "자연 명소"]
}
style_detail = widgets.Dropdown(description="세부 유형")
# 스타일 변경 시 세부 스타일 업데이트
def update_style_detail(*args):
style_detail.options = style_detail_map.get(style.value, [])
style.observe(update_style_detail, 'value')
update_style_detail()
# ✅ 실행 버튼 정의
submit_button = widgets.Button(description="🚀 여행지 추천받기", button_style='success')
output = widgets.Output()
def on_submit(b):
with output:
output.clear_output()
if not date_picker.value:
print("❗ 날짜를 선택해주세요.")
return
season = date_to_season(date_picker.value)
user_info = {
"date": str(date_picker.value),
"season": season,
"start_location": start_location.value,
"distance": distance.value,
"transport": transport.value,
"purpose": purpose.value,
"companion": companion.value,
"style_type": style.value,
"style_detail": style_detail.value
}
prompt = build_prompt(user_info)
print(f"📅 여행 시기: {user_info['date']} ({season})")
print(f"📍 출발지: {user_info['start_location']} (선호 거리: {user_info['distance']}km 이내)")
print(f"🚗 이동 수단: {user_info['transport']}")
print(f"🎯 여행 목적: {user_info['purpose']}")
print(f"👥 동반자: {user_info['companion']}")
print(f"✈️ 여행 스타일: {user_info['style_type']} - {user_info['style_detail']}")
print("\n💬 추천 결과:\n")
print(chat_with_gpt(prompt))
submit_button.on_click(on_submit)
# ✅ 위젯 출력
display(
date_picker, start_location, distance, transport,
purpose, companion, style, style_detail,
submit_button, output
)
3. 지역 기반 축제 정보 제공
※ 해당 코드를 실행하려면 아래 두 사이트를 통해
1. 관광데이터포털에서 '한국관광공사_국문 관광정보 서비스_GW' 활용신청 후 인증키를 받아 servicekey 변수에 입력하고,
https://www.data.go.kr/tcs/dss/selectApiDataDetailView.do?publicDataPk=15101578
2. OpenAI Platform에서 신규 API key를 발급받아 api_key 변수에 입력해야한다.
https://platform.openai.com/api-keys
# RAG 방식 축제 추천
: GPT 호출 + RAG 구조를 통해 입력 키워드를 확장 및 확장된 키워드에 맞는 축제 추천
# 🔧 설치 (최초 1회만)
!pip install openai pandas requests --quiet
# ✅ 1. 패키지 임포트
import requests
import sqlite3
import pandas as pd
from pandas import json_normalize
from openai import OpenAI
# ✅ 2. OpenAI 클라이언트 생성 (GPT 호출용)
client = OpenAI(api_key="") # ⚠️ 본인의 OpenAI 키로 교체하세요!
# ✅ 3. SQLite 연결 및 테이블 생성
conn = sqlite3.connect("festivals.db")
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS festivals (
contentid TEXT PRIMARY KEY,
title TEXT,
addr1 TEXT,
eventstartdate TEXT,
eventenddate TEXT,
mapx REAL,
mapy REAL
)
''')
conn.commit()
# ✅ 4. TourAPI에서 축제 데이터 수집
def fetch_and_store_festivals():
servicekey = '' # ⚠️ 본인의 TourAPI 키로 교체하세요!
url = 'http://apis.data.go.kr/B551011/KorService2/searchFestival2'
page = 1
while True:
print(f"{page} 페이지 수집 중...")
params = {
'MobileOS': 'ETC',
'MobileApp': 'Soso',
'serviceKey': servicekey,
'_type': 'json',
'eventStartDate': '20250601',
'eventEndDate': '20250831',
'numOfRows': 100,
'pageNo': page
}
response = requests.get(url, params=params)
try:
data = response.json()
except ValueError:
print("❌ JSON 파싱 실패:\n", response.text)
break
if isinstance(data, str):
print("❌ 응답이 문자열입니다:\n", data)
break
try:
items = data['response']['body']['items'].get('item', [])
except Exception as e:
print("❌ 응답 구조 오류:", e)
print("전체 응답:\n", data)
break
if not items:
print("✅ 데이터 수집 완료.")
break
df = json_normalize(items)
for _, row in df.iterrows():
try:
cursor.execute("""
INSERT OR REPLACE INTO festivals
(contentid, title, addr1, eventstartdate, eventenddate, mapx, mapy)
VALUES (?, ?, ?, ?, ?, ?, ?)
""", (
str(row.get('contentid')),
row.get('title'),
row.get('addr1'),
row.get('eventstartdate'),
row.get('eventenddate'),
float(row.get('mapx', 0)) if row.get('mapx') else None,
float(row.get('mapy', 0)) if row.get('mapy') else None,
))
except Exception as e:
print(f"❌ 저장 오류: {e}")
conn.commit()
page += 1
# ✅ 5. GPT로 관련 키워드 확장 (RAG 방식의 핵심)
def get_related_keywords(keyword):
prompt = f"""
여행 관련 축제를 검색하려고 해. '{keyword}'과(와) 의미상 관련된 키워드를 5~7개 정도 추천해줘.
한글 단어만, 쉼표(,)로 구분해서 출력해줘. 예를 들어 '음악'을 입력하면 '재즈, 밴드, 콘서트, EDM, 라이브' 등으로 출력해줘.
"""
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "여행 축제 키워드 추천 도우미입니다."},
{"role": "user", "content": prompt}
],
temperature=0.7,
max_tokens=100
)
raw = response.choices[0].message.content
return [k.strip() for k in raw.split(",")]
# ✅ 6. SQLite에서 키워드 기반으로 축제 검색
def search_festivals_by_keywords(keywords):
placeholders = " OR ".join(["title LIKE ? OR addr1 LIKE ?" for _ in keywords])
query = f"SELECT title, addr1, eventstartdate, eventenddate FROM festivals WHERE {placeholders}"
params = []
for kw in keywords:
like_kw = f"%{kw}%"
params.extend([like_kw, like_kw])
cursor.execute(query, tuple(params))
return cursor.fetchall()
# ✅ 7. 메인 실행 (지역 기반 추가)
def main():
# 축제 데이터 수집 (이미 했으면 생략 가능)
fetch_and_store_festivals()
keyword = input("\n📌 여행 목적 키워드를 입력하세요 (예: 음악, 전통, 불꽃): ")
region = input("📍 여행 지역을 입력하세요 (예: 전주, 강릉, 부산 등): ")
# GPT로 키워드 확장
related_keywords = get_related_keywords(keyword)
print("\n🔍 확장된 키워드:", related_keywords)
# 지역 키워드도 함께 검색 조건에 추가
all_keywords = related_keywords + [region]
results = search_festivals_by_keywords(all_keywords)
if results:
print(f"\n✅ '{keyword}' 및 '{region}' 관련 축제 목록:")
for row in results:
print(f"\n🎉 {row[0]}")
print(f"📍 장소: {row[1]}")
print(f"📅 일정: {row[2]} ~ {row[3]}")
else:
print(f"\n❌ '{keyword}' 또는 '{region}' 관련 축제를 찾을 수 없습니다.")
# 마무리
cursor.close()
conn.close()
# 실행
main()
# 위치 기반 근방 10km 이내 축제 추천
: TourAPI 를 활용하여 반경 10km 이내의 축제 데이터 수집
import requests
import pandas as pd
from pandas import json_normalize
import mysql.connector
# ✅ MySQL 접속 정보 입력
conn = mysql.connector.connect(
host='localhost',
user='root',
password='MyPassword',
database='tour_db'
)
cursor = conn.cursor()
# ✅ TourAPI 설정
servicekey = '' # ⚠️ 본인의 TourAPI 키로 교체하세요!
url = 'http://apis.data.go.kr/B551011/KorService2/searchFestival2'
page = 1
while True:
print(f"{page} 페이지 수집 중...")
params = {
'MobileOS': 'ETC',
'MobileApp': 'Soso',
'serviceKey': servicekey,
'_type': 'json',
'eventStartDate': '20250602',
'eventEndDate': '20250610',
'numOfRows': 100,
'pageNo': page
}
response = requests.get(url, params=params)
try:
data = response.json()
if isinstance(data, str): # 응답이 JSON이 아니라 문자열일 경우
print("응답이 문자열입니다. 종료합니다.")
break
items = data['response']['body']['items'].get('item', [])
except Exception as e:
print(f"오류 발생: {e}")
break
if not items:
print("✅ 모든 데이터 수집 완료.")
break
df = json_normalize(items)
# ✅ 행별로 MySQL 저장
for _, row in df.iterrows():
try:
cursor.execute("""
INSERT INTO festivals (contentid, title, addr1, eventstartdate, eventenddate, mapx, mapy)
VALUES (%s, %s, %s, %s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
title = VALUES(title),
addr1 = VALUES(addr1),
eventstartdate = VALUES(eventstartdate),
eventenddate = VALUES(eventenddate),
mapx = VALUES(mapx),
mapy = VALUES(mapy)
""", (
row.get('contentid'),
row.get('title'),
row.get('addr1'),
row.get('eventstartdate'),
row.get('eventenddate'),
float(row.get('mapx', 0)),
float(row.get('mapy', 0)),
))
except Exception as insert_error:
print(f"❌ 삽입 오류: {insert_error}")
conn.commit()
page += 1
# 마무리
cursor.close()
conn.close()
print(" MySQL 저장 완료")
#여기까지 데이터 받아오기
from geopy.distance import geodesic
import mysql.connector
def fetch_festivals_from_mysql():
# ✅ MySQL 연결 정보
conn = mysql.connector.connect(
host='localhost',
user='root',
password='MyPassword',
database='tour_db'
)
cursor = conn.cursor(dictionary=True) # 딕셔너리 모드로 가져오기
cursor.execute("SELECT title, addr1, eventstartdate, eventenddate, mapy AS lat, mapx AS lng FROM festivals")
festivals = cursor.fetchall()
cursor.close()
conn.close()
return festivals
def main():
print("🎯 내 위치 기반 축제 검색기 (MySQL)")
lat = float(input("📍 현재 위도 입력: "))
lng = float(input("📍 현재 경도 입력: "))
festivals = fetch_festivals_from_mysql()
nearby = []
for f in festivals:
if f["lat"] is None or f["lng"] is None:
continue # 좌표 없는 데이터는 제외
dist = geodesic((lat, lng), (f["lat"], f["lng"])).km
if dist <= 10:
f["distance_km"] = round(dist, 2)
nearby.append(f)
if not nearby:
print("❌ 10km 이내에 축제가 없습니다.")
return
print(f"\n✅ 내 위치 기준 10km 이내 축제 {len(nearby)}건:")
for f in sorted(nearby, key=lambda x: x["distance_km"]):
print(f"\n🎉 {f['title']}")
print(f" 📍 장소: {f['addr1']}")
print(f" 📅 기간: {f['eventstartdate']} ~ {f['eventenddate']}")
print(f" 🧭 거리: {f['distance_km']}km")
if __name__ == "__main__":
main()
4. 로컬 특산물 등록 및 구매/판매
※ 아래 코드블럭별로 구분된대로 코랩에서의 별도의 셀이라 이해하면 된다.
# 로컬 특산물 정보 제공 (위젯사용ver)
: 지역 특산물에 대해 판매자-구매자 연결을 위한 데모 기능 구현 코드
# 📌 로컬 특산물 판매 데모 (게시물 관리 + 리뷰 + 인증 + 되돌아가기 포함)
import pandas as pd
# 데이터 저장소
sellers = []
products = []
reviews = {}
# 판매자 등록
def register_seller(name, address, business_id, manager, phone):
if any(s["name"] == name and s["business_id"] == business_id for s in sellers):
return f"⚠️ 이미 등록된 판매자입니다: {name}"
sellers.append({
"name": name,
"address": address,
"business_id": business_id,
"manager": manager,
"phone": phone
})
return f"✅ 판매자 등록 완료: {name} ({business_id})"
# 판매자 인증
def authenticate_seller(name, business_id):
return any(s["name"] == name and s["business_id"] == business_id for s in sellers)
# 제품 등록
def register_product(seller_name, product_name, price, description):
product = {
"판매자": seller_name,
"상품명": product_name,
"가격": price,
"설명": description,
"상태": "판매중"
}
products.append(product)
return f"✅ 상품 '{product_name}' 등록 완료!"
# 제품 보기
def view_products():
if not products:
print("🔍 등록된 상품이 없습니다.")
return
df = pd.DataFrame(products).reset_index().rename(columns={"index": "번호"})
print(df[["번호", "상품명", "판매자", "가격", "상태"]])
selection_input = input("상세히 볼 상품 번호를 선택하세요 (또는 'b' 입력 시 이전으로): ").strip()
if selection_input.lower() == 'b':
return
try:
selection = int(selection_input)
if 0 <= selection < len(products):
product = products[selection]
print("\n📦 상품 상세 정보:")
for k, v in product.items():
print(f"{k}: {v}")
# 리뷰 출력
product_key = product["상품명"]
product_reviews = reviews.get(product_key, [])
print("\n📝 리뷰:")
if product_reviews:
for idx, r in enumerate(product_reviews):
print(f"{idx+1}. {r}")
else:
print("등록된 리뷰가 없습니다.")
# 채팅 여부
chat = input("🤝 판매자와 채팅하시겠습니까? (y/n): ").strip().lower()
if chat == "y":
seller_info = next(s for s in sellers if s["name"] == product["판매자"])
print(f"📞 연결 완료! {seller_info['manager']}님에게 연락하세요: {seller_info['phone']}")
else:
print("❌ 채팅을 취소했습니다.")
else:
print("❗유효하지 않은 번호입니다.")
except:
print("❗잘못된 입력입니다.")
# 리뷰 쓰기
def write_review():
keyword = input("리뷰를 남길 상품명을 입력하세요 (또는 'b' 입력 시 이전으로): ").strip()
if keyword.lower() == 'b':
return
matches = [p for p in products if keyword in p["상품명"]]
if not matches:
print("❌ 해당 상품을 찾을 수 없습니다.")
return
print("\n🔍 검색 결과:")
for idx, m in enumerate(matches):
print(f"{idx}: {m['상품명']} (판매자: {m['판매자']})")
selection_input = input("리뷰를 남길 상품 번호를 선택하세요: ").strip()
try:
idx = int(selection_input)
selected_product = matches[idx]
content = input("✍ 리뷰를 작성해주세요: ")
key = selected_product["상품명"]
if key not in reviews:
reviews[key] = []
reviews[key].append(content)
print("✅ 리뷰가 저장되었습니다.")
except:
print("❗잘못된 입력입니다.")
# 게시물 관리
def manage_posts():
print("\n🔐 게시물 관리를 위해 판매자 인증이 필요합니다.")
name = input("상호명: ")
if name.lower() == 'b': return
business_id = input("사업자등록번호: ")
if business_id.lower() == 'b': return
if not authenticate_seller(name, business_id):
print("❌ 판매자 인증 실패")
return
my_products = [p for p in products if p["판매자"] == name]
if not my_products:
print("📭 등록한 상품이 없습니다.")
return
print("\n📋 나의 등록 상품 목록:")
for idx, p in enumerate(my_products):
print(f"{idx}: {p['상품명']} / 상태: {p['상태']} / 가격: {p['가격']}")
sel_input = input("수정/삭제할 상품 번호 선택 (또는 'b' 입력 시 이전으로): ").strip()
if sel_input.lower() == 'b': return
try:
sel_idx = int(sel_input)
selected = my_products[sel_idx]
print("\n1. 상품 정보 수정")
print("2. 판매 상태 변경")
print("3. 상품 삭제")
action = input("수행할 작업 번호 선택: ").strip()
if action == '1':
new_name = input(f"새 상품명 입력 (Enter=변경 없음): ").strip()
new_price = input(f"새 가격 입력 (Enter=변경 없음): ").strip()
new_desc = input(f"새 설명 입력 (Enter=변경 없음): ").strip()
if new_name: selected["상품명"] = new_name
if new_price: selected["가격"] = int(new_price)
if new_desc: selected["설명"] = new_desc
print("✅ 상품 정보가 수정되었습니다.")
elif action == '2':
print("선택 가능한 상태: 판매중 / 품절 / 예약중")
new_state = input("새 판매 상태 입력: ").strip()
if new_state in ["판매중", "품절", "예약중"]:
selected["상태"] = new_state
print(f"✅ 상태가 '{new_state}'(으)로 변경되었습니다.")
else:
print("❌ 유효하지 않은 상태입니다.")
elif action == '3':
products.remove(selected)
print("🗑️ 상품이 삭제되었습니다.")
else:
print("❗잘못된 입력입니다.")
except:
print("❗입력 오류입니다.")
# 메인 루프
while True:
print("\n🛍️ 무엇을 하시겠습니까?")
print("1: 판매자 등록")
print("2: 제품 등록")
print("3: 제품 보기")
print("4: 리뷰 쓰기")
print("5: 게시물 관리")
print("0: 종료")
choice = input("번호 입력: ").strip()
if choice == "1":
print("\n👤 판매자 등록 (이전: 'b')")
name = input("상호명: ")
if name.lower() == 'b': continue
address = input("주소: ")
if address.lower() == 'b': continue
business_id = input("사업자등록번호: ")
if business_id.lower() == 'b': continue
manager = input("담당자 이름: ")
if manager.lower() == 'b': continue
phone = input("가게 연락처: ")
if phone.lower() == 'b': continue
print(register_seller(name, address, business_id, manager, phone))
elif choice == "2":
print("\n📦 제품 등록 - 판매자 인증 (이전: 'b')")
name = input("상호명: ")
if name.lower() == 'b': continue
business_id = input("사업자등록번호: ")
if business_id.lower() == 'b': continue
if authenticate_seller(name, business_id):
product_name = input("상품명: ")
if product_name.lower() == 'b': continue
price_input = input("가격 (숫자): ")
if price_input.lower() == 'b': continue
try:
price = int(price_input)
except:
print("❗유효한 숫자가 아닙니다.")
continue
description = input("상품 설명: ")
if description.lower() == 'b': continue
print(register_product(name, product_name, price, description))
else:
print("❌ 판매자 인증 실패. 등록된 판매자만 제품을 등록할 수 있습니다.")
elif choice == "3":
print("\n📋 등록된 제품 보기")
view_products()
elif choice == "4":
print("\n✍ 리뷰 작성")
write_review()
elif choice == "5":
print("\n🛠️ 게시물 관리")
manage_posts()
elif choice == "0":
print("👋 종료합니다.")
break
else:
print("❗잘못된 입력입니다. 다시 시도해주세요.")
💡위 코드들에 대한 결과 및 전체 시연영상은 아래 링크에서 확인할 수 있다.
데모영상
https://youtu.be/dMyhT8ioe9s?si=xKmXJQUNNJlcuILl
다음 글에서는..
스타트 최종보고서 작성과 기말 심층인터뷰의 후기를 기록으로 남겨보도록 하겠다.
'주전공 > 캡스톤디자인과창업프로젝트' 카테고리의 다른 글
| 여름방학 기록(2) : React Native 개발 환경 구축 (0) | 2025.08.09 |
|---|---|
| 여름방학 기록(1) : 방학 개발계획 수립 및 피그마 UI 제작 (0) | 2025.08.04 |
| 졸프 - 소소행; | 1차 중간발표 준비 | 세부 기획 및 발표자료 제작 (0) | 2025.06.12 |
| 졸프 - 소소행; | Project Briefs.MD 작성 및 지도교수님 선정 | 대면 면담 ㅂㄷㅂㄷ (0) | 2025.06.05 |
| 졸프 - 소소행; | 첫 회의부터 깃허브 사용법 익히기까지 (0) | 2025.06.02 |