안수찬 블로그

postgresql 에서 한글 정렬 문제 해결하기

Introduction

안수찬 @dobestan

서울대학교에서 컴퓨터공학을 전공하고, 오랜 기간 서비스 기획 및 개발을 해 왔습니다. 이러한 전문성을 인정받아 미래부 소프트웨어 마에스트로에 선정된 바 있습니다. 현재는 모바일 방송국, 퍼스트캔버스에서 컨텐츠로 새로운 가치를 그리고 있습니다. 나는 안수찬이다. 그러므로 나는 할 수 있다. me@ansuchan.com


postgresql 에서 한글 정렬 문제 해결하기

Posted by 안수찬 @dobestan on .
Featured

postgresql 에서 한글 정렬 문제 해결하기

Posted by 안수찬 @dobestan on .

최근에 나무 직거래 관련된 서비스를 개발하고 있습니다. 오랜만에 개인 취미로 개발하고 있어서 굉장히 재미있게 개발하고 여러가지 시도들을 많이 해보고 있습니다. 최근에 작업한 내용은 나무/조경수 농장들이 가능하면 편하게 거래할 수 있도록, 가능한한 표준화된 형태의 수목 정보, 표준 가격 정보 ( 조달청/나라장터 단가 기준 ) 를 API 형태로 제공하는 기능을 개발했습니다.

이 API를 개발하면서 ( 사실 이전에도 똑같은 문제들이 있었는데 제가 발견하지 못했었는, ),

  • Postgresql 에서의 한글 정렬(ORDER_BY) 이 되지 않는 문제
  • ( 사실상 동일한 문제인데, ) sort 커맨드가 정상적으로 동작하지 않는 문제

가 있었고, 이 문제를 해결하는 방법을 공유합니다.

tl;dr

  • 이 문제는 locale 의 LC_COLLATE 과 관련된 문제입니다.
  • 다음과 같이 LC_COLLATE="C" 를 명시적으로 설정해줌으로써 sort 커맨드에서 한글 정렬이 정상적으로 동작하도록 수정하실 수 있습니다:
$ export LC_COLLATE="C"
  • 설정이 제대로 된 상태에서 postgresql 을 재설치 합니다. ( 혹은 쿼리 뒤에 collate="C" 를 추가합니다. )

문제점 발견

Django 를 이용해서 개발을 진행하고 있는데, 로컬 개발 환경에서 Tree.objects.sort() ( Django ORM ) 기능이 정상적으로 동작하지 않는 문제를 발견했습니다. 뭐라고 설명하기가 애매한데, 정렬되는 것 처럼 보이지만, 실상은 정렬되지 않는 문제를 발견했습니다.

Django 의 설정들은 다 올바르게 되어 있어서, 사용하고 있던 Postgresql 의 문제인 것 같아, SELECT * FROM tree ORDER BY name; 를 해봐도, Postgresql 에서도 동일하게 정렬이 안되는 문제가 있었습니다.

제가 초등교육과정을 이수한지 오래 지나서, ㄱㄴㄷㄹㅁㅂㅅ... 말고 다른 정렬이 있는지도 잠깐 고민했습니다. 혹시나 하는 마음에 sort 커맨드를 사용해봐도, 정렬이 안되는 문제가 발생했습니다.

정렬되는 것 처럼 보이지만, 실상은 정렬되지 않는 문제

다음과 같은 순서로 정렬이 되고 있습니다:

$ cat tree.txt | uniq | sort

감나무
소나무
소나무(금송)
소나무(조형)
느티나무      # 이 "느티나무" 의 위치가 굉장히 이상합니다. "ㄴ" 이니깐 감나무 뒤에 와야 합니다.
조팝나무

문제의 원인

찾아보니 이와 유사한 문제를 다른 개발자들도 겪고 있었습니다.

결론적으로 살펴보면, 이는 LC_COLLATE 와 관련된 설정의 문제였습니다. 따라서 export LC_COLLATE="C" 로 변경을 하고 sort를 하니 정상적으로 정렬이 되었습니다.

$ locale | grep LC_COLLATE
LC_COLLATE="en_US.UTF8"  # 제 로컬 맥의 경우에는 다음과 같이 설정이 되어서 문제가 발생했습니다.  
                         # LC_ALL 설정이 된 경우에도 변경해주셔야 합니다.

$ export LC_COLLATE="C"
$ locale | grep LC_COLLATE
LC_COLLATE="C"  
$ cat tree.txt | uniq | sort

감나무
느티나무     # 이제 ㄱㄴㄷ 순으로 정상적으로 정렬됨을 확인하실 수 있습니다.
소나무
소나무(금송)
소나무(조형)
조팝나무

다만, Postgresql 의 경우에는 system locale 을 변경해주셔도 이미 데이터베이스/테이블을 생성하는 시점에 COLLATE 가 결정되기 때문에, 다음과 같이 쿼리 뒤에 명시적으로 collate "C" 를 명시해야 정상적으로 정렬된 결과를 받을 수 있습니다. 그런데 이건 또 이상하니깐 제대로 설정을 하도록 합시다.

postgres#= SELECT * FROM tree ORDER BY name collate "C";  

제가 locale 에 대한 이해도가 낮아서, 왜 한글인 경우에 en_US.UTF-8 혹은 ko_KR.UTF-8 / ko_KR.EUCKR 인 경우에 정렬이 되지 않는지는 잘 모르겠습니다. 혹시 아시는 분은 댓글로 남겨주시면 감사하겠습니다.

Postgresql 다시 설치하기

1. 맥에서 brew 를 이용한 설치하기

맥용 패키지 매니저 brew 의 경우에는 기본 system locale 의 값을 기준으로 postgresql initdb 를 수행합니다. 따라서, locale 만 제대로 설정되었다면 기존에 설치된 postgresql 을 삭제하시고 재설치하시면 됩니다.

$ # postgresql 삭제하기
$ brew uninstall postgresql
$ sudo rm -rf /usr/local/var/postgres

$ export LC_COLLATE="C"  # 어차피 sort 커맨드로 한글 정렬을 하신다면,
                         # 사용하시는 프로필에 넣어두시면 됩니다. ( ~/.bash_profile, ~/.zshrc )

$ # postgresql 설치하기
$ brew install postgresql

2. Ubuntu apt-get 을 이용한 설치하기

Ubuntu 16.04 패키지 매니저인 apt-get 의 경우에는 en_US.UTF-8 을 기준으로 설치하게 됩니다. 따라서, 이 경우에는 이미 생성된 postgresql cluster 를 삭제하고, 새롭게 locale 을 명시해서 설치해주셔야 합니다.

$ pg_lsclusters    # 현재 cluster 목록 확인하기

Ver Cluster Port Status Owner    Data directory               Log file  
9.5 main    5432 online postgres /var/lib/postgresql/9.5/main /var/log/postgresql/postgresql-9.5-main.log  
$ pg_dropcluster --stop 9.5 main   # 위에서 찾은 cluster 를 삭제합니다.

$ # --lc-collate 설정으로 LC_COLLATE 값을 명시할 수 있습니다.
$ sudo pg_createcluster --locale en_US.UTF8 --lc-collate=C --start 9.5 main
$ psql --list

                               List of databases
   Name    |  Owner   | Encoding | Collate |   Ctype    |   Access privileges
-----------+----------+----------+---------+------------+-----------------------
 postgres  | postgres | UTF8     | C       | en_US.UTF8 |
 template0 | postgres | UTF8     | C       | en_US.UTF8 | =c/postgres          +
           |          |          |         |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | C       | en_US.UTF8 | =c/postgres          +
           |          |          |         |            | postgres=CTc/postgres
(3 rows)

References

안수찬 @dobestan

https://ansuchan.com/

서울대학교에서 컴퓨터공학을 전공하고, 오랜 기간 서비스 기획 및 개발을 해 왔습니다. 이러한 전문성을 인정받아 미래부 소프트웨어 마에스트로에 선정된 바 있습니다. 현재는 모바일 방송국, 퍼스트캔버스에서 컨텐츠로 새로운 가치를 그리고 있습니다. 나는 안수찬이다. 그러므로 나는 할 수 있다. me@ansuchan.com

View Comments...