글자수 세기 (공백 포함 · 제외)
공백 포함/제외, 바이트, 단어, 줄 수를 동시에
입력한 글은 브라우저 밖으로 나가지 않습니다.
글자수 (공백 포함)
0
띄어쓰기·줄바꿈을 모두 포함
글자수 (공백 제외)
0
띄어쓰기·탭·줄바꿈을 모두 제외 — 자소서 폼 기준
단어 (어절)
0
줄
0
문단
0
UTF-8
0B
EUC-KR
0B
글자수 제한 확인
기준이 제한마다 다릅니다
| 제한 | 기준 | 현재 | 남은 수 |
|---|---|---|---|
| 자기소개서 500자 | 공백 제외 | 0 / 500 | 500 |
| 자기소개서 1,000자 | 공백 제외 | 0 / 1,000 | 1,000 |
| 자기소개서 1,500자 | 공백 제외 | 0 / 1,500 | 1,500 |
| X(트위터) 게시물한글·한자는 2자로 계산돼 실제로는 약 140자 | 공백 포함 | 0 / 280 | 280 |
| 네이버 블로그 제목 | 공백 포함 | 0 / 100 | 100 |
| YouTube 영상 제목 | 공백 포함 | 0 / 100 | 100 |
| Instagram 캡션 | 공백 포함 | 0 / 2,200 | 2,200 |
| SMS 단문한글 45자 · 90바이트를 넘으면 LMS로 전환된다 | EUC-KR 바이트 | 0 / 90 | 90 |
같은 글인데 사이트마다 글자수가 다른 이유
글자수를 세는 건 쉬운 일처럼 보입니다. 실제로 어려운 건 세는 게 아니라 “글자 하나”가 무엇인지 정하는 일입니다. 놀랍게도 여기에는 정답이 하나가 아니고, 그래서 같은 글을 여러 사이트에 붙여넣으면 다른 숫자가 나옵니다.
자바스크립트에서 "글자".length를 부르면 글자 수가 나오는 것처럼 보입니다. 하지만 이 값이 실제로 세는 건 UTF-16 코드 단위입니다. 한글과 영문은 우연히 1대1로 맞아떨어져서 문제가 드러나지 않을 뿐입니다. 우연이 깨지는 순간 이런 일이 벌어집니다:
입력 .length [...str] 실제 글자
─────────────────────────────────────────────
가 1 1 1
a 1 1 1
😀 2 1 1
👨👩👧👦 11 7 1
é (e + ́) 2 2 1
한 (ᄒ+ᅡ+ᆫ) 3 3 1가족 이모지 하나가 11자로 세집니다. 이건 버그가 아니라 정의의 문제입니다. 👨👩👧👦는 사실 남자·여자·여아·남아 네 개의 이모지를 ZWJ(zero-width joiner, U+200D)라는 보이지 않는 접착제로 이어 붙인 것이고, 그 각각이 서로게이트 쌍(2코드 단위)이라 4×2 + 3 = 11이 됩니다. 트위터에 이모지 하나 넣었다고 남은 글자가 11자 줄어드는 경험을 해 봤다면 그 사이트가 .length를 쓰고 있었던 겁니다.
세는 방법은 세 가지고, 각각 다른 답을 준다
- 코드 단위 (
str.length) — 가장 빠르고 가장 틀립니다. 메모리에 몇 칸 차지하는지를 셀 뿐입니다. 그런데 대부분의 글자수 세기 사이트가 이걸 씁니다. 한 줄이면 되니까요. - 코드 포인트 (
[...str].length) — 이모지 하나는 제대로 1로 셉니다. 스프레드 연산자가 서로게이트 쌍을 붙여서 순회하기 때문입니다. 하지만 ZWJ 시퀀스는 7로, 결합 문자 é는 2로 셉니다. 절반만 맞는 답입니다. - Grapheme cluster (
Intl.Segmenter)— 유니코드가 정의한 “사람이 글자 하나라고 인식하는 단위”입니다. 위 표의 마지막 열이 이 값이고,이 도구가 쓰는 기준입니다.
const seg = new Intl.Segmenter("ko", { granularity: "grapheme" });
[...seg.segment("👨👩👧👦")].length; // 1Segmenter는 브라우저의 ICU 데이터를 쓰기 때문에 .length보다 훨씬 느립니다. 그래도 이걸 쓰는 이유는, 사용자가 “내 글이 몇 자냐”라고 물을 때 알고 싶은 게 메모리 사용량이 아니라 화면에 보이는 글자 개수이기 때문입니다.
“한”이 세 글자가 되는 순간
한글에는 유니코드가 남긴 고약한 함정이 하나 더 있습니다. 같은 글자를 두 가지 방식으로 적을 수 있다는 것입니다.
"한" // U+D55C — 완성형, 1 코드 포인트 (NFC)
"ᄒ" + "ᅡ" + "ᆫ" // U+1112 U+1161 U+11AB — 조합형, 3 코드 포인트 (NFD)화면에 렌더된 결과는 픽셀 단위로 동일합니다. 눈으로는 절대 구별할 수 없습니다. 그런데 코드 포인트 수는 1 vs 3이고, UTF-8 바이트는 3 vs 9입니다.
이게 이론상의 이야기가 아닌 이유는 macOS때문입니다. macOS의 파일 시스템은 파일명을 NFD로 저장하고, 일부 앱이 그 형태를 그대로 클립보드에 올립니다. 그래서 맥에서 쓴 글을 회사 폼에 붙여넣었더니 500자 제한에 “1,400자”라고 뜨는 일이 실제로 벌어집니다. 사용자는 자기 글을 세 번 세어 봐도 원인을 찾을 수 없습니다. 보이지 않는 차이니까요.
해법은 세기 전에 정규화하는 것 한 줄입니다:
text.normalize("NFC") // 조합형 자모를 완성형으로 합친다이 도구는 입력을 받자마자 NFC로 정규화하고, 그 다음에 셉니다. 그래서 어느 OS에서 붙여넣어도 같은 숫자가 나옵니다. 참고로 grapheme 기준으로는 정규화 없이도 “한”이 1자로 나옵니다 — Segmenter가 자모를 다시 한 덩어리로 묶어 주기 때문입니다. 하지만 바이트 수는 정규화하지 않으면 진짜로 3배가 되고, 여러분이 상대할 폼은 Segmenter를 쓰지 않습니다.
왜 한국에서만 ‘공백 제외’를 이렇게 찾을까
영어권 글자수 도구에는 “excluding spaces”가 구석에 작게 있거나 아예 없습니다. 한국에서만 이게 headline 숫자인 이유는 하나입니다 — 자기소개서 입력 폼이 그렇게 센다.
여기서 사람들이 놓치는 게 줄바꿈도 공백이라는 점입니다. 대부분의 폼은 text.replace(/\s/g, "").length 같은 코드를 쓰고, 정규식의 \s는 스페이스뿐 아니라 탭·줄바꿈·전각 공백(U+3000)·NBSP(U+00A0)까지 전부 포함합니다. 문단을 열 번 나눈 글이라면 그것만으로 수십 자가 사라집니다. 이 도구도 같은 정의를 씁니다.
NBSP와 전각 공백을 굳이 언급하는 이유가 있습니다. 워드에서 복사하면 NBSP가, 한글(HWP)에서 복사하면 전각 공백이 섞여 들어옵니다. 둘 다 눈에는 그냥 공백으로 보이는데, 이걸 빼지 않는 도구를 쓰면 “공백 제외” 숫자가 이유 없이 커집니다.
UTF-8 3바이트 vs EUC-KR 2바이트 — 진짜 사고가 나는 곳
바이트 수는 개발자용 부가 정보처럼 보이지만, 한국에서 실제로 장애를 만드는 값입니다.
"한글" UTF-8 → 6 바이트 (글자당 3)
"한글" EUC-KR → 4 바이트 (글자당 2)
"ab" 둘 다 → 2 바이트 (ASCII 는 1)이 차이가 VARCHAR(100) 컬럼에 몇 글자가 들어가는지를 바꿉니다. MySQL의 utf8mb4에서 VARCHAR(100)은 100글자지만, 오래된 시스템의 VARCHAR(100)은 100바이트여서 한글은 50자, EUC-KR이면 50자, UTF-8 바이트 기준이면 33자만 들어갑니다. 같은 스키마 정의가 charset에 따라 세 가지 답을 냅니다.
여기서 나오는 전형적인 프로덕션 버그가 “잘린 한글”입니다. 100바이트에서 자르면 33.3번째 글자의 한가운데가 잘려서, 마지막 글자가 ?나 �로 저장됩니다. 화면 어디선가 깨진 글자가 하나씩 보이기 시작하는데 재현이 안 되는 이유가 이겁니다 — 입력이 딱 경계에 걸릴 때만 터집니다.
그리고 이모지는 UTF-8에서 4바이트입니다. MySQL의 예전 기본값이던 utf8(실제로는 utf8mb3, 최대 3바이트)에 이모지를 넣으면 그대로 에러가 납니다. “한글은 잘 되는데 이모지만 안 저장돼요”의 정체입니다.
위 계산기의 EUC-KR 값에 대해서는 정직하게 밝혀 둡니다. 이건 진짜 CP949 인코딩이 아니라 ASCII는 1, 나머지는 2로 세는 계산입니다. 그런데 이게 바로 관공서·대학 폼과 구형 게시판이 실제로 쓰는 방식입니다. 그쪽 코드는 대개 charAt(i) > 127 ? 2 : 1한 줄이거든요. 사용자가 알고 싶은 건 “CP949 표준이 뭐냐”가 아니라 “그 폼이 내 글을 몇 바이트로 셀 것이냐”이므로, 표준이 아니라 현실을 재현했습니다.
단어 수는 애매하다 — 그리고 그건 고칠 수 없다
영어의 word count는 정의가 명확합니다. 공백으로 끊으면 그게 단어입니다. 한국어는 그렇지 않습니다.
“학교에서”는 공백 기준으로 1어절이지만, 형태소로 쪼개면 학교 + 에서 로 2개입니다. “만났다”는 만나 + 았 + 다 로 3개입니다. 어느 쪽이 “단어 수”냐는 질문에는 국어학적으로도 맥락에 따라 답이 갈립니다.
형태소 분석은 사전과 통계 모델이 필요한 작업이고, 타이핑할 때마다 브라우저에서 돌릴 수 있는 일이 아닙니다. 그래서 이 도구는 공백 기준 어절로 정의하고 화면에도 그렇게 적었습니다. 애매한 값을 “단어 수”라는 이름으로 그럴듯하게 감추는 것보다, 무엇을 세고 있는지 밝히는 편이 쓸모 있습니다. 영어 원고의 단어 수를 볼 때는 이 값이 정확합니다.
정리하면
- 글자수는 하나의 숫자가 아닙니다. 이모지·결합 문자가 없다면 어떤 방법으로 세도 같지만, 하나라도 있으면 세 가지 다른 답이 나옵니다. 이 도구는 사람이 보는 단위를 기준으로 삼습니다.
- 제출 직전에는 실제 폼에 붙여넣어 확인하세요. 이 도구가 아무리 정확해도, 여러분을 심사하는 건 그 폼의 계산식입니다. 500자 제한에 499자를 채워 놓는 것보다 480자쯤에 여유를 두는 게 안전합니다.
- 숫자가 예상과 다르면 보이지 않는 문자를 의심하세요. NFD로 분해된 자모, 워드에서 딸려 온 NBSP, 윈도우의 CR — 전부 눈에 보이지 않으면서 숫자를 바꿉니다.
자주 묻는 질문
- 사이트마다 글자수가 다르게 나오는데 어느 쪽이 맞나요?
- 이모지나 결합 문자가 없는 순수 한글·영문이라면 어디서 세든 같은 숫자가 나와야 정상이고, 다르다면 공백을 세는 기준이 다른 것입니다. 반대로 이모지가 들어 있으면 사이트마다 다른 게 당연합니다. 대부분의 글자수 세기 사이트가 자바스크립트의 .length를 그대로 쓰는데, 이건 글자가 아니라 UTF-16 코드 단위를 세는 값이라 😀 하나를 2로 셉니다. 이 도구는 Intl.Segmenter로 사람이 보는 글자(grapheme cluster) 단위를 세기 때문에 1로 나옵니다.
- 자기소개서의 '공백 제외'에 줄바꿈도 포함되나요?
- 네, 이 도구는 띄어쓰기·탭·줄바꿈을 모두 공백으로 보고 뺍니다. 대부분의 채용 사이트 입력 폼도 같은 방식(정규식 \s 제거)으로 계산합니다. 문단을 많이 나눈 글이라면 줄바꿈만으로 수십 자가 차이 날 수 있으니, 제출 직전에는 실제 폼에 붙여넣어 최종 확인하는 것이 안전합니다.
- 맥에서 복사한 글을 붙여넣으니 글자수가 이상하게 늘어납니다.
- macOS는 유니코드를 NFD(분해형)로 저장하는 곳이 있어서, '한'이 초성 ᄒ + 중성 ᅡ + 종성 ᆫ 세 개의 코드 포인트로 들어오는 경우가 있습니다. 화면에 보이는 모양은 완전히 같은데 숫자만 최대 3배가 됩니다. 이 도구는 입력을 먼저 NFC로 정규화하기 때문에 어느 쪽으로 붙여넣어도 같은 숫자가 나오지만, 다른 사이트나 폼에서는 그대로 3배로 세질 수 있습니다.
- UTF-8 바이트와 EUC-KR 바이트는 왜 다른가요?
- 같은 한글 한 글자를 UTF-8은 3바이트로, EUC-KR(CP949)은 2바이트로 저장하기 때문입니다. 관공서·대학 폼이나 오래된 게시판은 아직 EUC-KR 기준으로 글자수를 제한하는 경우가 많고, SMS 90바이트 제한도 이쪽 계산을 씁니다. 다만 이 도구의 EUC-KR 값은 'ASCII는 1, 나머지는 2'라는 계산으로, 그런 폼들이 실제로 쓰는 방식을 그대로 재현한 근사값입니다.
- 단어 수는 어떤 기준으로 세나요?
- 공백으로 끊은 어절을 셉니다. '학교에서 만났다'는 2로 나옵니다. 한국어에서 '단어'를 형태소 단위로 보면 학교 + 에서 + 만나 + 았 + 다처럼 훨씬 많아지지만, 그건 사전과 분석기가 필요한 작업이라 브라우저에서 즉시 계산할 수 있는 범위를 넘습니다. 영어 원고의 단어 수(word count)를 확인하는 용도로는 그대로 신뢰해도 됩니다.
- 입력한 글이 서버로 전송되나요?
- 아닙니다. 모든 계산은 브라우저 안에서 끝나고, 입력한 텍스트는 어디로도 전송되거나 저장되지 않습니다. 자기소개서처럼 민감한 글을 붙여넣어도 페이지를 닫는 순간 사라집니다.