사전 형태소 분석
알고리즘

형태소 분석

gabury1고친 사람 github-actions[bot]

형태소 분석은 문장을 뜻을 가진 가장 작은 말 조각으로 나누는 일입니다. 나눈 조각마다 명사인지 조사인지 이름표도 붙여 줍니다. 한국어 검색 엔진은 이 일로 「한강을」에서 「한강」만 골라냅니다. 그래야 「한강」으로 찾을 때 그 글이 걸립니다.

쉽고 빠른 이해

무슨 일을 하나 — 문장을 넣으면 말 조각 목록을 돌려줍니다. 「동생이 책을 읽는다」를 넣으면 「동생 · 이 · 책 · 을 · 읽 · 는다」가 나옵니다. 조각마다 명사 · 조사 · 동사 같은 이름표가 붙습니다.

왜 필요한가 — 한국어는 낱말 끝에 조사와 어미가 붙어 모양이 자꾸 바뀝니다. 띄어쓰기로만 자르면 「한강을」과 「한강에서」가 서로 다른 낱말이 됩니다. 그러면 「한강」으로 찾아도 둘 다 안 걸립니다.

어떻게 도나

  1. 사전을 보고 문장 속에서 낱말이 될 수 있는 조각을 전부 찾습니다
  2. 그 조각들을 이어 문장 처음부터 끝까지 가는 풀이를 여럿 만듭니다
  3. 어떤 조각이 어떤 조각 뒤에 흔히 오는지까지 따져 풀이 하나를 고릅니다

대가 — 사전에 없는 새 낱말은 엉뚱하게 자릅니다. 새 낱말이 생길 때마다 사전을 손봐야 합니다. 새 낱말이 많아 하나도 놓치면 안 되는 곳에서는 글자를 겹쳐 자르는 n-gram 을 대신 씁니다.

상세

이 절은 먼저 형태소와 품사가 무엇인지 봅니다. 그다음 「나는」 두 글자가 문장마다 다르게 풀리는 예를 봅니다. 형태소 분석이 그중 하나를 어떻게 고르는지도 따라갑니다.

뒤쪽 소절들은 검색 엔진 안에서 이 일이 어디에 끼는지 봅니다. 끝으로 형태소 분석 없이 글자를 겹쳐 자르는 방법, 다른 언어에서 쓰는 방법과 견줍니다.

형태소

형태소는 뜻을 가진 가장 작은 말 단위입니다. 더 쪼개면 뜻이 사라집니다. 「바다를」은 「바다」와 「를」 두 형태소로 되어 있습니다.

「를」은 혼자서는 쓰이지 못합니다. 그래도 앞말이 목적어라는 뜻을 싣고 있습니다. 그래서 「를」도 형태소 하나로 칩니다.

「를」처럼 명사 뒤에 붙어 문장 속 역할을 알려 주는 말을 조사라고 합니다. 「가」 · 「를」 · 「에서」가 모두 조사입니다.

동사 끝에 붙어 때와 말투를 바꾸는 말은 어미라고 합니다. 「었」 · 「다」 · 「어서」가 어미입니다. 한국어 낱말은 조사와 어미가 붙으면서 모양이 계속 바뀝니다.

같은 「바다」도 「바다가」 · 「바다를」 · 「바다에서」로 적힙니다. 띄어쓰기로만 자르면 이 셋이 서로 다른 낱말이 됩니다. 형태소 분석이 필요한 까닭이 이것입니다.

품사 태그

형태소 분석은 조각을 나누는 데서 끝나지 않습니다. 조각마다 명사 · 조사 · 동사 · 어미 같은 품사를 붙입니다. 이렇게 붙인 품사 이름표를 품사 태그라고 부릅니다.

품사 태그가 있어야 뒤 단계가 조각을 골라 쓸 수 있습니다. 검색 엔진은 명사와 동사처럼 뜻을 지는 조각만 남깁니다. 조사와 어미는 버립니다. 어느 조각이 조사인지 모르면 버릴 것을 못 고릅니다.

원래 모양 되살리기

「달렸다」를 글자 단위로 들여다보면 「달리」가 없습니다. 동사 「달리」와 지난 일을 나타내는 어미 「었」이 합쳐져 「렸」 한 글자가 됐기 때문입니다. 형태소 분석은 이것을 「달리 · 었 · 다」로 되돌립니다.

그래서 형태소 분석은 글자를 자르기만 하는 일이 아닙니다. 합쳐지거나 모양이 바뀐 조각을 원래 모양으로 되살립니다. 이 덕분에 「달리다」 · 「달렸다」 · 「달려서」가 모두 같은 「달리」로 모입니다.

같은 글자의 다른 풀이

「나는」 두 글자는 문장에 따라 전혀 다르게 풀립니다. 아래 두 결과는 형태소 분석이 내놓는 모양을 흉내 낸 것입니다. 오른쪽 주석이 각 조각의 품사입니다.

「나는 학교에 간다」를 넣으면 이렇게 나옵니다.

나    // 대명사
는    // 조사
학교  // 명사
에    // 조사
가    // 동사
ㄴ다  // 어미

이 문장의 「나는」은 말하는 사람 「나」에 조사 「는」이 붙은 것입니다. 「간다」도 동사 「가」와 어미 「ㄴ다」로 나뉘었습니다.

「하늘을 나는 새」를 넣으면 이렇게 나옵니다.

하늘  // 명사
을    // 조사
날    // 동사
는    // 어미
새    // 명사

이 문장의 「나는」은 동사 「날다」입니다. 「날」은 「는」 앞에서 받침 ㄹ 이 빠져 「나」로 적힙니다. 형태소 분석은 빠진 ㄹ 을 되살려 「날」로 돌려놓습니다.

두 풀이 중 무엇이 맞는지는 「나는」 두 글자만 봐서는 모릅니다. 앞뒤 조각을 함께 봐야 정해집니다. 형태소 분석이 푸는 문제의 핵심이 이것입니다.

입력과 출력

형태소 분석을 계산 문제로 적으면 이렇습니다. 입력은 문장 하나입니다. 출력은 (형태소, 품사) 짝의 목록입니다.

가능한 목록은 대개 여럿입니다. 그중 가장 그럴듯한 하나를 내는 것이 목표입니다. 아래 소절들이 그 하나를 고르는 방법입니다.

후보 격자

풀이를 고르려면 먼저 가능한 풀이를 다 펼쳐 놓아야 합니다. 형태소 분석은 문장의 글자 위치마다 사전을 찾아봅니다. 그 위치에서 시작하는 낱말 후보를 전부 꺼냅니다.

위치마다 사전을 찾으려면 사전 찾기가 빨라야 합니다. 그래서 사전은 흔히 트라이에 담습니다. 트라이는 낱말을 앞 글자부터 한 글자씩 가지로 나눠 담는 트리입니다. 한 위치에서 가지를 한 번 따라 내려가면 그 위치에서 시작하는 낱말이 전부 나옵니다.

꺼낸 후보들을 앞뒤로 이으면 그래프가 됩니다. 이 그래프를 격자(lattice)라고 부릅니다. 문장 첫머리에서 문장 끝까지 가는 길 하나가 풀이 하나입니다.

「나는」 한 마디의 격자는 아래와 같습니다. 가운데 후보는 「싹이 나는 봄」에 쓰인 동사 「나다」입니다.

flowchart TD
    S["문장 첫머리"] --> A["나 · 대명사"]
    S --> B["나 · 동사 나다"]
    S --> C["날 · 동사 날다"]
    A --> D["는 · 조사"]
    B --> E["는 · 어미"]
    C --> E
    D --> F["문장 끝"]
    E --> F

그림에서 첫머리부터 끝까지 가는 길은 셋입니다. 글쓴이가 뜻한 풀이는 이 가운데 하나뿐입니다. 어느 길인지는 「나는」 앞뒤에 무엇이 오느냐에 달려 있습니다.

가장 그럴듯한 길 고르기

길을 고르는 기준은 비용입니다. 후보 조각마다 비용을 매깁니다. 자주 쓰이는 조각일수록 비용이 낮습니다.

조각과 조각이 이어지는 데도 비용을 매깁니다. 대명사 뒤에 조사가 오는 이음은 흔해서 싸게 칩니다. 흔하지 않은 이음은 비싸게 칩니다.

이 비용들은 사람이 형태소를 미리 나눠 둔 글 묶음에서 세어 얻습니다. 이런 글 묶음을 말뭉치라고 부릅니다. 말뭉치에 자주 나온 조각과 이음일수록 비용이 낮아집니다.

길의 비용은 그 길에 놓인 조각 비용과 이음 비용을 모두 더한 값입니다. 형태소 분석은 비용 합이 가장 작은 길을 고릅니다. 격자 위에서 최단 경로를 찾는 문제가 되는 셈입니다.

비터비 알고리즘

길을 하나씩 다 세어 보는 방법은 못 씁니다. 풀이가 두 갈래로 갈리는 곳이 문장에 열 군데 있으면 길은 2를 열 번 곱한 1,024개입니다. 스무 군데면 백만 개를 넘습니다.

그래서 동적 계획법으로 풉니다. 왼쪽에서 오른쪽으로 가면서 후보 조각마다 거기 도착하는 길 가운데 가장 싼 것 하나만 기억합니다. 나머지 길은 거기서 버립니다.

버려도 되는 까닭은 이음 비용이 바로 앞 조각 하나만 보고 정해지기 때문입니다. 같은 조각에 도착한 두 길은 그 뒤로 똑같은 비용을 더해 갑니다. 지금 비싼 길은 끝까지 비쌉니다.

이렇게 격자 위에서 가장 싼 길을 찾는 방법을 비터비 알고리즘이라고 부릅니다. 문장 끝에 닿으면 기억해 둔 길을 거꾸로 따라가 풀이를 꺼냅니다.

두 방법이 드는 시간은 이렇게 갈립니다.

방법 드는 시간
길을 전부 세기 갈리는 곳 k 군데마다 두 배 · 2 의 k 제곱에 비례
비터비 알고리즘 격자에 놓인 이음 수에 비례

한 위치에서 시작하는 후보는 몇 개로 그칩니다. 그래서 격자의 이음 수는 대략 문장 길이에 비례합니다. 비터비 알고리즘도 문장 길이에 비례하는 시간 안에 끝납니다.

사전에 없는 낱말

사전에 없는 낱말을 미등록어라고 부릅니다. 새로 생긴 가게 이름이나 「갓생」 같은 신조어가 그렇습니다. 격자에 그 낱말 후보가 없습니다. 형태소 분석은 사전에 있는 조각들로 억지로 잘라 냅니다.

흔히 쓰는 대책은 사용자 사전입니다. 서비스를 운영하는 쪽이 자기 서비스에서 쓰는 낱말을 따로 적어 둡니다. 그러면 형태소 분석이 그 낱말을 한 조각으로 봅니다.

검색 엔진 안의 형태소 분석

검색 엔진은 문서가 들어오면 역색인에 적어 둡니다. 역색인은 낱말마다 그 낱말이 든 문서 번호를 적어 둔 찾아보기 표입니다. 검색어가 오면 이 표에서 낱말을 찾아 문서를 곧바로 꺼냅니다.

역색인에 적으려면 먼저 글을 낱말 조각으로 쪼개야 합니다. 이 일을 토큰화라고 합니다. 한국어 검색에서는 형태소 분석이 토큰화를 맡습니다.

형태소 분석으로 나눈 뒤에는 품사 태그를 보고 조사와 어미를 버립니다. 남은 조각만 역색인에 적힙니다. 이 과정을 한데 묶은 부품을 분석기라고 부릅니다.

flowchart TD
    D["문서 · 바다를 보았다"] --> M["형태소 분석"]
    M --> T["바다 · 를 · 보 · 았 · 다"]
    T --> P["품사 태그로 거르기 · 조사와 어미를 버린다"]
    P --> K["바다 · 보"]
    K --> I["역색인에 적는다"]

그림에서 문서 한 줄은 조각 다섯이 됐다가 둘만 남습니다. 역색인에는 「바다」와 「보」만 적힙니다. 「를」 · 「았」 · 「다」는 어느 문서에나 나오는 말이라 찾는 데 쓸모가 없습니다.

검색어도 같은 분석기를 지납니다. 문서에 「바다를」이 있고 검색어가 「바다에서」여도 둘 다 「바다」가 됩니다. 그래서 역색인에서 만납니다. 넣을 때와 찾을 때 분석기가 다르면 같은 낱말이 서로 못 만납니다.

Lucene 은 역색인을 만들고 찾는 자바 검색 라이브러리입니다. Lucene 에는 Nori 라는 한국어 형태소 분석기가 모듈로 들어 있습니다. Lucene 위에 선 Elasticsearch 는 이 Nori 를 플러그인으로 붙여 씁니다.

형태소 분석과 n-gram

형태소 분석 없이 한국어를 색인하는 길도 있습니다. 글자를 n 개씩 겹쳐 잘라 조각으로 쓰는 방법입니다. 이런 조각을 n-gram이라고 부릅니다. 두 글자씩 자르면 「바다를」은 「바다」와 「다를」이 됩니다.

두 방법은 잘하는 것이 서로 반대입니다. 아래 표가 그 차이입니다.

형태소 분석 n-gram
사전 필요하다 필요 없다
사전에 없는 새 낱말 엉뚱하게 자를 수 있다 글자만 맞으면 걸린다
엉뚱하게 걸리는 문서 적다 많다 · 「시장」으로 찾으면 「서울시장애인복지관」도 걸린다
역색인에 적는 조각 수 적다 많다

뜻이 맞는 문서만 찾아야 하면 형태소 분석이 낫습니다. 새 낱말이 많고 하나도 놓치면 안 되면 n-gram 이 낫습니다. 둘을 함께 적어 두는 방식도 씁니다. 이때는 형태소 쪽에서 맞은 문서를 검색 결과 위쪽에 올립니다.

다른 언어와 이웃 기법

영어는 띄어쓰기로 낱말이 거의 갈립니다. 그래서 형태소 분석까지 가지 않고 어간 추출로 끝내는 경우가 많습니다. 어간 추출은 사전 없이 규칙으로 낱말 끝을 잘라 내는 방법입니다. 「jumps」 · 「jumping」에서 끝을 잘라 「jump」를 남기는 식입니다.

표제어 추출은 사전을 보고 낱말을 기본형으로 돌려놓는 방법입니다. 「went」는 끝을 잘라서는 「go」가 되지 않습니다. 사전이 있어야 돌려놓을 수 있습니다. 형태소 분석이 「달렸다」에서 「달리」를 되살리는 것도 이 방법에 가깝습니다.

일본어와 중국어는 문장에 띄어쓰기가 없습니다. 그래서 낱말 경계를 찾는 일부터 사전을 보는 분석이 맡습니다. 형태소 분석이 이 언어들에서도 검색의 첫 단계가 되는 까닭입니다.

형태소 분석은 검색 밖에서도 씁니다. 한국어 글에서 명사만 뽑아 자주 나온 낱말을 세는 일이 그렇습니다. 한국어 글을 낱말 단위로 다뤄야 하는 자연어 처리 작업은 이 단계를 앞에 둡니다.

관련 항목

형태소 분석이 나누고 이름 붙이는 말의 단위

형태소 · 품사 · 품사 태깅 · 어간 · 교착어

형태소 분석이 풀이를 고르는 알고리즘

비터비 알고리즘 · 동적 계획법 · 최단 경로 · 은닉 마르코프 모델 · 조건부 랜덤 필드

형태소 분석기가 기대는 사전과 학습 자료

트라이 · 말뭉치 · 사용자 사전 · 미등록어

형태소 분석 앞뒤로 이어지는 검색 처리 단계

토큰화 · 분석기 · 토크나이저 · 불용어 · 동의어 사전 · 유니코드 정규화 · 역색인

같은 몫을 두고 겨루는 낱말 정리 방법

n-gram · 어간 추출 · 표제어 추출 · 서브워드 · 바이트 쌍 인코딩

형태소 분석을 채택한 검색 엔진과 모듈

Nori · Lucene · Elasticsearch · 검색 엔진 · 전문 검색 · BM25

형태소 분석 뒤에 이어지는 자연어 처리 작업

자연어 처리 · 개체명 인식 · 의존 구문 분석 · 감정 분석 · 언어 모델

다른 이름: morphological analysis · 형태소 분석기 · morphological analyzer