일상/IT

유니코드 Zalgo 문자란? UI가 깨지는 원리와 보안 위험 완전 정리

얇은생각 2026. 3. 21. 07:30
반응형

유니코드의 허점과 Zalgo 문자: UI 파괴, 보안 위협, 그리고 기술적 대응

들어가며

웹과 앱 UI를 다루다 보면, “문자”는 단순한 표시 요소처럼 취급되기 쉽다. 그러나 현대 컴퓨팅에서 문자는 단순한 글꼴 출력이 아니라, 표준 규격(유니코드)과 렌더링 엔진, 폰트, 운영체제, 그리고 입력/검증 로직이 맞물린 복합 시스템의 결과물이다. 이 글은 유니코드의 구조적 특징과 그 허점을 악용해 발생할 수 있는 UI 파괴, 데이터 은닉, 보안 위협, 시스템 안정성 문제를 영상 스크립트의 흐름과 예시를 그대로 보존하여 정리한 롱폼 글이다.

유니코드는 지구상에 있는 모든 문자를 담아내기 위해 설계된 표준 문자 체계이며, 실제로 대부분의 프로그램은 유니코드를 이용해 문자를 저장하고 표현한다. 그 결과 다국어 지원이라는 이점을 얻었지만, 동시에 복잡한 문법과 확장성 때문에 “문자 하나”가 UI를 붕괴시키거나 보안 정책을 우회하는 현상까지도 만들어낼 수 있다. 특히 결합 문자(발음기호·성조 등) 중첩으로 만들어지는 Zalgo 문자, 화면에서 보이지 않지만 동작에 영향을 주는 투명 문자(Zero Width Joiner 등), 외형은 같아 보이지만 코드 포인트가 다른 호모글리프 문제는 현실적인 위험 요소로 자주 언급된다.

 

유니코드(Unicode)

 


1. 유니코드(Unicode)란 무엇인가

1.1 “세상의 모든 문자를 담는 목록”이라는 개념

유니코드는 지구상에 있는 모든 문자를 담고 있는 목록에 가깝다. 문자마다 고유한 번호(코드 포인트)가 부여되며, 컴퓨터는 문자를 직접 저장하는 대신 이 번호를 저장하는 방식으로 동작한다. 영상에서는 유니코드가 총 약 15만 자 정도를 담고 있다고 설명한다.

현대의 대부분의 프로그램이 유니코드를 “문자 처리의 표준”처럼 사용하기 때문에, 다양한 언어와 문자를 동일한 규칙 아래에서 저장·표현·전송할 수 있다. 이는 국제화(i18n) 관점에서 사실상 필수 기반이 되었지만, 동시에 규격이 방대해지면서 예상치 못한 취약점이나 악용 가능성도 함께 커졌다.

 

 

1.2 코드 포인트 예시: 대문자 A는 U+0041

유니코드의 앞쪽에는 숫자와 알파벳 같은 기본 문자가 배치되어 있다. 예를 들어 대문자 A0041이라는 번호를 가진다. 따라서 사용자가 컴퓨터에서 A를 입력하면 내부적으로는 U+0041이 저장되는 방식으로 사용될 수 있다.

이처럼 유니코드는 “문자 → 코드 포인트” 매핑을 표준화하며, 프로그램은 이를 통해 동일한 문자를 일관되게 처리하려고 한다.

 

 

1.3 유니코드에 포함된 문자 범위

영상에서는 유니코드의 범위를 직관적으로 보여주기 위해 다양한 예시를 나열한다.

  • 이집트 문자도 포함되어 있다.
  • 마작패 문자도 포함되어 있다.
  • 이모지도 약 4,000자 정도 포함되어 있다.
  • 한글은 약 1만 자 정도 저장되어 있다.
  • 중국 한자도 매우 많으며, 한중일 문자를 전부 합하면 약 10만 자 정도가 들어 있다.
  • 그리고 중요한 요소로 성조 또는 발음기호 같은 기호들도 포함되어 있다.

 

이 방대한 범위는 “모든 문자를 자유롭게 표현하려는 목표”의 직접적인 결과이며, 이후 소개되는 문제들도 대부분 이 범위와 문법의 복잡성에서 기인한다.

 

 

 


2. UI를 박살내는 이상한 문자: Zalgo 현상

 

 

2.1 UI를 위로/아래로 ‘끝없이’ 뻗게 만드는 문자 배치

영상은 “UI를 박살내는 이상한 문자들이 있다”는 문제 제기로 시작한다. 이 문자를 사용하면 화면에서 글자가 위쪽으로 끝없이 향하게 만들 수도 있고, 반대로 아래로 끝없이 향하게 만들 수도 있다. 더 복잡하게 사용하면 훨씬 과격한 형태의 UI 파괴도 가능하다.

이때 언급되는 대표적 형태가 Zalgo 문자이다. Zalgo는 기본 문자 위·아래에 발음기호 같은 결합 요소를 과도하게 쌓아 올려 글자 주변이 무너져 내리듯 난잡하게 보이게 만드는 텍스트를 말한다.

 

 

2.2 왜 막기 어려운가: 유니코드 문법의 ‘허점’ 활용

이런 텍스트가 문제인 이유는, 단순한 “버그”가 아니라 유니코드 표준이 허용하는 문법을 정직하게(?) 사용한 결과인 경우가 많기 때문이다. 즉, 많은 환경에서 “정상적으로 지원되는 기능”으로 동작한다.

대부분의 프로그램은 유니코드를 이용해 문자를 저장하고 표현한다. 그리고 요즘은 거의 모든 곳에서 유니코드 문법을 잘 지원하는 편이다. 따라서 공격자는 유니코드가 허용하는 문자 배치 규칙을 이용해, 렌더링 엔진이 “정상 처리”하는 방식 그대로 UI를 파괴하는 효과를 만들 수 있다.

 

 

 


3. 결합 문자(Non-spacing Mark)와 중첩의 원리

 

 

3.1 Non-spacing Mark란 무엇인가

유니코드에는 성조발음기호처럼 “독립적으로 문자 하나의 공간을 차지하지 않는” 요소들이 있다. 영상에서는 이런 부류를 non spacing mark라고 설명한다.

non spacing mark는 단독으로 폭을 차지하지 않는다. 대신 일반 문자 뒤에 붙이면 해당 문자에 자동으로 결합되는 방식으로 렌더링된다. 즉, 기본 글자(베이스 문자) 위나 아래에 표시되면서도 레이아웃 상의 폭을 별도로 차지하지 않는 것이 특징이다.

 

 

3.2 개수 제한이 사실상 없을 때 생기는 문제

영상의 핵심은 여기서 발생한다. 결합 문자가 “문법적으로” 허용되는 만큼, 그리고 그 개수에 제한이 없다면(또는 사실상 제한이 없다면) 원하는 만큼 중첩이 가능해진다.

이 중첩이 과도하게 일어나면 다음 현상이 발생한다.

  • 문자 하나가 위쪽으로 길게 치솟는 것처럼 보인다.
  • 문자 하나가 아래쪽으로 끝없이 늘어지는 것처럼 보인다.
  • 결과적으로 텍스트 영역이 주변 UI 요소를 침범하거나, 줄 간격과 레이아웃 계산을 무너뜨린다.

 

이것이 바로 Zalgo 텍스트가 UI를 “박살낸다”는 표현으로 요약되는 이유이다.

 

 

 


4. 투명 문자와 Zero Width Joiner(ZWJ)

 

 

4.1 보이지 않는 문자: ‘투명한 문자’의 존재

유니코드는 신기하게도 투명한 문자들을 포함한다. 즉, 출력했을 때 화면에 보이지 않거나 거의 보이지 않지만, 텍스트 처리 과정에는 영향을 주는 문자들이다.

그중 대표적인 것이 Zero Width Joiner이다.

 

 

4.2 Zero Width Joiner의 기능: 문자를 결합해 보여주기

Zero Width Joiner는 문자들을 결합해 주는 특수한 문자로, 왼쪽과 오른쪽에 있는 문자를 합쳐서 보여주는 역할을 한다. 이 과정은 단순한 “글자 붙이기”가 아니라, 렌더러가 특정 규칙에 따라 조합된 표현으로 표시하는 동작에 가깝다.

특히 이모지에서도 결합이 가능하다는 점이 강조된다.

 

 

4.2.1 이모지 결합 예시

영상에서는 다음과 같은 결합 예시를 제시한다.

  • 곰 이모지와 눈송이 이모지를 합치면 북극곰이 된다.
  • 남자 이모지와 프라이팬을 합치면 남자 요리사를 만들 수 있다.
  • 사람 이모지와 쌀 이모지를 합치면 쌀숭이가 된다.

 

이런 조합은 임의로 되는 것이 아니라, “조합 공식 같은 것이 따로 있다”고 설명된다. 즉, 표준 또는 구현 규칙에 의해 가능한 조합이 정해져 있으며, ZWJ는 그 결합을 위한 문법 요소로 사용된다.

 

 

4.3 문법 구현용 투명 문자의 확장: 데이터 은닉

ZWJ 같은 투명 문자는 원래 문법 구현을 위해 존재하지만, 이를 응용하면 비밀 메시지를 문자 안에 숨길 수 있다.

영상에서는 다음 방식이 언급된다.

  • 어떤 사이트는 문법용 문자들을 0과 1로 표현해서 데이터를 문자 안에 숨겨 주는 것처럼 보인다고 설명한다.
  • 또는 요즘은 잘 안 쓰는 투명한 유니코드 문자들이 있는데, 출력하면 투명하게 나올 수 있다.
  • 그런데 이런 문자가 영어 알파벳과 번호가 굉장히 유사해, 이를 이용해 비밀 메시지를 문자들 사이에 기록하는 사람들도 있다.

 

 

4.3.1 활용 가능 시나리오

이런 데이터 은닉은 다양한 용도로 활용될 수 있다고 영상은 제안한다.

  • ARG 게임에서 숨겨진 메시지 전달
  • 블로그 글에 워터마크를 몰래 삽입
  • 그리고 특히 중요한 사례로, 이를 이용해 프롬프트 인젝션을 구현하는 사람들도 존재한다.

 

따라서 에이전트(Agent) 같은 자동화 도구를 사용할 때 조심하라는 경고가 이어지며, 그 이유 중 하나가 이런 투명 문자를 통한 은닉·주입 가능성이라는 설명이 덧붙는다.

 

 

 


5. 유니코드 렌더링과 시스템 안정성 문제

 

 

5.1 글자 렌더링 중 OS가 뻗는 사건

유니코드가 복잡하기 때문에, 글자를 렌더링하는 과정에서 운영체제(OS)가 뻗는 사건도 가끔 발생한다고 설명한다. 이는 단순히 UI가 깨지는 수준을 넘어서 시스템 안정성을 위협할 수 있다는 의미이다.

 

 

5.2 아이폰 강제 재시작 사건: 문자 하나로 가능한 ‘테러’

영상은 과거 사례로, 예전 아이폰에서 특정 문자를 출력하려고 하면 기기가 강제로 재시작되는 사건이 있었다고 언급한다. 즉, 문자 렌더링 경로의 취약점을 이용하면 문자 하나로도 기기 재시작을 유발할 수 있었다.

이 때문에 “문자 하나로 테러가 가능했던 시절도 있었다”는 표현이 등장한다. 여기서의 ‘테러’는 폭력적 의미가 아니라, 시스템을 마비시키는 기술적 교란 행위를 지칭하는 맥락으로 사용된다.

 

 

 


6. 코딩에서의 장난질: 호모글리프(Homoglyph) 문제

 

 

6.1 겉으로 같아 보이지만 비교하면 False가 되는 이유

유니코드를 사용하면 코딩에서도 예상치 못한 장난이 가능하다. 영상에서는 “두 개 글자가 똑같아 보이지만 비교하면 False가 나온다”는 예시를 든다.

그 이유는, 외형은 동일하지만 코드 포인트가 다른 문자가 존재하기 때문이다. 대표적으로 키릴 문자에는 라틴 알파벳 A와 똑같이 생긴 문자가 있다. 사람이 보기에는 같아 보이지만, 코드 포인트가 다르므로 컴퓨터는 서로 다른 문자로 인식한다.

 

 

6.2 호모글리프의 정의

이처럼 모양이 비슷한 다른 글자를 부르는 말이 있으며, 이를 **호모글리프(homoglyph)**라고 한다.

 

 

6.3 한글과 비슷한 구자라트 문자 사례

영상은 호모글리프의 위험성을 보여주기 위해 “한글이랑 비슷하게 생긴 구자라트 문자가 있다”고 언급한다. 그리고 이 문자들을 이용해 사람 눈에는 한글처럼 보이지만 실제로는 다른 문자로 구성된 텍스트를 만들 수 있음을 예시로 제시한다.

  • 이를 이용하면 “엉덩이 더러워도” 같은 문구를 만들 수도 있고,
  • “멍멍이랑 벗어도” 같은 문구도 만들 수 있다고 설명한다.

 

이 예시는 특정 표현을 실제로 강조하려는 것이 아니라, “겉보기”와 “실제 문자열”이 달라질 수 있다는 점을 직관적으로 보여주기 위한 사례로 제시된다.

 

 

 


7. 호모글리프 기반 피싱과 브라우저의 대응

 

 

7.1 유명 도메인을 비슷하게 만들어 피싱에 활용

호모글리프는 단순한 장난을 넘어 실질적인 보안 위협이 될 수 있다. 대표적인 사례가 도메인 피싱이다.

유명한 도메인을 호모글리프로 비슷하게 만들어 사용자가 공식 사이트로 착각하게 유도하는 공격 방식이 존재한다. 영상에서는 “여기 들어가면 애플 공식 사이트가 나오는 게 아니라 이상한 사이트로 납치될 것”이라는 식으로 설명한다.

 

 

7.2 퓨니코드(Punycode) 표시

요즘 브라우저는 호모글리프 도메인을 발견하면 이를 퓨니코드로 바꿔서 보여주기도 한다. 즉, 사람이 보기에는 유사해 보이는 국제화 도메인을 그대로 보여주지 않고, 인코딩된 형태로 노출해 사용자가 이상함을 눈치채도록 돕는 장치가 있다.

따라서 URL만 잘 보면 위험하지 않을 수 있다는 취지의 설명이 이어지지만, 이는 어디까지나 사용자가 주의 깊게 확인할 때의 이야기이며, 자동화·백엔드 로직에서는 다른 층위의 위험이 발생한다.

 

 

 


8. 백엔드 검증 로직에서의 위험: ‘admin’ 차단이 무력화되는 이유

 

 

8.1 단순 문자열 필터링의 한계

백엔드에서 회원 가입 같은 기능을 구현할 때, ‘admin’ 같은 아이디를 막는 경우가 있다. 이는 사용자가 관리자 아이디로 가입해 관리자로 사칭하는 상황을 방지하기 위함이다.

그러나 호모글리프를 이용하면, 겉보기에는 ‘admin’으로 보이지만 실제로는 다른 코드 포인트의 문자들로 구성된 문자열을 만들 수 있다. 이 경우 단순 비교 기반의 필터링은 사실상 무력화된다.

영상은 이를 두고 “아무 쓸 데가 없다”는 강한 표현으로 경고한다.

 

 

8.2 실질적 대응: 허용 문자 집합 제한

이 문제에 대한 현실적인 대응으로 영상은 다음을 제시한다.

  • 아이디로 만들 수 있는 글자는 알파벳으로 한정하는 것이 좋다.
  • 즉, 허용 가능한 문자 집합을 엄격히 정의해 검증하는 방식이 안전하다.

 

이는 국제화 요구와 사용자 편의성 사이의 트레이드오프가 존재하지만, 계정·권한과 직결되는 식별자 영역에서는 보안적 관점이 우선될 수 있음을 시사한다.

 

 

 


9. 기술적 대응책과 그 한계

 

 

9.1 Zalgo가 보기 싫을 때: 프론트엔드(UI) 측 대응

Zalgo 텍스트가 UI를 깨뜨리는 것이 문제라면, 프론트엔드에서 우선 적용할 수 있는 접근으로 CSS overflow 속성을 만지는 방법이 언급된다. 즉, 텍스트가 레이아웃을 침범하지 못하도록 잘라내거나 스크롤 처리하는 식의 방어가 가능하다.

이 방식은 UI 파괴를 “표시 단계에서 완화”하는 접근이며, 입력 자체를 막는 것과는 별개로 작동한다.

 

 

9.2 백엔드에서 Zalgo 차단: 정규식 필터링의 비용

백엔드에서 Zalgo를 아예 막고 싶다면, 발음기호 같은 결합 문자를 정규식으로 걸러 버리는 방식도 가능하다. 그러나 영상은 이 방식이 CPU 낭비가 굉장히 심할 것이라고 평가한다.

즉, 성능 비용이 크고, 트래픽이 많은 환경에서는 방어 로직 자체가 부담이 될 수 있다.

 

 

9.3 다국어 환경의 현실: 발음 기호 중첩이 정당한 경우

또한 발음 기호를 여러 개 쓴다고 해서 무조건 악성으로 판단하는 것도 문제가 된다. 영상에서는 “발음 기호를 최대 여덟 개를 겹쳐 사용하는 다국어들도 있기 때문에” 무작정 차단하면 불편을 초래할 수 있다고 설명한다.

따라서 ‘결합 문자가 많다’는 이유만으로 차단하는 정책은 사용자 경험과 언어 지원 측면에서 부작용이 발생할 수 있다.

 

 

9.4 투명 문자 문제가 우려될 때: 스트립(제거) 가능성

투명 문자(예: ZWJ 등)가 문제가 될 것 같다면, 그 정도는 스트립(제거)해 주는 것이 괜찮을 수도 있다는 제안이 나온다. 즉, 완전 차단이 아니라 “표준 문법 기능 중 위험도가 높은 일부”를 제거하는 방식의 절충도 고려할 수 있다는 취지이다.

 

 


10. 결론: 유니코드의 복잡성과 감수해야 할 비용

유니코드 특성상 여러 가지 테러 행위도 가능하고, 보안 위협도 존재하며, 구현과 운영에서 귀찮은 점도 많다. 그럼에도 불구하고 세상에 있는 모든 문자를 자유롭게 표현하려면 어느 정도의 복잡성과 위험을 감수해야 하는 부분이 존재한다.

즉, 유니코드는 “문자 표현의 자유와 포괄성”을 얻기 위한 거대한 체계이고, 그 체계를 현실에서 안전하게 운용하려면 UI·백엔드·보안 정책·사용자 경험을 함께 고려한 균형 잡힌 대응이 필요하다.

 

 

 


실무 체크리스트(요약)

  • UI 파괴 완화: 텍스트 렌더링 영역에서 overflow 정책을 명확히 설정한다.
  • 식별자 정책 강화: 아이디/권한 관련 문자열은 허용 문자 집합을 엄격히 제한한다(예: 알파벳 한정).
  • 정규식 필터링 주의: 결합 문자를 전면 차단하는 접근은 성능 비용과 다국어 지원 부작용을 고려한다.
  • 투명 문자 리스크 대응: ZWJ 등 보이지 않는 문자로 인한 은닉·주입 가능성을 염두에 두고 필요한 범위에서 스트립한다.
  • 보안 인식: 호모글리프 도메인 피싱, 프롬프트 인젝션 등 “표시와 실제 데이터의 괴리”를 전제하고 검증 설계를 한다.

 

 

 


FAQ (2026 기준으로도 여전히 자주 묻는 질문)

 

Q1. Zalgo 문자는 왜 ‘버그’가 아니라 ‘표준 악용’에 가깝다고 하나?

Zalgo는 결합 문자를 중첩하는 방식인데, 결합 문자 자체는 유니코드가 다국어 표현을 위해 제공하는 문법 요소이기 때문이다. 많은 렌더러가 이를 정상적으로 처리하기 때문에 결과적으로 “표준이 허용한 방식으로 UI가 망가지는” 형태가 된다.

 

Q2. 결합 문자를 몇 개 이상 쓰면 무조건 악성으로 봐도 되나?

그렇지 않다. 영상에서는 발음 기호를 최대 8개까지 겹쳐 쓰는 언어도 있다고 언급한다. 따라서 단순 개수 기반 차단은 정상 사용자를 막을 수 있다.

 

Q3. UI가 깨지는 문제만 보면 프론트엔드에서만 막아도 충분한가?

UI 표시 문제는 overflow 같은 속성으로 완화할 수 있으나, 입력 데이터 자체가 다른 시스템(검색, 로깅, 알림, 에이전트 등)으로 흘러가면 다른 위험(은닉, 인젝션, 비교 우회)이 발생할 수 있다.

 

Q4. Zero Width Joiner는 왜 위험할 수 있나?

ZWJ는 보이지 않지만 문자를 결합해 표현을 바꾼다. 이런 투명 문자를 응용하면 데이터 은닉이나 비밀 메시지 삽입이 가능해지며, 일부는 이를 프롬프트 인젝션 같은 용도로도 사용한다.

 

Q5. 이모지 결합은 어떻게 가능한가?

곰+눈송이=북극곰, 남자+프라이팬=남자 요리사처럼 특정 조합은 미리 정의된 조합 규칙에 따라 렌더링된다. ZWJ는 이 결합을 구현하는 문법용 문자로 쓰인다.

 

Q6. 호모글리프는 왜 백엔드에서 특히 위험한가?

사람 눈에는 같은 문자열처럼 보여도 코드 포인트가 다르면 컴퓨터는 다른 문자열로 취급한다. ‘admin’ 차단처럼 단순 비교 필터는 외형만 같은 다른 문자로 우회될 수 있다.

 

Q7. 브라우저가 퓨니코드로 보여주면 도메인 피싱은 끝난 것 아닌가?

브라우저가 감지해 퓨니코드로 표시하는 경우가 있지만, 모든 상황에서 동일하게 보호되는 것은 아니다. 사용자가 URL을 제대로 확인하지 않거나, 앱/임베디드 환경에서는 표시 방식이 다를 수 있다.

 

Q8. 정규식으로 결합 문자를 다 제거하면 가장 안전한가?

영상에서는 CPU 낭비가 심할 수 있다고 지적한다. 또한 다국어에서 정당한 결합 문자 사용까지 막게 되어 사용자 불편을 유발할 수 있다.

 

Q9. ‘문자 하나로 아이폰이 재시작’ 같은 일은 실제로 왜 발생했나?

유니코드 렌더링 경로가 복잡하고, 특정 조합/표현을 처리하는 과정에서 OS나 렌더러가 오류를 내면 시스템이 뻗는 사건이 발생할 수 있다. 영상은 과거 아이폰에서 강제 재시작 사건이 있었음을 사례로 든다.

 

Q10. 최소한의 현실적 대책은 무엇인가?

식별자(아이디 등)처럼 보안적으로 민감한 문자열은 허용 문자 집합을 제한하고, UI 파괴는 표시 단계에서 overflow 등으로 완화하며, 투명 문자의 은닉 가능성은 필요한 범위에서 스트립하는 식으로 ‘위험도가 큰 지점부터’ 관리하는 접근이 현실적이다.

 

 

 


인용(발언 하이라이트)

“유니코드 특성상 여러 가지 테러 행위도 가능하고 보안 위협도 있고 이거저거 귀찮은 점도 있지만 결국 세상에 있는 모든 문자를 자유롭게 표현하려면 어느 정도 감수해야 하는 부분 같습니다.”

이 발언은 유니코드가 가진 양면성을 요약한다. 표현의 보편성과 자유를 얻기 위해 복잡성과 위험을 전부 제거할 수는 없으며, 결국 서비스 특성에 맞춘 정책과 방어 설계가 필요하다는 결론으로 연결된다.

반응형