Skip to content

중간 피드백)챗봇 기능 추가 구현 필요 #14

@annalee8595

Description

@annalee8595

챗봇) Write-Through 패턴을 사용하여 DB와 캐시를 동시에 업데이트하거나 Cache-Aside 패턴으로 캐시 미스 시에만 DB에서 로드하는 방식을 권장합니다.

  • 챗봇

    1. Write-Through 패턴

    쓰기를 할 때마다 DB(또는 JSON 파일)와 Redis 캐시를 동시에 업데이트

    from backend.survey.content_recommend import compute_user_tag_scores
    import json, os
    
    def save_user_profile(user_id: int, profile_data: dict):
        # 1) DB/파일에 저장
        path = os.path.join(PROFILES_DIR, f"{user_id}.json")
        with open(path, "w", encoding="utf-8") as f:
            json.dump(profile_data, f, ensure_ascii=False, indent=2)
    
        # 2) 캐시에 같은 키로 저장 (Write-Through)
        cache_key = f"user_profile:{user_id}"
        cache.set(cache_key, profile_data)
    • 장점: 캐시와 원본 데이터가 항상 동기화
    • 단점: 쓰기 비용이 캐시에까지 이중 발생

    1. Cache-Aside 패턴

    읽기 시 캐시에 없으면(DB/파일에서) 로드 → 캐시에 써 두기

    def load_user_profile(user_id: int) -> dict:
        cache_key = f"user_profile:{user_id}"
        profile = cache.get(cache_key)
        if profile is not None:
            app.logger.debug("Cache hit for %s", cache_key)
            return profile
    
        app.logger.debug("Cache miss for %s, loading from file", cache_key)
        # 파일에서 로드
        path = os.path.join(PROFILES_DIR, f"{user_id}.json")
        try:
            with open(path, "r", encoding="utf-8") as f:
                profile = json.load(f)
        except FileNotFoundError:
            # 기본 프로필
            with open(DEFAULT_PROFILE_PATH, "r", encoding="utf-8") as f:
                profile = json.load(f)
    
        # 캐시에 적재
        cache.set(cache_key, profile)
        return profile
    • 장점: 읽기 빈도가 높은 데이터만 캐시
    • 단점: 첫 읽기 시에는 캐시 미스로 지연 발생

    1. 예시: 추천 API에 적용하기
    @content_recommend_bp.route('/api/recommend/contents', methods=['GET'])
    def get_recommendations():
        user_id   = current_user.id if current_user.is_authenticated else "default"
        profile   = load_user_profile(user_id)      # Cache-Aside 로드
        user_tags = [t for t in profile["weights"] if t != "필터"]
        city      = request.args.get("city", "서울")
        contents  = load_city_contents(city)
    
        groups    = recommend_grouped_contents(contents, user_tags)
        return jsonify(groups)
    • 쓰기 (/api/survey 등) 핸들러에서 save_user_profile(user_id, new_profile) 을 호출하면,
      • 파일(DB)과 캐시를 동시에 갱신(Write-Through)
    • 읽기 (/api/recommend/contents) 핸들러에서는 load_user_profile() 를 통해 캐시 우선 로딩(Cache-Aside)

    • Write-Through: 쓰기 시점에 캐시도 함께 업데이트 → 항상 최신
    • Cache-Aside: 읽을 때 캐시 확인 → 없으면 로드 후 캐싱 → 읽기 속도 최적화

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions