이 페이지에서는 KWord 2.0의 빈도율이 어떻게 계산되고, 사이트는 어떻게 구축되었는지에 대한 기술적인 설명을 합니다. 전체 흐름은 이렇습니다.
신문 기사 원문(zip) → madi 형태소 분석 → 날짜별 1~5-gram 횟수(Parquet) → 남길 어구 고르기 → SQLite DB → 웹 서버
한글로 된 문장들이 오랜 기간에 걸쳐 균일하게 있어야 합니다. 제가 선택한 것은 신문 기사입니다. 2.0에서는 1990년 1월까지 거슬러 올라갔습니다.
| 기간 | 원문 | 기사 수 |
|---|---|---|
| 1990.01 ~ 2015.12 | 조선일보 아카이브 (1996년 6~12월은 본문이 거의 없음) | 1,247,124 |
| 1996.10 ~ 2019.12 | 동아일보 아카이브 | 948,457 |
| 2020.01 ~ 2024.12 | 네이버 뉴스 지면 기사: 종합일간지 10개사(국민·동아·문화·세계·조선·중앙·한겨레·경향·서울·한국) | 1,261,999 |
| 2025.01 ~ 2026.09 | 네이버 뉴스 지면 기사: 위 10개사 + 매일경제·서울경제·한국경제·헤럴드경제·아시아경제·디지털타임스·전자신문 | 677,997 |
| 2026.10 ~ | 네이버 뉴스 지면 기사, 매일 자동 수집 | 매주 늘어남 |
기사에서 HTML 태그를 벗기고, 기자 이름·이메일 줄, 사진 설명, "관련 기사" 줄, 저작권 문구 같은 상투적인 문장은 규칙으로 걸러 냅니다. 네이버 기사는 이런 줄이 많아서 문장의 약 19%가 걸러집니다. 너무 짧은 문장(5글자 미만)도 버립니다.
1.0에서는 Okt와 Kiwi를 썼는데, 2.0에서는 형태소 분석기를 직접 만들었습니다. 이름은 madi(마디)입니다.
예를 들어 "국회의원들이 말했다"는 다음처럼 나뉩니다.
국회/NNG 의원/NNG 들/XSN 이/JKS 말/NNG 하/XSV 았/EP 다/EF
madi는 학습 말뭉치를 따라 복합명사를 나누어 분석합니다("국회의원" → "국회 의원"). 그래서 검색할 때는 이어 붙인 형태와 나눈 형태를 함께 찾습니다(아래 6번).
분석기의 버전이 바뀌면 빈도도 달라지므로, DB에는 그 DB를 만든 분석기 버전(0.1.0-kword3+dee5d…)을 적어 두고, 서버가 검색어를 분석하는 분석기와 같은지 확인합니다.
분석 결과의 형태/품사 하나가 단위입니다. 이것을 한 개(1-gram)부터 다섯 개(5-gram)까지 이어서 날짜별로 셉니다.
36년치를 이렇게 세면 서로 다른 어구가 수십억 가지가 나옵니다. 그래서 DB에는 다음 것만 남깁니다.
| 길이 | 남기는 기준 | 개수 |
|---|---|---|
| 1-gram | 전부 | 2,873,350 |
| 2-gram | 전 기간 20회 이상. 단, 체언+접미사(성장/NNG 률/XSN), 체언+하다(말/NNG 하/XSV)는 횟수와 관계없이 | 2,595,170 |
| 3-gram | 전 기간 40회 이상 | 2,693,129 |
| 4-gram | 전 기간 40회 이상 | 2,201,686 |
| 5-gram | 전 기간 40회 이상 | 1,386,619 |
2~5-gram은 먼저 해마다 1번만 나온 것을 버리고 나서 전 기간을 합칩니다(계산량 때문). 2026년 10월 이후에 새로 기준을 넘은 어구는 주간 갱신 때 더해집니다.
빈도율은 실제 횟수가 아니라, 그 기간에 나온 같은 길이 n-gram 전체에 대한 비율입니다.
빈도율(ppm) = 그 달(그 날)의 그 어구 횟수 × 1,000,000 / 그 달(그 날)의 같은 길이 n-gram 전체 횟수
madi는 "말했다"를 말/NNG 하/XSV 았/EP 다/EF로 나눕니다. 그대로 "말"을 세면 "말하다"의 '말'까지 들어가 버립니다. "생각"에 "생각하다"가, "공부"에 "공부하다"가 들어가는 것도 마찬가지입니다.
그래서 명사 하나를 검색하면 기본으로 다음처럼 계산합니다.
"말" = 말/NNG − 말/NNG 하/XSV(말하다) − 말/NNG 하/XSA
검색 화면의 '-하다 포함'을 체크하면 빼지 않고 함께 셉니다. "말하다"를 따로 보고 싶으면 "말하다"를 검색하면 됩니다.
입력한 검색어도 서버에서 madi로 분석해서, 기사를 셀 때와 같은 형태소 키로 바꿉니다.
1.0에서는 "단어 하나에 파일 하나" 구조를 직접 만들어 썼습니다. 단어 300만 개까지는 그걸로 됐는데, 어구 1,175만 개와 일별 자료까지 넣으려니 감당이 안 돼서 2.0에서는 SQLite를 씁니다.
| 표 | 내용 |
|---|---|
| ngram | 어구 번호, 길이(n), 형태소 키, 전체 횟수 |
| monthly | 어구별 월 횟수 (1990년부터 전 기간, 약 7.9억 행) |
| daily | 어구별 일 횟수 (올해 기준 2년 전 1월 1일부터, 약 4.3억 행) |
| day_total | 날짜별 n-gram 전체 횟수(빈도율의 분모), 기사·문장 수 |
| article, ngram_news | 기사 제목·링크, 단어별로 그 단어가 많이 나온 기사 (그래프 점 더블클릭) |
해가 바뀌면 일별 자료의 시작이 한 해 뒤로 옮겨 가고, 그 전 일별 자료는 지웁니다(월별 자료는 그대로 남습니다).
2026년 10월부터는 집에 있는 Ubuntu 랩탑이 자동으로 합니다.
표출할 내용이 단일 페이지면 족할 것이기에, HTML과 CSS와 순수 Javascript, 그리고 그래프는 Chart.js로 만들었습니다. 1.0 때처럼 이번에도 AI의 도움을 많이 받았습니다.
* 이 문서는 2026년 10월 기준으로 작성되었습니다. 문의: p14jeffwest@gmail.com