모든 콘텐츠 크리에이터가 알아야 할 이모지 인코딩
이모지는 이미지가 아니라 텍스트입니다. 이모지는 코드포인트, 대리 쌍, ZWJ 시퀀스, 변이 선택자를 가집니다. 대부분의 콘텐츠 크리에이터는 이모지를 불투명한 글리프로 취급합니다. 인코딩이 중요하며, 버그는 실제로 존재합니다.
Lois Chen·이모지 문화 리서처 + 플랫폼별 가이드 작가·2026년 6월 20일

대부분의 콘텐츠 크리에이터는 이모지를 불투명한 이미지로 취급합니다. 선택기를 클릭하고, 적절한 얼굴을 찾아서 보내면 수신자 기기가 자체 방식으로 렌더링합니다. 이 방식은 95%의 경우에 작동합니다. 나머지 5%, 깨진 문자열, 끊긴 클러스터, 이모지 대신 나타나는 물음표, 플랫폼별 렌더링, 는 이모지가 텍스트이고 인코딩이 중요하기 때문에 발생합니다.
이모지는 이미지가 아니라 텍스트입니다
이모지에 대해 가장 중요한 사실은 이미지가 아니라 텍스트라는 점입니다. 각 이모지는 유니코드 코드포인트(Unicode Consortium이 할당한 숫자)를 가지며, 그 코드포인트는 텍스트 스트림의 일부로 저장됩니다. 😂을 포함한 메시지를 보낼 때, 메시지에는 코드포인트 U+1F602가 들어 있으며 수신자 기기가 자체 글리프를 사용해 이를 렌더링합니다.
같은 코드포인트라도 플랫폼마다 다르게 렌더링됩니다. 각 플랫폼이 자체 글리프를 그리기 때문입니다. 😂은 iOS에서는 평평한 노란색 얼굴, Google에서는 얼룩덜룩한 색 덩어리, Samsung에서는 3D 렌더링, Twitter 이미지 프록시에서는 고대비 단색으로 나타납니다. 코드포인트는 같고, 그리기는 플랫폼에 따라 다릅니다. 이 모델은 라틴 알파벳과 동일합니다. "A"의 코드포인트는 U+0041이며, "A"의 모양은 글꼴에 따라 다릅니다.
기본: 코드포인트와 UTF-8
모든 유니코드 문자는 U+ 접두사가 붙은 16진수 코드포인트를 가집니다. 이모지 코드포인트는 보충 다국어 평면(Supplementary Multilingual Plane, SMP)에 있으며, 이는 U+FFFF 이상이라는 뜻입니다. 이 지점에서부터 인코딩이 흥미로워집니다.
UTF-8(현재 웹에서 가장 널리 쓰이는 인코딩)에서 각 코드포인트는 1~4 바이트로 인코딩됩니다. 이모지는 항상 4 바이트입니다. UTF-16(JavaScript 문자열과 Windows가 사용하는 인코딩)에서는 U+FFFF 이상의 코드포인트가 대리 쌍(surrogate pair)으로 인코딩됩니다. 대리 쌍은 하나의 코드포인트를 표현하는 두 개의 16비트 코드 유닛입니다. 이것이 바로 이모지가 JavaScript에서 길이가 1이 아니라 2인 이유입니다. JavaScript에서 "😂".length === 2입니다. 이는 문자 카운팅을 수행하는 많은 프런트엔드 코드에서 문제를 일으킵니다.
흔한 이모지 코드포인트
| 이모지 | 코드포인트 | UTF-8 바이트 | UTF-16 코드 유닛 |
|---|---|---|---|
| 😂 | U+1F602 | 4 | 2 |
| ❤️ | U+2764 U+FE0F | 6 | 4 |
| 👨👩👧 | U+1F468 U+200D U+1F469 U+200D U+1F467 | 17 | 10 |
| 🇺🇸 | U+1F1FA U+1F1F8 | 8 | 4 |
마지막 행이 흥미롭습니다. 🇺🇸(미국 국기)은 두 개의 지역 표시기호 코드포인트(U+1F1FA는 "U", U+1F1F8은 "S")가 결합되어 국기 글리프를 형성합니다. 국기 자체만을 위한 코드포인트는 없습니다. 페어로부터 계산됩니다. 이것이 바로 사용자가 "US"를 입력하면 지역 표시기호를 지원하는 플랫폼에서 🇺🇸을 얻을 수 있지만, 내부 데이터는 하나가 아니라 두 코드포인트인 이유입니다.
일부 이모지가 여러 코드포인트인 이유
일부 이모지는 단일 코드포인트입니다(😂은 그저 U+1F602일 뿐입니다). 일부는 시퀀스입니다. 👨👩👧(가족: 남자, 여자, 소녀)은 제로 너비 결합자(U+200D)로 연결된 다섯 개의 코드포인트입니다. U+1F468(남자) + U+200D(ZWJ) + U+1F469(여자) + U+200D(ZWJ) + U+1F467(소녀). ZWJ는 렌더러에 대한 지시입니다. "나의 양쪽에 있는 코드포인트를 하나의 글리프로 묶어라."
이것은 강력한 메커니즘입니다. 사용자는 어떤 구성의 가족이든 만들 수 있습니다, 👨👩👧👦(두 부모, 두 자녀) 또는 👨👨👧(두 아버지, 한 딸), 코드포인트를 순서대로 입력하면 됩니다. 단, 어떤 플랫폼도 그 정확한 조합을 한 번도 렌더링한 적이 없어도 됩니다. 결과는 렌더링 플랫폼이 ZWJ 시퀀스를 인식하는지에 따라 달라집니다. 대부분의 최신 플랫폼은 인식하지만, 렌더링은 차이가 있을 수 있으며 오래된 플랫폼은 이모지를 별도의 글리프로 표시할 수도 있습니다.
대리 쌍과 JavaScript
대리 쌍 문제는 JavaScript에서 발생하는 많은 이모지 버그의 근원입니다. JavaScript 문자열은 UTF-16이며, U+FFFF 이상의 코드포인트는 두 개의 16비트 코드 유닛(상위 대리와 하위 대리)으로 저장됩니다. 즉, 문자열에 두 개의 UTF-16 코드 유닛이 포함되어 있으므로 "😂".length === 2이며, 1이 아닙니다.
가장 흔한 버그는 문자 카운팅입니다. 단순한 message.length는 사용자 인지 문자가 아니라 UTF-16 코드 유닛의 개수를 반환합니다. 5개의 이모지와 10개의 ASCII 문자가 있는 메시지는 길이가 15가 아니라 20으로 보고됩니다. 해결책은 전개 연산자([...message].length) 또는 Intl.Segmenter API를 사용하는 것이며, 둘 다 코드포인트 또는 그래핌 클러스터(grapheme cluster) 단위로 셉니다.
변이 선택자
변이 선택자(Variation Selector)는 이전 코드포인트의 렌더링 방식을 바꾸는 코드포인트입니다. 가장 흔한 것은 U+FE0F(VARIATION SELECTOR-16, VS-16)로, 텍스트 스타일도 함께 가진 문자를 이모지 스타일로 강제합니다.
가장 명확한 예는 하트입니다. ❤(U+2764)는 기본적으로 텍스트 스타일의 하트 글리프로 렌더링됩니다. 무겁고 어두운 빨간색의 인쇄용 딩벳처럼 보이는 하트입니다. ❤️(U+2764 U+FE0F)는 같은 하트 코드포인트에 VS-16을 더한 것으로, 이모지 스타일을 강제합니다. 밝은 빨간색에 광택이 있는 하트 글리프입니다. 두 결과는 매우 다르게 렌더링되며, 그 차이는 단 하나의 코드포인트입니다.
이것이 바로 이모지 선택기에서 "heart"를 입력했을 때의 결과와 유니코드 이름을 직접 입력하여 얻는 결과가 다른 이유입니다. 선택기는 자동으로 변이 선택자를 추가합니다. 손으로 입력한 bare 코드포인트는 추가하지 않습니다.
피부톤 변형자
Fitzpatrick 척도의 이모지 변형자(U+1F3FB~U+1F3FF)는 이를 지원하는 이모지의 피부톤을 변경합니다. 🏋️(역도 선수)는 U+1F3CB(역도 선수) + U+FE0F(VS-16) + U+1F3FB(밝은 피부톤)의 조합입니다. 변형자가 없으면 기본 노란색 이모지가 사용됩니다. 변형자가 있으면 특정 피부톤이 렌더링됩니다.
알아야 할 중요한 점은 피부톤 변형자가 명시적으로 이를 수용하도록 설계된 이모지에만 작동한다는 것입니다. 비지원 이모지에 피부톤 변형자를 추가해도 아무 일도 일어나지 않습니다(변형자는 무시됩니다). 일부 플랫폼은 비지원 조합을 일관되지 않게 처리합니다. Forgemoji 생성기는 유니코드 명세를 따릅니다. 지원되는 조합은 피부톤을 받고, 지원되지 않는 조합은 기본 노란색을 받습니다.
흔한 버그와 회피 방법
- •데이터베이스의 깨진 문자열. ISO-8859-1이나 그 이전 인코딩을 기대하는 데이터베이스에 이모지를 저장하면 데이터가 손상됩니다. 전체 스택에서 UTF-8을 사용하십시오.
- •길이 계산. 단순한 문자 카운팅은 이모지가 많은 콘텐츠의 "사용자 인지 길이"를 과소평가합니다. 그래핌 클러스터(grapheme cluster)를 사용하십시오.
- •검색 인덱싱. 검색 엔진이 공백을 기준으로 토큰화하면 이모지는 주변 텍스트의 일부로 인덱싱됩니다. 대부분의 최신 검색 엔진(Elasticsearch, OpenSearch, Algolia)은 올바른 토크나이저에서 이모지를 올바르게 처리합니다.
- •접근성. 화면 판독기는 CLDR 짧은 이름을 읽습니다. 맞춤 이모지나 AI 생성 이모지의 경우 짧은 이름이 잘못되거나 누락될 수 있습니다. 화면 판독기로 테스트하십시오.
- •데이터베이스 저장 한계. VARCHAR(255)는 문자 수가 아니라 코드 유닛을 셉니다. utf8mb4 인코딩을 사용하는 MySQL의 VARCHAR(255) 컬럼은 255자를 저장할 수 있지만 바이트 한도는 문자당 4 바이트이므로 이모지가 많은 콘텐츠의 실제 저장 예산은 1020 바이트입니다. 그에 맞게 계획하십시오.
실무 요점
- •전체 스택에서 항상 UTF-8을 사용하십시오. 2026년에 이전 유니코드 인코딩을 사용할 합리적인 이유는 없습니다.
- •길이에 민감한 코드(데이터베이스 컬럼, 문자 카운터)에는 UTF-16 코드 유닛이 아닌 그래핌 클러스터 또는 코드포인트를 사용하십시오.
- •사용자에게 중요한 플랫폼에서 이모지 렌더링을 테스트하십시오. iOS, Android, Windows는 다르게 렌더링합니다.
- •ZWJ 시퀀스는 오래된 기기에서 테스트하십시오. 2018년에 렌더링이 일관되지 않았고, 2026년에도 아직 완전히 일관되지 않습니다.
- •변이 선택자는 중요합니다. 이모지 스타일을 원하면 VS-16을 추가하십시오. 원하지 않으면 추가하지 마십시오.
Forgemoji는 깨끗한 투명 PNG를 출력합니다. 인코딩은 사용자의 몫이지, 저희의 몫이 아닙니다, 다만 엔지니어링 노트에 ZWJ 시퀀스에 대한 심층 기술 문서가 있습니다.
구현 원리 보기 →참고 자료
추천 다음 읽기
- •이모지가 어떻게 언어가 되었는가: 유니코드 기호에서 문화적 속기법까지 — 코드포인트와 이름이 중요한 이유
- •이모지 접근성 가이드: 모든 사람이 읽을 수 있는 맞춤 이모지 만들기 — 인코딩을 실무에 적용
- •투명 PNG, GIF, WebP 내보내기를 지원하는 AI 이모지 생성기를 만드는 방법 — 내보내기 형식이 다른 이유
출처
Source: 유니코드 16.0 핵심 명세 . 보충 문자와 이모지 — 유니코드 컨소시엄 (2026년 6월 확인)
Source: MDN . 문자열 length와 대리 쌍 — Mozilla Developer Network (2026년 6월 확인)
Lois Chen·콘텐츠 편집자
검토일: 2026년 6월 20일
작성 방법: 블로그 글은 1차 플랫폼 테스트(Discord 서버, Telegram 그룹, TikTok), r/discordapp과 Telegram 스티커 커뮤니티의 파워 유저 인터뷰, 그리고 매주 Unicode 릴리스 노트 확인을 바탕으로 작성됩니다. 모든 가이드는 최소 한 명의 편집자가 기술적 정확성을 검토하며, 해당 플랫폼의 규칙이 바뀌면 업데이트합니다. 이모지 사용 데이터는 공개된 Google Trends, UDF(Unicode 이모지 사용 빈도) 보고서, 그리고 저희 Forgemoji 생성 로그에서 수집합니다.
출처: Forgemoji 내부 편집 팀 — 개별 기여자 정보는 '팀 소개' 페이지를 참고하세요
