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

모르는 상태로 하는 RSS&분석&RAG 프로젝트(16) 크로스 플랫폼 키워드 추출 및 빈도 분석

by chol_rang 2026. 1. 2.

이번 글에는 이전 글에서 작성했던

"크로스 플랫폼 키워드 추출"

에 대해서 완성하고 어떤식으로 돌아가는지 어떤 로직을 통해 동작하는지에 대해서 간단하게 정리하면서 

나도 더 기억할 수 있게끔 작성해보도록 할 예정이다. 

 

먼저 우리가 만든 프로젝트는 News의 RSS와 SNS(DCinside, Reddit)의 RSS,Scraping으로 수집된 article,post들을 분석 후 대시보드에 내보내서 결과적으로는 수집된 글과 함께 분석이 완료되어 News,SNS의 관계도 함께 볼 수 있는 웹 페이지를 만들고 있다.

 

그래서 현재까지는 news랑 sns의 글들을 수집하고 있었고 키워드 추출과 플랫폼별 비교 분석을 간단하게 완성해서 

어떤식으로 동작하는지 알아보기 위해 글을 작성한다.

 

 

전체적인 실행 흐름은 아래와 같다.

[1단계] 데이터 수집 및 전처리 

[2단계] 형태소 분석 및 키워드 추출 (뉴스/SNS 각각) 

[3단계] 빈도 계산 및 정규화 

[4단계] 플랫폼 비교 분석 

결과 출력

 

services.py에 작성한 내용을 조금 풀어서 설명 및 이해 해보도록하겠다.

 

[1단계] 데이터 수집 및 전처리

def analyze_news_articles(
    queryset=None,
    days: int = 7,
    min_length: int = 2,
    exclude_stopwords: bool = True,
    top_n: Optional[int] = None
) -> Dict[str, any]:

와 

def analyze_sns_posts(
    queryset=None,
    days: int = 7,
    min_length: int = 2,
    exclude_stopwords: bool = True,
    top_n: Optional[int] = None
) -> Dict[str, any]:

위의 두 함수로 데이터 수집 및 전처리를 진행한다. 

 

 

    if queryset is None:
        start_date = timezone.now() - timedelta(days=days)
        queryset = NewsArticle(or SocialMediaPost).objects.filter(
            published_at__gte=start_date
        )

의 로직으로 queryset을 NewsArticle,SocialMediaPost 의 DB 데이터를 조회하고 

 

texts = []
for article in news_queryset:
    text = article.title + " " + article.description  # 뉴스
    # 또는
    text = post.title + " " + post.content  # SNS
    texts.append(text)

위의 로직으로 텍스트들을 빈 텍스트를 제외하여 추출한다. 

 

[2단계] 형태소 분석 및 키워드 추출 (뉴스/SNS 각각) 

형태소 분석 및 키워드 추출의 경우 java언어의 분석기인 komoran을 python에서 사용할 수 있게 만든 pykomoran을 사용하여 

입력값을 분석하였다. 

 

# 텍스트 분석
result = komoran.get_plain_text("대한민국은 민주공화국이다")
# 결과: "대한민국/NNP 은/JX 민주공화국/NNG 이/VCP 다/EF ./SF"

# 형태소-품사 쌍으로 파싱
morphemes = []
for item in result.split():
    morph, pos = item.rsplit('/', 1)
    morphemes.append((morph, pos))
# 결과: [('대한민국', 'NNP'), ('은', 'JX'), ('민주공화국', 'NNG'), ...]

 

위의 내용처럼 입력값을 하나하나 분석한것들 중 명사 품사인 NNP(고유명사), NNG(일반명사), NNB(의존명사), NNBC(단위명사)

만 필터링 하고 최소 2글자 이상만 가지고 올 수 있도록 필터링을 걸었다. 

 

또한, 불용어( 문장을 분석하는데 큰 의미가 없는 문자열 ) 제거를 하기 위해 검색 한 뒤

https://gist.github.com/spikeekips/40eea22ef4a89f629abd87eed535ac6a?permalink_comment_id=5140281

 

Korean Stopwords

Korean Stopwords. GitHub Gist: instantly share code, notes, and snippets.

gist.github.com

의 내용을 복사하여 새로운 파일에 넣고 SNS 특성 상 문장을 분석하는데 큰 의미가 없는 문자들

예를들어, 커뮤니티 용어들인 "대박", "헐 ㅋㅋ", "ㅋㅋㅋ" "ㄹㅇㅋㅋ" 등등

을 더 추가하여 총 880여개의 불용어 리스트를 만들고 가지고온 명사들중에 불용어가 있으면 제거하도록 했다. 

 

이것들을 전체 텍스트에 적용하여 확인하였더니 결과가 아래와같이 나왔다. 

all_keywords = []
for text in texts:  # 2,967개 뉴스 텍스트
    keywords = analyzer.extract_keywords(text)
    all_keywords.extend(keywords)

# 결과:
# 뉴스: 17,755개 키워드 (중복 포함)
# SNS: 2,072개 키워드 (중복 포함)


최종 결과:
- 뉴스: 17,755개 키워드 추출 → 130개 고유 키워드 (중복 제거 전)
- SNS: 2,072개 키워드 추출 → 191개 고유 키워드 (중복 제거 전)

 

[3단계] 빈도 계산 및 정규화 

위와 같이 결과가 나온 이유는 당연히 News가 더 많이 수집되어 text가 더 많아서 생긴 이슈이다.

 

이렇게 글자체의 갯수차이가 많이 난다면 빈도계산을 할 경우 어떤 명사들이 들어가도 News가 압도적으로 많이 나올수 밖에없는 구조가 형성되어 이것을 해결하기 위해 간단한 정규식을 적용해 진행했다.

 

일단 먼저 모든 키워드 들을 하나의 리스트로 만들고 Counter로 빈도 계산을 했다.

결과는 아래와 같다.

"달러": 282회 (뉴스), 33회 (SNS)"
서울": 1,227회 (뉴스), 13회 (SNS)
"대통령": 1,139회 (뉴스), 14회 (SNS)

 

이렇게 하나의 키워드 들을 볼때 post가 많은 News에서 훨씬 더 많은 빈도 수를 가지고 있기에 

#frequency = 모든 키워드들을 Counter로 계산한 결과 = Counter(all_keywords)
def normalize_frequency(frequency):
    # 전체 키워드 수 계산
    total = sum(frequency.values())
    # 뉴스: 257,000개 (전체 키워드 합계)
    # SNS: 4,600개 (전체 키워드 합계)
    
    # 상대 빈도 계산
    normalized = {}
    for word, count in frequency.items():
        normalized[word] = count / total
    
    return normalized

#아래는 계산 예시
# 뉴스 "달러"
absolute = 282
total_news = 257000  # 전체 키워드 수
normalized = 282 / 257000 = 0.001097 ≈ 0.0011 (0.11%)

# SNS "달러"
absolute = 33
total_sns = 4600  # 전체 키워드 수
normalized = 33 / 4600 = 0.007174 ≈ 0.0073 (0.73%)

결과적으로는

"달러" 라는 단어가 당연히 뉴스에서 더 많이 나왔지만 전체 키워드에서의 비중은 더 SNS가 훨씬 높다는 결과가 나왔다. 

 

[4단계] 플랫폼 비교 분석

최소 빈도(0.01)를 제외한 키워드들을 가지고 교집합과 차집합을 구해 각 플랫폼별 비교도 해보았다.

# 집합 교집합 연산
news_keywords_set = set(news_filtered.keys())
sns_keywords_set = set(sns_filtered.keys())

common_keywords_set = news_keywords_set & sns_keywords_set
# 결과: OO개 공통 키워드

# 결과
news_set = {'달러', '서울', '대통령', '언론', '정부', ...}
sns_set = {'달러', '서울', '대통령', '갤러리', '원본', ...}
common = {'달러', '서울', '대통령', ...}  # 50개

이거 뿐만 아니라 공통 키워드 비교 리스트를 만들어 

common_keywords = []

for keyword in common_keywords_set:
    news_freq = news_filtered[keyword]
    sns_freq = sns_filtered[keyword]
    
    # 차이 계산 (SNS - 뉴스)
    diff = sns_freq - news_freq
    # 양수면 SNS가 더 높음, 음수면 뉴스가 더 높음
    
    # 절대 빈도도 함께 저장
    news_abs = absolute_freq_news[keyword]
    sns_abs = absolute_freq_sns[keyword]
    
    common_keywords.append({
        'keyword': keyword,
        'news_frequency': news_freq,  # 상대 빈도
        'sns_frequency': sns_freq,    # 상대 빈도
        'difference': diff,
        'news_absolute': news_abs,    # 절대 빈도
        'sns_absolute': sns_abs       # 절대 빈도
    })

# 결과 
{
    'keyword': '달러',
    'news_frequency': 0.0011,  # 상대 빈도 0.11%
    'sns_frequency': 0.0073,   # 상대 빈도 0.73%
    'difference': 0.0062,      # SNS가 더 높음
    'news_absolute': 282,      # 절대 빈도 282회
    'sns_absolute': 33         # 절대 빈도 33회

상위 50개만 가지고 와서 정렬하도록 했다.

 

차집합도 비슷하게 진행했다.

# 뉴스에만 있는 키워드 (차집합)
news_only = {
    k: v for k, v in news_filtered.items()
    if k not in sns_filtered
}

# SNS에만 있는 키워드 (차집합)
sns_only = {
    k: v for k, v in sns_filtered.items()
    if k not in news_filtered

 

그 결과 전체적인 결과가 나온걸 확인했다.

 

분석 기간: 최근 7일
상위 키워드: 50개


[플랫폼 비교 분석]
--------------------------------------------------------------------------------
[INFO] 2026-01-02 14:31:07,414 services PyKOMORAN 형태소 분석기 초기화 완료 (모델: STABLE)
[INFO] 2026-01-02 14:31:07,438 services 불용어 파일 로드 완료: 884개 단어 (C:\Users\vhtmx\OneDrive\바탕 화면\trend\analyzer\data\stopwords_ko.txt)
[INFO] 2026-01-02 14:31:44,218 services 뉴스 기사 분석 완료: 2967개 기사, 17755개 키워드
[INFO] 2026-01-02 14:31:45,238 services SNS 게시물 분석 완료: 267개 게시물, 2072개 키워드
[INFO] 2026-01-02 14:31:45,241 services 플랫폼 비교 분석 완료: 뉴스 2967개, SNS 267개, 공통 키워드 50개
✅ 분석 완료:
  - 뉴스: 2967개 기사, 130개 키워드
  - SNS: 267개 게시물, 191개 키워드
  - 공통 키워드: 50개

공통 키워드 비교:
   1. 달러
      뉴스: 0.0011 (0.11%) [282회]
      SNS:  0.0073 (0.73%) [33회]
      차이: +0.0062 (SNS가 더 높음)
   2. 서울
      뉴스: 0.0048 (0.48%) [1227회]
      SNS:  0.0029 (0.29%) [13회]
      차이: -0.0019 (뉴스가 더 높음)
   3. 대통령
      뉴스: 0.0044 (0.44%) [1139회]
      SNS:  0.0031 (0.31%) [14회]
      차이: -0.0013 (뉴스가 더 높음)
   4. 대표
      뉴스: 0.0030 (0.30%) [779회]
      SNS:  0.0044 (0.44%) [20회]
      차이: +0.0014 (SNS가 더 높음)
   5. 사람
      뉴스: 0.0016 (0.16%) [398회]
      SNS:  0.0055 (0.55%) [25회]
      차이: +0.0040 (SNS가 더 높음)
   6. 의혹
      뉴스: 0.0016 (0.16%) [399회]
      SNS:  0.0053 (0.53%) [24회]
      차이: +0.0038 (SNS가 더 높음)
   7. 기자
      뉴스: 0.0047 (0.47%) [1206회]
      SNS:  0.0020 (0.20%) [9회]
      차이: -0.0027 (뉴스가 더 높음)
   8. 관련
      뉴스: 0.0022 (0.22%) [562회]
      SNS:  0.0044 (0.44%) [20회]
      차이: +0.0022 (SNS가 더 높음)
   9. 이재명
      뉴스: 0.0014 (0.14%) [346회]
      SNS:  0.0042 (0.42%) [19회]
      차이: +0.0029 (SNS가 더 높음)
  10. 미국
      뉴스: 0.0024 (0.24%) [623회]
      SNS:  0.0031 (0.31%) [14회]
      차이: +0.0007 (SNS가 더 높음)
  11. 한국
      뉴스: 0.0027 (0.27%) [702회]
      SNS:  0.0027 (0.27%) [12회]
      차이: -0.0001 (뉴스가 더 높음)
  12. 문제
      뉴스: 0.0016 (0.16%) [400회]
      SNS:  0.0033 (0.33%) [15회]
      차이: +0.0018 (SNS가 더 높음)
  13. 기업
      뉴스: 0.0028 (0.28%) [728회]
      SNS:  0.0020 (0.20%) [9회]
      차이: -0.0009 (뉴스가 더 높음)
  14. 조사
      뉴스: 0.0021 (0.21%) [550회]
      SNS:  0.0027 (0.27%) [12회]
      차이: +0.0005 (SNS가 더 높음)
  15. 평가
      뉴스: 0.0016 (0.16%) [407회]
      SNS:  0.0031 (0.31%) [14회]
      차이: +0.0015 (SNS가 더 높음)
  16. 의원
      뉴스: 0.0026 (0.26%) [676회]
      SNS:  0.0018 (0.18%) [8회]
      차이: -0.0009 (뉴스가 더 높음)
  17. 지역
      뉴스: 0.0031 (0.31%) [786회]
      SNS:  0.0013 (0.13%) [6회]
      차이: -0.0017 (뉴스가 더 높음)
  18. 민주당
      뉴스: 0.0015 (0.15%) [388회]
      SNS:  0.0029 (0.29%) [13회]
      차이: +0.0014 (SNS가 더 높음)
  19. 국민
      뉴스: 0.0033 (0.33%) [836회]
      SNS:  0.0011 (0.11%) [5회]
      차이: -0.0022 (뉴스가 더 높음)
  20. 올해
      뉴스: 0.0024 (0.24%) [607회]
      SNS:  0.0020 (0.20%) [9회]
      차이: -0.0004 (뉴스가 더 높음)
  21. 시작
      뉴스: 0.0013 (0.13%) [345회]
      SNS:  0.0029 (0.29%) [13회]
      차이: +0.0015 (SNS가 더 높음)
  22. 개발
      뉴스: 0.0011 (0.11%) [269회]
      SNS:  0.0031 (0.31%) [14회]
      차이: +0.0020 (SNS가 더 높음)
  23. 이후
      뉴스: 0.0021 (0.21%) [534회]
      SNS:  0.0020 (0.20%) [9회]
      차이: -0.0001 (뉴스가 더 높음)
  24. 기준
      뉴스: 0.0015 (0.15%) [382회]
      SNS:  0.0024 (0.24%) [11회]
      차이: +0.0009 (SNS가 더 높음)
  25. 공개
      뉴스: 0.0018 (0.18%) [461회]
      SNS:  0.0020 (0.20%) [9회]
      차이: +0.0002 (SNS가 더 높음)
  26. 내년
      뉴스: 0.0022 (0.22%) [565회]
      SNS:  0.0015 (0.15%) [7회]
      차이: -0.0007 (뉴스가 더 높음)
  27. 장관
      뉴스: 0.0015 (0.15%) [381회]
      SNS:  0.0022 (0.22%) [10회]
      차이: +0.0007 (SNS가 더 높음)
  28. 시장
      뉴스: 0.0022 (0.22%) [551회]
      SNS:  0.0015 (0.15%) [7회]
      차이: -0.0006 (뉴스가 더 높음)
  29. 사업
      뉴스: 0.0025 (0.25%) [638회]
      SNS:  0.0011 (0.11%) [5회]
      차이: -0.0014 (뉴스가 더 높음)
  30. 투자
      뉴스: 0.0016 (0.16%) [408회]
      SNS:  0.0020 (0.20%) [9회]
      차이: +0.0004 (SNS가 더 높음)
  31. 가능
      뉴스: 0.0011 (0.11%) [286회]
      SNS:  0.0024 (0.24%) [11회]
      차이: +0.0013 (SNS가 더 높음)
  32. 정보
      뉴스: 0.0022 (0.22%) [566회]
      SNS:  0.0013 (0.13%) [6회]
      차이: -0.0009 (뉴스가 더 높음)
  33. 청와대
      뉴스: 0.0011 (0.11%) [275회]
      SNS:  0.0024 (0.24%) [11회]
      차이: +0.0014 (SNS가 더 높음)
  34. 결과
      뉴스: 0.0020 (0.20%) [513회]
      SNS:  0.0013 (0.13%) [6회]
      차이: -0.0007 (뉴스가 더 높음)
  35. 국내
      뉴스: 0.0015 (0.15%) [397회]
      SNS:  0.0018 (0.18%) [8회]
      차이: +0.0002 (SNS가 더 높음)
  36. 수사
      뉴스: 0.0022 (0.22%) [563회]
      SNS:  0.0011 (0.11%) [5회]
      차이: -0.0011 (뉴스가 더 높음)
  37. 경우
      뉴스: 0.0013 (0.13%) [326회]
      SNS:  0.0020 (0.20%) [9회]
      차이: +0.0007 (SNS가 더 높음)
  38. 계획
      뉴스: 0.0017 (0.17%) [431회]
      SNS:  0.0015 (0.15%) [7회]
      차이: -0.0001 (뉴스가 더 높음)
  39. 경찰
      뉴스: 0.0014 (0.14%) [371회]
      SNS:  0.0018 (0.18%) [8회]
      차이: +0.0003 (SNS가 더 높음)
  40. 기록
      뉴스: 0.0016 (0.16%) [413회]
      SNS:  0.0015 (0.15%) [7회]
      차이: -0.0001 (뉴스가 더 높음)
  41. 최고
      뉴스: 0.0012 (0.12%) [299회]
      SNS:  0.0020 (0.20%) [9회]
      차이: +0.0008 (SNS가 더 높음)
  42. 정치
      뉴스: 0.0012 (0.12%) [297회]
      SNS:  0.0020 (0.20%) [9회]
      차이: +0.0008 (SNS가 더 높음)
  43. 개인
      뉴스: 0.0015 (0.15%) [396회]
      SNS:  0.0015 (0.15%) [7회]
      차이: +0.0000 (SNS가 더 높음)
  44. 발표
      뉴스: 0.0015 (0.15%) [396회]
      SNS:  0.0015 (0.15%) [7회]
      차이: +0.0000 (SNS가 더 높음)
  45. 개월
      뉴스: 0.0010 (0.10%) [265회]
      SNS:  0.0020 (0.20%) [9회]
      차이: +0.0010 (SNS가 더 높음)
  46. 상황
      뉴스: 0.0014 (0.14%) [371회]
      SNS:  0.0015 (0.15%) [7회]
      차이: +0.0001 (SNS가 더 높음)
  47. 제공
      뉴스: 0.0017 (0.17%) [446회]
      SNS:  0.0011 (0.11%) [5회]
      차이: -0.0006 (뉴스가 더 높음)
  48. 안전
      뉴스: 0.0017 (0.17%) [442회]
      SNS:  0.0011 (0.11%) [5회]
      차이: -0.0006 (뉴스가 더 높음)
  49. 사고
      뉴스: 0.0014 (0.14%) [365회]
      SNS:  0.0013 (0.13%) [6회]
      차이: -0.0001 (뉴스가 더 높음)
  50. 트럼프
      뉴스: 0.0012 (0.12%) [303회]
      SNS:  0.0015 (0.15%) [7회]
      차이: +0.0004 (SNS가 더 높음)

뉴스에만 있는 키워드 (상위 10개):
   1. 언론                   0.0030 (0.30%)
   2. 정부                   0.0029 (0.29%)
   3. 특검                   0.0027 (0.27%)
   4. 공감                   0.0026 (0.26%)
   5. 지원                   0.0024 (0.24%)
   6. 이날                   0.0021 (0.21%)
   7. 진행                   0.0020 (0.20%)
   8. 국가                   0.0020 (0.20%)
   9. 대상                   0.0020 (0.20%)
  10. 경제                   0.0019 (0.19%)

SNS에만 있는 키워드 (상위 10개):
   1. 김병기                  0.0055 (0.55%)
   2. 생각                   0.0055 (0.55%)
   3. 때문                   0.0046 (0.46%)
   4. 환율                   0.0044 (0.44%)
   5. 남편                   0.0044 (0.44%)
   6. 논문                   0.0042 (0.42%)
   7. 심사                   0.0042 (0.42%)
   8. 우크라이나                0.0040 (0.40%)
   9. 허드슨                  0.0038 (0.38%)
   6. 논문                   0.0042 (0.42%)
   7. 심사                   0.0042 (0.42%)
   8. 우크라이나                0.0040 (0.40%)
   9. 허드슨                  0.0038 (0.38%)
   9. 허드슨                  0.0038 (0.38%)
  10. 이유                   0.0035 (0.35%)

 

이로써 키워드 분석 및 비교분석까지 해보았고 이 비교분석과는 별개로 다른 분석들도 진행하여 정리해서 대시보드에 잘 나타나게끔 해보겠다.

 

만들때 ai의 도움을 많이 받았고 순조롭게 되진않았지만 그래도 결과를 한번 보니 생각보다 재밌다.