PostgreSQL: 정규표현식으로 한글 포함 여부 확인하기


PGSQL에서 정규식을 이용하여 한글이 포함된 텍스트인지 확인하는 방법입니다.

알파벳만 찾는 경우 "[a-z]" 입력하여 그 범위에 포함되는 모든 문자를 찾도록 합니다.
한글도 동일하게 첫 글자와 끝 글자를 입력하여 찾고자 하는 범위를 지정해주면됩니다.
그런데 한글의 첫 글자와 끝 글자만 알면되는데 여기서 많은 분들이 실수가 발생합니다.
알파벳과 다르게 한글은 자음, 모음이 있고 완성된 글자가 있어서 어렵습니다. 그래서 대부분은 검색해서 찾은 정규식을 사용합니다.
찾은 정규식이 정말 한글만 검색되는지 테스트해보시길 권장드리며 아래의 쿼리도 시스템의 환경에 따라 다른 결과가 나올 수 있습니다.

아래 범위는 엄격한 범위는 아니며 일반적으로 입력하기 힘든 확장형 한글은 제외된 범위입니다.
엄격한 범위 지정을 원하시면 하단의 "함께보기" 링크를 참조하여 추가하시면 됩니다.

한글 문자를 입력한 방법

참고: UTF-8환경에서 실행 시 유니코드 블록의 범위로 검색됩니다.
SELECT
(CASE WHEN 'Taekyun 김' ~ E'[ㄱ-ㅣ가-힣]' THEN 'true' ELSE 'false' END) AS string1,
(CASE WHEN 'ㅏ' ~ E'[ㄱ-ㅣ가-힣]' THEN 'true' ELSE 'false' END) AS string2,
(CASE WHEN 'Taekyun' ~ E'[ㄱ-ㅣ가-힣]' THEN 'true' ELSE 'false' END) AS string3,
(CASE WHEN 'Taekyun 金' ~ E'[ㄱ-ㅣ가-힣]' THEN 'true' ELSE 'false' END) AS string4;


유니코드 사용한 방법(Unicode)

주의: 유키코드에서는 한글과 관련되어 5개의 코드 블록이 존재합니다. 그 중 확장 블록은 일반적으로 입력할수 없기 때문에 2개의 블록만 사용했습니다.
참고 1: [ㄱ-ㅣ가-힣]의 유니코드로 변경한 쿼리입니다. 위 쿼리 결과와 동일합니다.
참고 2: 한글 관련된 유니코드 블록 정보는 하단의 "함께보기" 링크에서 확인 가능합니다.
SELECT
(CASE WHEN 'Taekyun 김' ~ E'[\u3131-\u3163\uAC00-\uD7A3]' THEN 'true' ELSE 'false' END) AS string1,
(CASE WHEN 'ㅏ' ~ E'[\u3131-\u3163\uAC00-\uD7A3]' THEN 'true' ELSE 'false' END) AS string2,
(CASE WHEN 'Taekyun' ~ E'[\u3131-\u3163\uAC00-\uD7A3]' THEN 'true' ELSE 'false' END) AS string3,
(CASE WHEN 'Taekyun 金' ~ E'[\u3131-\u3163\uAC00-\uD7A3]' THEN 'true' ELSE 'false' END) AS string4;

아스키 코드를 사용한 방법(ASCII) (권장하지 않음)

주의: 한글 문자를 찾는 것이 아닌 2Byte 문자를 찾는 방법입니다. 예제 쿼리를 보시면 한자도 "true"로 출력됩니다.
SELECT
(CASE WHEN 'Taekyun 김' ~ E'[\xA1-\xFE]' THEN 'true' ELSE 'false' END) AS string1,
(CASE WHEN 'ㅏ' ~ E'[\xA1-\xFE]' THEN 'true' ELSE 'false' END) AS string2,
(CASE WHEN 'Taekyun' ~ E'[\xA1-\xFE]' THEN 'true' ELSE 'false' END) AS string3,
(CASE WHEN 'Taekyun 金' ~ E'[\xA1-\xFE]' THEN 'true' ELSE 'false' END) AS string4;

마무리하며

SELECT
(CASE WHEN 'Taekyun 김' ~ E'[ㄱ-힣]' THEN 'true' ELSE 'false' END) AS string1,
(CASE WHEN 'ㅏ' ~ E'[ㄱ-힣]' THEN 'true' ELSE 'false' END) AS string2,
(CASE WHEN 'Taekyun' ~ E'[ㄱ-힣]' THEN 'true' ELSE 'false' END) AS string3,
(CASE WHEN 'Taekyun 金' ~ E'[ㄱ-힣]' THEN 'true' ELSE 'false' END) AS string4,
(CASE WHEN 'ㅏ' ~ E'[ㄱ-ㅎ]' THEN 'true' ELSE 'false' END) AS string5;

많이 검색되는 정규식인데 EUC-KR 환경과 UTF-8 환경에서 다른 결과가 출력됩니다.
국내에서는 EUC-KR 환경을 많이 사용했었기 때문에 해당 정규식에서 큰 이슈가 없었을거 같습니다.
그리고 "[ㄱ-ㅎㅏ-ㅣ가-힝]"" 이렇게 "[ㅏ-ㅣ]"를 추가하셔도 되는데 "[ㄱ-ㅣ]"와 같은 블록에 있기때문에 차이가 없습니다.

다른 프로그래밍 언어에서도 한글 관련 처리에 대해서 동일한 이슈가 있는데 유니코드로 검색하는게 가장 좋은거 같습니다.
참고로 PHP 샘플 코드를 만들어놨는데, https://3v4l.org/k77DG 해당 코드를 EUC-KR 환경과 UTF-8 환경에서 테스트하면 다른 결과가 나오실겁니다.

본 내용에서도 잘못된 부분이 있을 수 있으며 알려주시면 감사히 배우겠습니다.

함께보기