본문 바로가기
AI_RSS_트래픽 프로젝트

모르는 상태로 하는 RSS&분석&RAG 프로젝트(18) 트러블슈팅2 analyze_time_lag

by chol_rang 2026. 1. 9.

시간차 분석 성능 최적화 (Time Lag Analysis Performance Optimization)

문제 상황

`analyze_time_lag` 명령어 실행 시 예상보다 훨씬 오래 걸리는 문제가 발생했습니다.

 

데이터 규모
- 뉴스 기사: 4,357개
- SNS 게시물: 469개
- 공통 키워드: 50개
- 총 게시물: 4,826개

 

원래 예상 시간
- 예상 시간: 약 3시간

 

 

원래 방식

def analyze_time_lag(keywords, days, ...):
    # 1. compare_platforms() 호출 → 모든 게시물 형태소 분석 (1회)
    comparison_result = compare_platforms(...)
    keywords = [item['keyword'] for item in comparison_result['common_keywords']]
    
    # 2. 각 키워드마다 get_keyword_occurrence_times() 호출
    for keyword in keywords:  # 50번 반복
        # 뉴스에서 등장 시간 추출
        news_times = get_keyword_occurrence_times(keyword, 'news', days, news_queryset)
        # → 모든 뉴스 기사(4,357개)를 다시 형태소 분석
        
        # SNS에서 등장 시간 추출
        sns_times = get_keyword_occurrence_times(keyword, 'sns', days, sns_queryset)
        # → 모든 SNS 게시물(469개)을 다시 형태소 분석

 

문제점

 

1. 중복 형태소 분석: 각 키워드마다 모든 게시물을 다시 형태소 분석
   - 50개 키워드 × 4,357개 게시물 = 217,850번 형태소 분석
   - 같은 게시물을 50번씩 반복 분석

2. 시간 복잡도: O(키워드 수 × 게시물 수 × 형태소 분석 시간)
   - 형태소 분석 시간: 게시물당 약 0.05초
   - 총 예상 시간: 217,850 × 0.05초 = 10,892초 = 약 3시간

3. 비효율적인 구조:
   - `compare_platforms()`에서 이미 모든 게시물을 형태소 분석했지만
   - 그 결과를 재사용하지 않고 다시 분석

 

최적화 방식

 

선택한 방법: 한 번만 형태소 분석하고 결과 재사용

def analyze_time_lag(keywords, days, ...):
    # 1단계: 모든 뉴스 기사를 한 번만 형태소 분석
    news_keywords_map = {}  # {article_id: [keyword1, keyword2, ...]}
    for article in news_queryset:
        text = extract_text_from_news_article(article)
        if text:
            keywords = analyzer.extract_keywords(text, ...)
            news_keywords_map[article.id] = keywords
    
    # 2단계: 모든 SNS 게시물을 한 번만 형태소 분석
    sns_keywords_map = {}  # {post_id: [keyword1, keyword2, ...]}
    for post in sns_queryset:
        text = extract_text_from_sns_post(post)
        if text:
            keywords = analyzer.extract_keywords(text, ...)
            sns_keywords_map[post.id] = keywords
    
    # 3단계: 각 키워드의 등장 시간을 메모리에서 빠르게 계산
    for keyword in keywords:
        # 뉴스에서 등장한 게시물 찾기 (메모리 조회)
        news_occurrences = [
            article.published_at 
            for article in news_queryset 
            if article.id in news_keywords_map 
            and keyword in news_keywords_map[article.id]
        ]
        
        # SNS에서 등장한 게시물 찾기 (메모리 조회)
        sns_occurrences = [
            post.published_at 
            for post in sns_queryset 
            if post.id in sns_keywords_map 
            and keyword in sns_keywords_map[post.id]
        ]
        
        # 최초 등장 시간 계산
        news_first = min(news_occurrences) if news_occurrences else None
        sns_first = min(sns_occurrences) if sns_occurrences else None

 


개선 사항

 

1. 형태소 분석 횟수: 241,300번 → 4,357번 (1회만)
2. 시간 복잡도: O(키워드 수 × 게시물 수) → O(게시물 수 + 키워드 수 × 게시물 수)
   - 형태소 분석: O(게시물 수) - 1회만
   - 키워드 검색: O(키워드 수 × 게시물 수) - 메모리 조회 (매우 빠름)


검색하며 알았던 다른 방법들

 

방법 1: 역색인(Inverted Index) 사용
아이디어: 키워드 → 게시물 ID 리스트 매핑 생성

keyword_to_news = defaultdict(list)   {keyword: [article_id1, article_id2, ...]}
keyword_to_sns = defaultdict(list)    {keyword: [post_id1, post_id2, ...]}

for article in news_articles:
    keywords = analyzer.extract_keywords(text)
    for keyword in keywords:
        keyword_to_news[keyword].append(article.id)

장점:
- 키워드 검색이 O(1)로 매우 빠름
- 메모리 효율적 (게시물 ID만 저장)

단점:
- 구현이 조금 더 복잡
- 키워드가 많을 경우 메모리 사용량 증가 가능

선택하지 않은 이유: 
- 현재 방식도 충분히 빠르고 구현이 더 간단함
- 메모리 사용량이 크게 차이 나지 않음

 

 

방법 2: compare_platforms() 결과 재사용
아이디어: `compare_platforms()`에서 이미 형태소 분석을 했으므로 그 결과를 재사용

 

장점:
- 중복 분석 완전 제거
- 기존 함수 재사용

단점:
- `compare_platforms()` 함수 시그니처 변경 필요
- 다른 곳에서 사용하는 코드에 영향 가능
- 함수 간 결합도 증가

선택하지 않은 이유:
- 함수 간 결합도를 높이고 싶지 않음
- `analyze_time_lag()` 내부에서 독립적으로 처리하는 것이 더 명확함

 


선택한 방법의 이유


 "한 번만 형태소 분석하고 결과 재사용" 방식을 선택한 이유

1. 구현 단순성   - 기존 함수 구조를 크게 변경하지 않음
   - `analyze_time_lag()` 함수 내부에서만 수정
   - 다른 함수에 영향 없음

2. 명확한 성능 개선   - 형태소 분석 횟수를 50배 감소 (241,300번 → 4,357번)
   - 메모리 조회는 매우 빠르므로 실질적인 병목 제거

3. 메모리 효율성   - 게시물당 키워드 리스트만 저장 (약 수십 KB)
   - 4,357개 게시물 × 평균 20개 키워드 = 약 100KB 정도
   - 현대 시스템에서 무시할 수 있는 수준

4. 유지보수 용이성   - 로직이 한 곳에 집중되어 이해하기 쉬움
   - 디버깅이 용이함

5. 확장성   - 키워드 수가 늘어나도 형태소 분석 횟수는 동일
   - 게시물 수가 늘어나면 선형적으로 증가 (예상 가능)

 


 성능 비교

항목  최적화 전 최적화 후 개선율
형태소 분석 횟수 241,300번 4,826번 99.0% 감소
예상 실행 시간 약 3시간 약 2분 내외 약 50배 빠름
시간 복잡도 O(n×m×k) O(n + m×k)  
메모리 사용량  낮음 약 100KB 추가 큰 차이없음

 

시간 복잡도에 대해서 간단하게 추가설명을 하자면 

 

수 의미:

  • n = 게시물 수 (4,826개)
  • m = 키워드 수 (50개)
  • k = 형태소 분석 시간 (게시물당 약 0.05초)

최적화 전: O(n × m × k)

의미: 각 키워드 마다 모든 게시물을 형태소 분석

        총 연산 = n × m = 4,826 × 50 = 241,300번 형태소 분석

       총 시간 = n * m * k = 4,826 * 50 * 0.05초 = 12,065초 ≈ 3.3시간

 

       O(n * m * k) = 각 키워드마다 모든 게시물을 형태소 분석

 

최적화 후: O(n + m × k)

의미:

  • 형태소 분석: 게시물 수만큼만 수행 (1회)
  • 키워드 검색: 키워드 수 × 게시물 수 (메모리 조회)
        1단계: 형태소 분석 = n = 4,826번 (한 번만)

2단계: 키워드 검색 = m * n = 50 × 4,826 = 241,300번 (메모리 조회)

      총 시간 = (n * 형태소_분석_시간) + (m * n * 메모리_조회_시간)
              = (4,826 * 0.05초) + (241,300 * 거의_0초)
              ≈ 4-5분


 

실제 측정 결과
- 최적화 전: 측정 불가 (너무 오래 걸려 30분 정도 시행 중 중단)
- 최적화 후: 약 2-3분
- 개선율: 약 99% 시간 단축 (3-4시간 → 2-3분)

 


최적화 결과

 

================================================================================
시간차 분석 시작
================================================================================
분석 기간: 최근 7일
[INFO] 2026-01-09 15:12:08,260 services PyKOMORAN 형태소 분석기 초기화 완료 (모델: STABLE)
[INFO] 2026-01-09 15:12:08,313 services 불용어 파일 로드 완료: 884개 단어 (C:\Users\vhtmx\OneDrive\바탕 화면\trend\analyzer\data\stopwords_ko.txt)
[INFO] 2026-01-09 15:12:59,803 services 뉴스 기사 분석 완료: 4357개 기사, 20551개 키워드
[INFO] 2026-01-09 15:13:01,731 services SNS 게시물 분석 완료: 469개 게시물, 2980개 키워드
[INFO] 2026-01-09 15:13:01,734 services 플랫폼 비교 분석 완료: 뉴스 4357개, SNS 469개, 공통 키워드 50개
[INFO] 2026-01-09 15:13:01,738 services 뉴스 기사 형태소 분석 시작: 4357개
[INFO] 2026-01-09 15:13:53,635 services SNS 게시물 형태소 분석 시작: 469개
[INFO] 2026-01-09 15:13:55,571 services 형태소 분석 완료. 키워드별 등장 시간 계산 시작
[INFO] 2026-01-09 15:13:55,610 services 시간차 분석 완료: 4개 키워드, 뉴스→SNS 4개, SNS→뉴스 0개

[실행 시간]
--------------------------------------------------------------------------------
⏱️  총 실행 시간: 108.75초 (1.81분)

[시간차 분석 통계]
--------------------------------------------------------------------------------
✅ 분석 완료: 4개 키워드
  - 뉴스 → SNS: 4개 (100.0%)
  - SNS → 뉴스: 0개 (0.0%)
  - 동시 등장: 0개
  - 뉴스 전용: 0개
  - SNS 전용: 0개

  - 뉴스 → SNS 평균 시간차: 81.22시간

[키워드별 분석 결과]
--------------------------------------------------------------------------------

📰 → 📱 뉴스 → SNS 전파:
   1. 지구촌                  시간차: 43.83시간 (뉴스: 2026-01-05 06:05, SNS: 2026-01-07 01:55)
   2. 일화                   시간차: 60.40시간 (뉴스: 2026-01-04 18:11, SNS: 2026-01-07 06:35)
   3. 안성기                  시간차: 109.71시간 (뉴스: 2026-01-02 17:27, SNS: 2026-01-07 07:10)
   4. 배우                   시간차: 110.94시간 (뉴스: 2026-01-02 16:13, SNS: 2026-01-07 07:10)

================================================================================
분석 완료
================================================================================