태그 uniq유니코드로케일macOS
전체 글 보기

uniq

uniq 가 서로 다른 한글 줄을 중복이라고 말합니다

맥에서 uniq 로 한글 중복을 세면 틀린 답이 나옵니다. 서로 다른 442줄 중 397줄이 중복으로 잡혔습니다. 원인은 로케일이고 LC_ALL=C 한 줄로 끝나지만, 그때까지 uniq 는 에러 하나 내지 않습니다.

2026년 8월 17일 3분

앱에 넣을 번역 제목 442개를 sort | uniq -c 로 검사하다가, uniq 가 거짓말을 하고 있는 걸 봤습니다. 저는 파일이 망가진 줄 알았는데 파일은 멀쩡했습니다.

uniq 가 442줄 중 397줄을 중복이라고 했습니다

제목 목록을 uniq 로 세어봤습니다.

cut -f2 titles.tsv | sort | uniq -c | sort -rn | head -3
 397 街で人を眺める
  12 夜に1時間本を読む
   8 朝5時に起きる

397개가 같은 제목이라니 번역이 통째로 망가진 줄 알았습니다. 그런데 그 문자열이 파일에 몇 번 있는지 직접 세어보니 이랬습니다.

grep -c '街で人を眺める' titles.tsv
1

한 번입니다. 파이썬으로 set() 에 넣어봐도 442개가 전부 서로 달랐습니다. 망가진 건 파일이 아니라 세는 쪽이었습니다.

범인은 sort 가 아니라 uniq 였습니다

처음에는 sort 를 의심했습니다. 정렬이 이상해서 엉뚱한 줄이 붙었나 싶었는데, sort 결과를 눈으로 보니 세 줄이 멀쩡히 세 줄로 나왔습니다.

printf '가나다\n라마바\n사아자\n' > k.txt
sort k.txt
가나다
라마바
사아자

그런데 여기에 uniq -c 를 붙이면 이렇게 됩니다.

sort k.txt | uniq -c
   3 가나다

서로 다른 세 줄이 한 줄로 접혔습니다. uniq 는 붙어 있는 줄끼리 같은지 비교하는데, 그 비교가 로케일을 탑니다. 제 셸은 이렇게 되어 있었습니다.

locale | grep LC_COLLATE
LC_COLLATE="en_US.UTF-8"

비교에서 한글이 통째로 빠집니다

어떤 규칙으로 같다고 보는지 궁금해서 몇 가지를 넣어봤습니다. 각 줄은 서로 다른 문자열이고, 숫자는 uniq 가 만든 그룹 수입니다.

넣은 줄기본 로케일LC_ALL=C
가나다 라마바 사아자13
가나다1 라마바2 사아자333
a가나다 a라마바 a사아자13
가a나 나a가12
apple banana cherry33

세 번째 줄이 규칙을 보여줍니다. a가나다a라마바 는 앞의 a 만 같고 뒤가 전부 다른데 같은 것으로 접혔습니다. 즉 한글 부분이 비교에서 아예 안 읽힙니다. 네 번째 줄은 더 분명합니다. 가a나나a가 는 남는 것이 a 하나뿐이라 같아집니다.

두 번째 줄이 왜 3개인지도 이걸로 설명됩니다. 1 2 3 은 읽히니까 그것만으로 갈린 겁니다. 제 파일에서 397줄이 한 덩어리가 된 것도 같은 이유였습니다. 그 397줄에는 숫자나 알파벳이 하나도 없었고, 나머지 45줄은 제목에 1 이나 5 같은 숫자가 들어 있어서 그 숫자로만 나뉜 것이었습니다.

한글만 그런 게 아닙니다

같은 방법으로 다른 문자도 재봤습니다.

넣은 두 줄기본 로케일LC_ALL=C
日本 中国12
αβγ δεζ12
Привет Мир12
🍎 🍊12
café cafe22
straße strasse22

한자, 그리스 문자, 키릴 문자, 이모지가 전부 무시됩니다. 반면 악센트가 붙은 라틴 문자는 제대로 구분됩니다. cafécafe 는 다르게 나오고 straßestrasse 도 다르게 나옵니다.

그래서 영어권 코드에서는 이 문제가 안 보입니다. sort -u 도 같은 비교를 쓰니 같이 틀립니다.

고치는 법은 한 줄입니다

cut -f2 titles.tsv | LC_ALL=C sort | LC_ALL=C uniq -d

sortuniq 양쪽 다 붙여야 합니다. LC_ALL=C 는 로케일 규칙 대신 바이트로 비교하라는 뜻이라, 문자열이 다르면 다르다고 나옵니다. 제 파일에 이걸 붙이니 중복 0건이 나왔고, 그게 맞는 답이었습니다.

정렬 순서가 필요한 경우라면 조심할 점이 있습니다. LC_ALL=C 는 사전 순이 아니라 바이트 순이라 한글 정렬 결과가 사람이 기대하는 순서와 다릅니다. 중복을 세는 것과 사람에게 보여줄 순서로 정렬하는 것은 목적이 다르니, 중복 검사에만 쓰면 문제가 없습니다.

배운 것

에러가 안 났다는 게 이 문제의 전부입니다. uniq 는 종료 코드 0을 주고, 숫자도 그럴듯하게 397 같은 값을 냅니다. 저는 그 숫자를 보고 번역 파일이 망가졌다고 판단했고, 잠깐이지만 멀쩡한 결과물을 버릴 뻔했습니다.

같은 저장소에서 통과했다고 말하지만 아무것도 안 보던 타입 검사를 겪은 적이 있습니다. 그때도 문제는 검사기가 틀린 게 아니라 검사기를 검사하지 않은 것이었습니다.

그래서 지금은 중복 검사를 셸에서 안 합니다. 검사기를 쓰는 코드 안에서 딕셔너리로 세게 바꿨습니다. 셸 파이프라인은 짧아서 좋지만, 짧다는 이유로 검산 없이 믿을 수는 없다는 걸 이번에 배웠습니다.

어디까지 확인했는지

macOS 26.6 (빌드 25G72), sort 2.3-Apple (199) 에서 확인했습니다. LC_COLLATE=en_US.UTF-8 인 기본 셸 환경입니다.

리눅스에서도 같은지는 확인하지 못했습니다. GNU coreutils 의 uniq 는 구현이 다르고 glibc 의 로케일 데이터도 다르므로 결과가 다를 수 있습니다. 다른 로케일(ko_KR.UTF-8 등)에서 어떻게 되는지도 재보지 않았습니다. 확인한 것은 위에 적은 조합 하나입니다.

이전 글 미라클모닝을 검색하는 사람들이 실제로 묻는 것