빈도수 계산 및 사이트 구축 설명

이 페이지에서는 이 사이트에서 사용하는 빈도율이 어떻게 계산되고, 사이트는 어떻게 구축되었는지에 대한 기술적인 설명을 합니다.

1. 원시 데이터 모으기

한글로 된 문장들이 있어야 합니다. 그것도 오랜 기간에 걸쳐 균일하게 얻을 수 있는. 그래야 거기서 단어들을 뽑아내고 빈도수를 세고 할 것입니다.

제가 선택한 방법은 신문에 있는 기사입니다.

신문 사이트에 있는 기사들에서 불필요한 정보들을 제거하고 순수 텍스트만을 얻어서 단어수를 셉니다.

시기는 1997년 1월 부터에 대한 자료을 모았습니다. 그 이전 데이터도 가능하긴 하나, 구할 수 없는 신문사도 있고 해서 일단 1997년 1월 1일부터를 기준으로 했습니다. 만약 데이터가 더 보강되면 이 시점은 더 과거로 갈 수 있습니다.

최신 데이터는 매월 기준으로 갱신합니다. 즉, 현재가 2025년 5월이면 4월까지의 데이터가 계산되어 그래프에 반영됩니다.

대상이되는 신문사는 일간지로, 총 10개의 신문사입니다. 2025.1월 부터는 이 10개 신문사의 매일 마다의 기사에서 단어만 추출해서 빈도수를 셉니다.

2. 단어 수 세기

선택되는 단어의 기준은, 형태소 분석에 의한 '명사' 혹은 '대명사'입니다. 명사/대명사/감탄사/부사/복합명사/영어 입니다.

텍스트로 된 신문 기사 문장에서 형태소 분석기를 통해 토큰을 뽑아낸 후 카운트를 합니다.

월별/일별로 모아진 모든 기사에서 토큰을 추출하고, 이 단어들이 몇 번 나왔는지 숫자를 세는 방식입니다.

3. 효율적인 데이터 구조 만들기

위 2번 과정에서 월별로 생성된 "단어, 빈도수"가 들어있는 파일들에서, 각 단어별로 24년 1월에는 몇 번, 2월에는 몇 번과 같은 데이터를 추출해서 DB화 해야합니다. 그래야, 사용자가 어떤 단어를 입력했을 때, 그 단어가 주어진 기간에 대해 얼마만큼의 빈도수를 나타내는지 출력할 수 있습니다.

처음 생각은 PostgreSQL 같은 DB를 써서 저장할 생각이었는데, 단어의 수가 너무 많고, 한 단어에 대해서 30년치면 30년 x 12개월 = 460개의 데이터가 있어야 하고, 시간이 흐를수록 데이터의 수가 많아져서, 테이블 설계와 쿼리 설계를 잘하지 않으면 데이터를 뽑아내는 데 너무 많은 시간이 소요될 것 같았습니다.

해서, 다른 방법을 쓰기로 맘 먹었습니다. 데이터 구조는 다음과 같습니다.

예를 들어, "바람"이라는 단어를 찾아야 한다면,

단어-빈도수 파일 구조

각 단어명으로 된 파일내에는 해당 단어의 각 "연도-월"에서의 빈도수 정보가 들어갑니다. 이 빈도수는 해당 월에서 모든 단어 횟수에 대한 ppm입니다. ppm은 백만분율로 1/1000000 입니다. 즉, 1ppm = 1/1000000 = 0.0001%

즉, 정확하게는 '빈도율'이라고 불려야 맞을 것입니다. 실제 나온 개수를 표시하는 것이 아니고, 모든 단어의 빈도수에 대한 상대적인 빈도수 비율인 것입니다.

예를 들어 "바람.csv"라는 파일에는 아래와 같은 정보가 들어가 있습니다. (예시입니다. 정확한 숫자는 아닙니다.)

199701, 34
199702, 50
199706, 10
...
    

단어-빈도수 파일 생성 방법

매 월마다 해당 월의 모든 기사에서 단어를 뽑아내고, 각 단어마다의 해당 월에서의 빈도수 ppm을 계산해서 하나의 파일로 만듭니다.

이 파일에 있는 모든 단어와 빈도수 정보를 가지고, 각 단어에 대한 "단어-빈도수" 파일을 찾아서, 해당 월에 해당하는 정보를 갱신하는 구조입니다.

이 작업은 대략 10분 정도 소요됩니다. Rust로 프로그램해서 비동기적으로 매우 빠르게 진행되나, 한 달에 뽑아지는 단어수가 20~30만개 정도 되고, 이 숫자만큼의 파일에 대해 갱신을 해야 해서, 10분 정도 소요됩니다. 파이썬으로 짰으면 아마도 30분 이상 소요될 것입니다.

4. 웹 서버 구축하기

웹 서버용 하드웨어

웹 서버용 인스턴스는 AWS의 Lightsail을 사용합니다.

월 $12면 1년이면 120달러이고, 요즘 환율이 높아져서 좀 아깝다는 생각이 들긴 하고 있습니다.

웹서버 프레임워크

웹 서버 프로그램은 Rust의 Axum 패키지를 써서 직접 프로그램을 짰습니다.

웹 서버 및 뒷 단에서 단어에 대한 빈도수 데이터를 가지고 오고 JSON으로 만드는 모든 과정을 순수 Rust로 짰습니다. 해서, 속도가 매우 빠르고 안정적입니다. ^^

실제 서버에서 파일을 찾고 JSON 데이터를 만드는 작업은 몇 ms에 이루어지고, 실제 소요되는 대부분의 시간은 브라우저와 서버 사이의 네트웍 속도만 걸립니다.

테스트를 해보니, 4개 단어에 대한 요청을 연속으로 했을 때, 모두 100ms~200ms 안에 화면 출력까지 이루어집니다.

5. 웹 페이지 만들기

앞의 과정은 모두 쉬운데, 저에게는 웹 페이지 만드는 것이 힘이 듭니다. HTML을 만드는 것까진 좋은데, 이것을 그래도 좀 볼 만하게 만드는 것이 고역입니다.

저번에는 Django로 웹 서버를 구축할 때는, Vue.js를 써서 어떻게든 꾸역꾸역 만든 적이 있는데, 이번에도 그렇게 할까 하다가, 표출할 내용이 단일 페이지면 족할 것이기에, 그냥 HTML과 CSS와 순수 Javascript만으로도 충분할 듯해서 그렇게 작성을 했습니다.

더군다나, VS Code에서 GitHub의 Copilot와 연동해 놨더니, HTML 페이지의 골격만 만드니, Copilot이 나머지 대부분의 CSS를 자동으로 만들어줘서 편하게 만들었습니다. 이제는 혼자서도 Frontend와 Backend 단을 만들 수 있는 시대가 되었습니다.


* 문의 사항이 있으시면, p14jeffwest@gmail.com으로 연락 주시기 바랍니다.