feat: 바코드 기반 제품 태깅 시스템 구축
- product_master 테이블: 제품 마스터 (바코드, 이름, 성분, 태그) - product_categories: 제품 카테고리 22개 (진통제, 소화제 등) - product_category_mapping: 다대다 매핑 (하나의 제품이 여러 카테고리) - disease_codes: 질병 코드 ICD-10 12개 - disease_product_mapping: 질병-제품 매핑 - 샘플 제품 3개 추가 (탁센, 베아제, 마그비맥스) - BARCODE 컬럼 95.79% 보유율 확인 - 온톨로지 기반 추천 시스템 설계 문서 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
396
docs/PRODUCT_TAGGING_SYSTEM.md
Normal file
396
docs/PRODUCT_TAGGING_SYSTEM.md
Normal file
@@ -0,0 +1,396 @@
|
||||
# 바코드 기반 제품 태깅 시스템 설계
|
||||
|
||||
## 목표
|
||||
|
||||
바코드를 기준으로 약품 정보를 AI로 자동 태깅하여 온톨로지 기반 추천 시스템 구축
|
||||
|
||||
## 배경
|
||||
|
||||
- **문제**: 약국마다 동일 제품의 이름이 다르게 저장됨 (예: "탁센", "탁센정", "Taxen")
|
||||
- **해결**: 바코드는 제품 껍데기에 인쇄되어 전국 동일 → 바코드 기준 마스터 데이터 구축
|
||||
- **현황**: SALE_SUB.BARCODE 컬럼 존재, 95.79% 판매 건수에 바코드 있음
|
||||
|
||||
## 시스템 구조
|
||||
|
||||
### 1. 데이터 구조
|
||||
|
||||
#### SQLite - product_master 테이블
|
||||
|
||||
```sql
|
||||
CREATE TABLE product_master (
|
||||
barcode TEXT PRIMARY KEY, -- 바코드 (8806449141111)
|
||||
product_name TEXT NOT NULL, -- 대표 제품명 (마그비맥스)
|
||||
|
||||
-- 기본 정보
|
||||
category TEXT, -- 분류 (일반의약품, 전문의약품, 건강기능식품)
|
||||
manufacturer TEXT, -- 제조사
|
||||
ingredients_json TEXT, -- 성분 정보 (JSON)
|
||||
|
||||
-- AI 태깅 (JSON)
|
||||
tags_symptoms TEXT, -- 증상 태그 ["피로회복", "구내염", "육체피로"]
|
||||
tags_ingredients TEXT, -- 성분 태그 ["메코발라민 1mg", "UDCA 60mg", "타우린 100mg"]
|
||||
tags_effects TEXT, -- 효능 태그 ["활성비타민 5종", "간 기능 개선"]
|
||||
|
||||
-- 온톨로지 (계층 구조)
|
||||
ontology_json TEXT, -- 온톨로지 구조 (JSON)
|
||||
|
||||
-- 메타데이터
|
||||
source_url TEXT, -- 크롤링한 URL
|
||||
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
is_verified BOOLEAN DEFAULT 0 -- 약사 검증 여부
|
||||
);
|
||||
|
||||
-- 인덱스
|
||||
CREATE INDEX idx_product_name ON product_master(product_name);
|
||||
CREATE INDEX idx_category ON product_master(category);
|
||||
```
|
||||
|
||||
#### JSON 구조 예시
|
||||
|
||||
**탁센 (Taxen)**
|
||||
```json
|
||||
{
|
||||
"barcode": "8806436016712",
|
||||
"product_name": "탁센캡슐",
|
||||
"category": "일반의약품",
|
||||
"manufacturer": "동아제약",
|
||||
|
||||
"ingredients": [
|
||||
{"name": "나프록센", "amount": "250mg", "role": "주성분"}
|
||||
],
|
||||
|
||||
"tags_symptoms": ["생리통", "치통", "골관절염", "두통", "근육통"],
|
||||
"tags_ingredients": ["나프록센 250mg", "비스테로이드성 소염진통제"],
|
||||
"tags_effects": ["진통", "소염", "해열"],
|
||||
|
||||
"ontology": {
|
||||
"class": "진통소염제",
|
||||
"subclass": "비스테로이드성 소염진통제",
|
||||
"mechanism": "COX 억제",
|
||||
"targets": ["관절염", "통증", "염증"],
|
||||
"relations": {
|
||||
"similar_to": ["이부프로펜", "디클로페낙"],
|
||||
"alternative_for": ["생리통약", "두통약"],
|
||||
"contraindications": ["위장장애", "임신말기", "아스피린 알레르기"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**마그비맥스**
|
||||
```json
|
||||
{
|
||||
"barcode": "8806265019618",
|
||||
"product_name": "마그비맥스",
|
||||
"category": "일반의약품",
|
||||
"manufacturer": "일양약품",
|
||||
|
||||
"ingredients": [
|
||||
{"name": "메코발라민", "amount": "1mg", "role": "비타민B12"},
|
||||
{"name": "UDCA", "amount": "60mg", "role": "간 기능 개선"},
|
||||
{"name": "타우린", "amount": "100mg", "role": "피로회복"},
|
||||
{"name": "피리독신", "amount": "50mg", "role": "비타민B6"},
|
||||
{"name": "티아민", "amount": "50mg", "role": "비타민B1"}
|
||||
],
|
||||
|
||||
"tags_symptoms": ["피로회복", "구내염", "육체피로", "신경통", "근육통"],
|
||||
"tags_ingredients": [
|
||||
"메코발라민 1mg",
|
||||
"UDCA 60mg",
|
||||
"타우린 100mg",
|
||||
"활성비타민 5종"
|
||||
],
|
||||
"tags_effects": ["간 기능 개선", "신경계 보호", "에너지 대사"],
|
||||
|
||||
"ontology": {
|
||||
"class": "비타민제",
|
||||
"subclass": "복합비타민",
|
||||
"mechanism": "비타민B군 보충",
|
||||
"targets": ["피로", "간기능", "신경계"],
|
||||
"relations": {
|
||||
"similar_to": ["박카스", "활명수", "우루사"],
|
||||
"alternative_for": ["피로회복제", "간 영양제"],
|
||||
"synergistic_with": ["밀크씨슬", "실리마린"],
|
||||
"contraindications": []
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. AI 자동 태깅 시스템
|
||||
|
||||
#### 2.1 데이터 소스
|
||||
|
||||
1. **약학정보원 (KPIS)**: https://www.health.kr
|
||||
- 의약품 검색 → 바코드로 검색
|
||||
- 효능, 성분, 용법 크롤링
|
||||
|
||||
2. **식약처 의약품안전나라**: https://nedrug.mfds.go.kr
|
||||
- 허가 정보, 성분, 효능효과
|
||||
- API 사용 가능 (공공데이터포털)
|
||||
|
||||
3. **건강보험심사평가원**: https://www.hira.or.kr
|
||||
- 약가 정보, 성분코드
|
||||
|
||||
4. **제품 인서트 이미지 OCR**
|
||||
- PIL + Tesseract OCR
|
||||
- 제품 박스 사진에서 성분 추출
|
||||
|
||||
#### 2.2 AI 태깅 프로세스
|
||||
|
||||
```python
|
||||
def ai_tag_product(barcode):
|
||||
"""
|
||||
바코드로 제품 자동 태깅
|
||||
|
||||
1. 웹 크롤링으로 제품 정보 수집
|
||||
2. OpenAI GPT-4o로 정보 분석 및 태깅
|
||||
3. 온톨로지 구조 생성
|
||||
4. SQLite에 저장
|
||||
"""
|
||||
|
||||
# Step 1: 웹 크롤링
|
||||
product_info = crawl_product_info(barcode)
|
||||
|
||||
# Step 2: OpenAI 프롬프트
|
||||
prompt = f"""
|
||||
다음 약품 정보를 분석하여 JSON 형식으로 태깅해주세요.
|
||||
|
||||
제품명: {product_info['name']}
|
||||
성분: {product_info['ingredients']}
|
||||
효능: {product_info['effects']}
|
||||
|
||||
다음 형식으로 반환:
|
||||
{{
|
||||
"tags_symptoms": ["증상1", "증상2", ...],
|
||||
"tags_ingredients": ["성분명 용량", ...],
|
||||
"tags_effects": ["효능1", "효능2", ...],
|
||||
"ontology": {{
|
||||
"class": "약품 분류",
|
||||
"subclass": "세부 분류",
|
||||
"mechanism": "작용 기전",
|
||||
"targets": ["대상 증상", ...],
|
||||
"relations": {{
|
||||
"similar_to": ["유사 제품", ...],
|
||||
"alternative_for": ["대체 가능 용도", ...],
|
||||
"synergistic_with": ["시너지 제품", ...],
|
||||
"contraindications": ["금기사항", ...]
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
|
||||
# Step 3: OpenAI 호출
|
||||
analysis = call_openai(prompt)
|
||||
|
||||
# Step 4: DB 저장
|
||||
save_to_product_master(barcode, analysis)
|
||||
```
|
||||
|
||||
#### 2.3 크롤링 구현
|
||||
|
||||
```python
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
def crawl_kpis(barcode):
|
||||
"""약학정보원에서 제품 정보 크롤링"""
|
||||
url = f"https://www.health.kr/searchDrug/result_drug.asp?barcode={barcode}"
|
||||
response = requests.get(url)
|
||||
soup = BeautifulSoup(response.text, 'html.parser')
|
||||
|
||||
return {
|
||||
"name": soup.select_one('.drug-name').text,
|
||||
"ingredients": soup.select('.ingredient'),
|
||||
"effects": soup.select_one('.effect').text,
|
||||
"manufacturer": soup.select_one('.maker').text
|
||||
}
|
||||
|
||||
def crawl_nedrug(barcode):
|
||||
"""식약처 의약품안전나라 API"""
|
||||
api_key = os.getenv('NEDRUG_API_KEY')
|
||||
url = f"https://apis.data.go.kr/1471000/DrugPrdtPrmsnInfoService05/getDrugPrdtPrmsnInq05"
|
||||
params = {
|
||||
"serviceKey": api_key,
|
||||
"bar_code": barcode,
|
||||
"type": "json"
|
||||
}
|
||||
response = requests.get(url, params=params)
|
||||
return response.json()
|
||||
```
|
||||
|
||||
### 3. API 엔드포인트
|
||||
|
||||
#### 3.1 제품 태깅 API
|
||||
|
||||
```python
|
||||
@app.route('/api/product/tag/<barcode>', methods=['POST'])
|
||||
def tag_product(barcode):
|
||||
"""
|
||||
바코드로 제품 자동 태깅
|
||||
|
||||
Returns:
|
||||
{
|
||||
"success": true,
|
||||
"product": {...},
|
||||
"tags": {...},
|
||||
"ontology": {...}
|
||||
}
|
||||
"""
|
||||
```
|
||||
|
||||
#### 3.2 제품 조회 API
|
||||
|
||||
```python
|
||||
@app.route('/api/product/<barcode>', methods=['GET'])
|
||||
def get_product(barcode):
|
||||
"""
|
||||
바코드로 제품 정보 조회
|
||||
|
||||
Returns:
|
||||
{
|
||||
"success": true,
|
||||
"product": {...},
|
||||
"recommendations": [...] # 온톨로지 기반 추천
|
||||
}
|
||||
"""
|
||||
```
|
||||
|
||||
#### 3.3 유사 제품 추천 API
|
||||
|
||||
```python
|
||||
@app.route('/api/product/<barcode>/recommendations', methods=['GET'])
|
||||
def get_recommendations(barcode):
|
||||
"""
|
||||
온톨로지 기반 유사/대체 제품 추천
|
||||
|
||||
Returns:
|
||||
{
|
||||
"similar_products": [...],
|
||||
"alternative_products": [...],
|
||||
"synergistic_products": [...]
|
||||
}
|
||||
"""
|
||||
```
|
||||
|
||||
### 4. 온톨로지 기반 추천 로직
|
||||
|
||||
```python
|
||||
def recommend_products(user_id, current_barcode):
|
||||
"""
|
||||
온톨로지 기반 제품 추천
|
||||
|
||||
1. 사용자 구매 이력 분석
|
||||
2. 현재 제품의 온톨로지 확인
|
||||
3. 유사/대체/시너지 제품 검색
|
||||
4. 사용자 맞춤 추천
|
||||
"""
|
||||
|
||||
# 사용자 구매 패턴
|
||||
user_purchases = get_user_purchase_history(user_id)
|
||||
|
||||
# 현재 제품 온톨로지
|
||||
product = get_product_master(current_barcode)
|
||||
ontology = product['ontology']
|
||||
|
||||
# 추천 알고리즘
|
||||
recommendations = []
|
||||
|
||||
# 1. 유사 제품 (similar_to)
|
||||
for similar_barcode in ontology['relations']['similar_to']:
|
||||
recommendations.append({
|
||||
"barcode": similar_barcode,
|
||||
"reason": "유사 제품",
|
||||
"score": 0.8
|
||||
})
|
||||
|
||||
# 2. 대체 제품 (alternative_for)
|
||||
for alt_category in ontology['relations']['alternative_for']:
|
||||
alt_products = search_by_category(alt_category)
|
||||
recommendations.extend(alt_products)
|
||||
|
||||
# 3. 시너지 제품 (synergistic_with)
|
||||
for synergy_barcode in ontology['relations']['synergistic_with']:
|
||||
recommendations.append({
|
||||
"barcode": synergy_barcode,
|
||||
"reason": "함께 복용 시 효과적",
|
||||
"score": 0.9
|
||||
})
|
||||
|
||||
return recommendations
|
||||
```
|
||||
|
||||
### 5. Vector Database 활용 (선택)
|
||||
|
||||
고급 검색을 위해 Vector DB(Pinecone, Weaviate, ChromaDB) 사용 가능:
|
||||
|
||||
```python
|
||||
# 제품 임베딩 생성
|
||||
from openai import OpenAI
|
||||
|
||||
def create_product_embedding(product):
|
||||
"""제품 정보를 벡터로 변환"""
|
||||
text = f"{product['name']} {' '.join(product['tags_symptoms'])} {' '.join(product['tags_ingredients'])}"
|
||||
|
||||
client = OpenAI()
|
||||
response = client.embeddings.create(
|
||||
input=text,
|
||||
model="text-embedding-3-small"
|
||||
)
|
||||
|
||||
return response.data[0].embedding
|
||||
|
||||
# 유사 제품 검색
|
||||
def search_similar_products(query_embedding, top_k=10):
|
||||
"""벡터 유사도 기반 제품 검색"""
|
||||
# ChromaDB 사용 예시
|
||||
results = collection.query(
|
||||
query_embeddings=[query_embedding],
|
||||
n_results=top_k
|
||||
)
|
||||
return results
|
||||
```
|
||||
|
||||
## 구현 단계
|
||||
|
||||
### Phase 1: 데이터 수집 (1주)
|
||||
- [ ] product_master 테이블 생성
|
||||
- [ ] 약학정보원 크롤러 구현
|
||||
- [ ] 식약처 API 연동
|
||||
- [ ] 100개 인기 제품 수동 태깅
|
||||
|
||||
### Phase 2: AI 태깅 (1주)
|
||||
- [ ] OpenAI 태깅 API 구현
|
||||
- [ ] 배치 태깅 스크립트
|
||||
- [ ] 전체 제품 자동 태깅
|
||||
|
||||
### Phase 3: 온톨로지 구축 (1주)
|
||||
- [ ] 제품 분류 체계 구축
|
||||
- [ ] 관계 정의 (유사/대체/시너지)
|
||||
- [ ] 추천 알고리즘 구현
|
||||
|
||||
### Phase 4: 검증 및 개선 (1주)
|
||||
- [ ] 약사 검증 UI
|
||||
- [ ] 오류 수정 시스템
|
||||
- [ ] 성능 최적화
|
||||
|
||||
## 예상 비용
|
||||
|
||||
- **OpenAI API**: GPT-4o-mini 사용 시 3,000개 제품 × $0.002 = $6
|
||||
- **웹 크롤링**: 무료 (공공데이터)
|
||||
- **Vector DB**: ChromaDB (로컬) 사용 시 무료
|
||||
|
||||
## 기대 효과
|
||||
|
||||
1. **개인화 추천**: 고객 구매 패턴 + 온톨로지 → 정확한 제품 추천
|
||||
2. **재구매 유도**: "지난번 구매한 탁센과 유사한 제품"
|
||||
3. **크로스셀**: "마그비맥스와 함께 복용하면 좋은 밀크씨슬"
|
||||
4. **약사 상담 지원**: 대체 제품 즉시 검색
|
||||
5. **재고 관리**: 유사 제품 재고 확인
|
||||
|
||||
## 참고 자료
|
||||
|
||||
- 약학정보원: https://www.health.kr
|
||||
- 식약처 의약품안전나라: https://nedrug.mfds.go.kr
|
||||
- 공공데이터포털 API: https://www.data.go.kr
|
||||
- OpenAI Embeddings: https://platform.openai.com/docs/guides/embeddings
|
||||
Reference in New Issue
Block a user