database

MongoDB - 텍스트 검색 오류

1. 유니코드 정규화(NFC vs NFD) 차이로 인한 검색 오류

MongoDB에서 텍스트 검색을 수행할 때, 유니코드 정규화 방식(Normalization Form)이 다르면 같은 문자열이라도 다르게 인식됩니다. 예를 들어, 한글이나 특수 문자가 포함된 텍스트를 검색할 때 NFC(Normalization Form C)와 NFD(Normalization Form D) 방식의 차이로 인해 조회되지 않는 문제가 발생할 수 있습니다. 이 문제는 MacOS 또는 특정 환경에서 텍스트가 NFD 형태로 저장되었지만, 검색 시 NFC 형식으로 입력되었을 때 자주 발생합니다.


2. 유니코드 정규화란?

유니코드에서는 같은 문자를 여러 방식으로 표현할 수 있습니다. 예를 들어, 한글 "가"는 다음 두 가지 방식으로 표현될 수 있습니다.

  • NFC (Normalization Form C): 조합된 형태 → "가"
  • NFD (Normalization Form D): 분해된 형태 → "ᄀ" + "ᅡ"
mongodb
console.log('가' === '\u1100\u1161'); // false (NFC vs NFD)
console.log('가'.normalize('NFC') === '\u1100\u1161'.normalize('NFC')); // true

이처럼 MongoDB에 저장된 문자열이 NFC인지 NFD인지에 따라 동일한 텍스트라도 검색 결과가 달라질 수 있습니다.


3. NFC와 NFD 차이로 인한 검색 오류

MongoDB에 한글 데이터를 저장하고, 동일한 문자열을 조회할 때 조회되지 않는 사례를 살펴보겠습니다.

3-1. 데이터 삽입 (NFC 형태)

mongodb
db.products.insertOne({ name: "컴퓨터" });

3-1. 3-2. 검색 (NFD 형태로 입력)

mongodb
db.products.find({ name: "컴퓨터" });

위와 같이 컴퓨터라는 문자열이 NFC로 저장되었지만, 검색 시 NFD 형태로 입력되면 조회되지 않습니다. 이는 MongoDB가 기본적으로 유니코드 정규화를 적용하지 않기 때문입니다.


4. 해결 방법

4-1. 저장 시 모든 데이터를 NFC로 정규화

데이터를 삽입하기 전에 NFC로 변환하여 저장하면 문제를 예방할 수 있습니다.

mongodb
db.products.insertOne({ name: "컴퓨터".normalize("NFC") });

4-2. 검색 시 정규화 적용

검색 시에도 입력 데이터를 NFC로 변환하여 조회하면 문제를 해결할 수 있습니다.

mongodb
db.products.find({ name: "컴퓨터".normalize("NFC") });

4-3. MongoDB에서 collation을 활용한 정규화

MongoDB의 collation 기능을 활용하면 유니코드 문자열 비교 방식을 개선할 수 있습니다. 이 방법을 사용하면 한글이나 특수 문자가 포함된 데이터의 정렬 및 검색이 더 일관성 있게 수행됩니다.

mongodb
db.products.find(
  { name: "컴퓨터" },
  { collation: { locale: "ko", strength: 1 } }
);
  • locale: "ko" → 한국어 정렬 방식 적용
  • strength: 1 → 문자 비교 시 정규화 차이를 무시하도록 설정

이 방법은 문자열 검색뿐만 아니라, 정렬 시에도 유니코드 정규화 차이를 무시하도록 설정할 수 있어 유용합니다.


5. 결론

  • MongoDB는 기본적으로 유니코드 정규화를 적용하지 않기 때문에, NFC와 NFD 차이로 인해 동일한 텍스트라도 검색이 실패할 수 있습니다. 따라서 데이터를 삽입하기 전에 NFC로 변환하여 저장하고, 검색 시에도 .normalize("NFC")를 적용하면 문제 해결 가능합니다. 또한, MongoDB collation 기능을 활용하면 검색 및 정렬 시 유니코드 정규화 차이를 줄일 수 있습니다.