아스키코드 변환기 (문자 ↔ ASCII 코드)
문자를 아스키코드로, 코드를 문자로 — 10·16·2·8진 동시에
각 글자를 코드로 바꿉니다. 한글·이모지는 ASCII가 아니라 코드포인트로 표시합니다
아스키코드표 (0~127)
회색은 제어문자각 칸: 10진 코드 · 문자. 칸에 마우스를 올리면 16진값과 제어문자 이름이 보입니다. 0~31과 127은 화면에 안 찍히는 제어문자(NUL·TAB·LF 등), 32는 공백(SP)입니다.
아스키코드는 “글자에 번호를 매긴 표” 하나입니다
컴퓨터는 글자를 모릅니다. 0과 1, 곧 숫자만 압니다. 그래서 A를 저장하려면 먼저 글자마다 번호를 정해 두는 약속이 필요합니다. 그 약속 가운데 가장 오래되고 모든 것의 바탕이 된 것이 ASCII(American Standard Code for Information Interchange, 1963)입니다. A는 65번, a는 97번, 공백은 32번 — 이렇게 0부터 127까지 128개 글자에 번호를 매긴 표가 전부입니다. 위 변환기가 하는 일도 그 표를 양방향으로 찾아 주는 것뿐입니다.
왜 하필 127까지일까요. ASCII는 7비트 부호이기 때문입니다. 비트 일곱 개로 만들 수 있는 경우의 수가 27 = 128가지라, 0~127로 딱 떨어집니다. 그 시절 한 바이트(8비트)에서 남는 한 비트는 통신 오류를 잡는 검사용으로 썼습니다. 이 “2의 거듭제곱” 감각이 낯설다면 진법 변환기에서 왜 16진 한 자리가 4비트인지부터 보면 전체 그림이 맞춰집니다.
표에는 세 구역이 있습니다
128칸은 아무렇게나 채워진 게 아니라 세 덩어리로 나뉩니다.
- 제어문자 (0~31, 그리고 127) — 화면에 안 찍히는명령입니다. 줄바꿈(LF·10), 탭(HT·9), 널(NUL·0), 백스페이스(BS·8), 벨(BEL·7) 등. 글자가 아니라 “동작”이라 변환기와 아래 표에서는
LF·TAB같은 약어로 보여 줍니다. - 기호와 숫자 (32~64) — 공백(32), 문장부호, 그리고 숫자
0~9(48~57). - 글자 (65~122) — 대문자
A~Z(65~90), 소문자a~z(97~122).
이 순서에는 뜻이 있습니다. 숫자가 글자보다 앞이고, 대문자가 소문자보다 앞입니다. 그래서 문자열을 코드값으로 그냥 정렬하면 Zebra가 apple보다 앞에 옵니다 — 대문자 Z(90)가 소문자 a(97)보다 작기 때문입니다. “사전순으로 정렬했는데 대문자만 위로 몰리는” 흔한 현상이 바로 이 아스키 순서의 결과입니다.
대소문자가 정확히 32 차이인 이유
표에서 가장 우아한 부분입니다. 같은 글자의 대문자와 소문자는 코드가 항상 정확히 32 차이 납니다.
A = 65 = 100 0001
a = 97 = 110 0001
└ 이 한 비트(값 32 = 0x20)만 다르다32는 2진수로 100000, 곧 비트 하나(0x20)입니다. A에 그 비트를 켜면 a가 되고, 끄면 다시 A가 됩니다. 대소문자 변환을 뺄셈도 조건문도 없이 비트 하나 토글로 처리하려고 설계자가 A~Z와 a~z를 일부러 그 간격에 놓은 것입니다. 위 변환기에서 A와 a를 각각 넣어 2진 열을 비교하면, 정말 여섯 번째 자리 하나만 다른 것이 보입니다. 이건 케이스 변환기가 camelCase·snake_case를 다루는 것과는 다른 층위의 이야기입니다 — 저기는 표기법, 여기는 글자 한 개의 비트입니다.
숫자 문자 ‘5’는 숫자 5가 아니다
같은 원리가 숫자에도 있습니다. 문자 '5'의 코드는 53이지 5가 아닙니다. 숫자 문자 0~9가 48~57에 연속으로 놓여 있어서, 문자에서 48('0'의 코드)을 빼면 진짜 숫자가 됩니다 — 53 − 48 = 5. 사용자가 입력창에 친 "5"는 글자라 그대로 더하면 문자열이 이어 붙을 뿐("5" + "3" = "53") 계산이 안 됩니다. 텍스트로 들어온 숫자를 변환 없이 계산에 넣어 생기는 버그의 뿌리가 이 48 간격입니다.
줄바꿈은 왜 둘인가: CR과 LF
제어문자 중 실무에서 가장 자주 부딪히는 건 줄바꿈입니다. 그런데 줄바꿈 코드는 하나가 아니라 둘입니다.
CR (13, \r) — 커서를 줄 맨 앞으로 (Carriage Return)
LF (10, \n) — 종이를 한 줄 아래로 (Line Feed)타자기에서 “다음 줄로”는 두 동작이었습니다 — 레버를 밀어 종이를 올리고(LF), 헤드를 왼쪽 끝으로 되돌리기(CR). 초기 컴퓨터가 이 관습을 그대로 물려받아, Windows는 줄 끝에 CR+LF 둘을, macOS·Linux는 LF 하나만 씁니다. 같은 텍스트 파일이 다른 OS에서 줄이 안 나뉘거나 줄 끝에 ^M이 붙어 보이는 문제가 정확히 여기서 옵니다. 참고로 여러 줄 텍스트의 CR/LF를 통일하고 눈에 안 보이는 제어·공백문자를 걷어내는 일은 이 zone이 아니라 형제 사이트 TextKit의 공백·줄바꿈 정리 도구가 맡습니다 — 이 변환기는 “한 글자 = 한 코드”를 보는 데 집중합니다.
“확장 아스키”라는 함정, 그리고 한글
여기서부터가 표만 보고는 알 수 없는, 그러나 문자 깨짐(���·?)의 원인 대부분을 설명하는 부분입니다. 순수 ASCII는 0~127, 128자가 전부입니다. 그런데 한 바이트는 0~255까지 담을 수 있으니, 남는 128~255 자리에 각자 글자를 얹기 시작했습니다. 문제는 그 표가 하나가 아니라는 것입니다.
- ISO-8859-1(서유럽)에서 200번은
È - Windows-1252에서는 조금 다르고
- CP949(옛 한글 인코딩)에서는 두 바이트를 묶어 한글 한 글자를 만듭니다
그래서 “확장 아스키”는 표준이 아니라 서로 안 맞는 여러 표의 모음입니다. 같은 200번이 어느 프로그램에서 열었느냐에 따라 다른 글자가 되고, 이것이 이메일·CSV·오래된 파일에서 글자가 깨지는 근본 원인입니다.
한글은 더 근본적으로 ASCII 밖입니다. 한글 음절은 11,172자라 256칸에 애초에 들어가지 않습니다. 그래서 한글은 ASCII가 아니라 유니코드를 씁니다 — 가는 코드포인트 U+AC00(10진 44032)입니다. 이 변환기에 한글을 넣으면 코드는 계산해 보여 주되 “ASCII 아님”을 함께 표시합니다. 모르는 것을 아는 척 ?로 뭉개지 않기 위해서입니다. 이 유니코드 코드포인트를 HTML에 가처럼 넣거나 되돌리는 일은 HTML 엔티티 변환기가, 값을 16진·2진으로 펼쳐 보는 일은 진법 변환기가 이어받습니다.
정리
ASCII는 0~127의 글자에 번호를 매긴 7비트 표 하나입니다. 제어문자·숫자· 대문자·소문자가 이 순서로 놓였고, 그 배치 덕분에 대소문자는 비트 하나(32) 차이, 숫자 문자는 48만 빼면 값이 됩니다. 줄바꿈이 CR·LF 둘로 갈리는 것도, 128~255의 “확장 아스키”가 서로 안 맞는 것도, 한글이 여기 없는 것도 모두 이 128칸의 한계에서 나옵니다. 화면 위쪽 변환기로 코드를 확인하고, 아래 0~127 아스키코드표를 옆에 두면 표가 더는 외울 대상이 아니라 “구조가 보이는 지도”가 됩니다.
자주 묻는 질문
- 왜 대문자 A가 65인가요?
- 1963년 ASCII를 설계할 때 코드 배치를 '쓰기 편하게'가 아니라 '기계가 처리하기 편하게' 정했기 때문입니다. 0~31은 화면에 안 찍히는 제어문자, 32는 공백, 33~47은 기호, 48~57은 숫자 0~9, 65~90은 대문자 A~Z, 97~122는 소문자 a~z 순서입니다. 숫자 0이 48(16진 0x30), 대문자 A가 65(0x41), 소문자 a가 97(0x61)로 딱 떨어지는 자리에 놓인 건 우연이 아니라, 뒤에 설명하는 비트 연산 트릭을 쓰려고 일부러 그렇게 배치한 것입니다.
- 대문자와 소문자 코드가 왜 정확히 32 차이인가요?
- 대소문자 변환을 뺄셈이 아니라 비트 하나로 처리하려고 그렇게 맞췄습니다. 32는 2진수로 100000, 즉 여섯 번째 비트(0x20) 하나입니다. A(65, 1000001)에 이 비트를 켜면 a(97, 1100001)가 되고, 끄면 다시 A가 됩니다. 그래서 옛 코드가 소문자로 바꿀 때 'code | 0x20', 대문자로 바꿀 때 'code & ~0x20'을 쓰는 걸 볼 수 있습니다. 위 변환기에서 A와 a를 각각 2진으로 보면 딱 그 한 자리만 다른 것이 눈에 보입니다.
- 확장 아스키코드(128~255)는 뭔가요? 한글도 아스키코드가 있나요?
- 순수 ASCII는 0~127까지, 딱 128자뿐입니다. 128~255는 '확장 아스키'라고 부르지만 표준이 하나가 아닙니다 — Windows-1252, ISO-8859-1(라틴), CP949(한글) 등 나라·프로그램마다 다른 표를 그 자리에 얹었습니다. 그래서 같은 200번이 어디서는 é, 어디서는 다른 글자입니다. 한글은 그 256칸에 다 담을 수 없어(11,172자) 애초에 ASCII가 아니라 유니코드를 씁니다. 이 변환기에 한글을 넣으면 코드는 보여 주되 'ASCII 아님'을 함께 표시하는 이유입니다.
- 줄바꿈(엔터)의 아스키코드는 무엇인가요? CR과 LF는 왜 둘인가요?
- 줄바꿈은 하나가 아니라 둘입니다 — LF(10, \n)와 CR(13, \r). 타자기 시절 '커서를 줄 맨 앞으로(CR)' 와 '종이를 한 줄 올리기(LF)' 가 별개 동작이었던 데서 왔습니다. 그 유산으로 지금도 Windows는 줄 끝에 CR+LF 둘을, macOS·Linux는 LF 하나만 씁니다. 같은 파일이 한쪽에서 줄이 안 나뉘거나 줄 끝에 ^M이 보이는 문제가 여기서 생깁니다. 줄바꿈 문자 통일은 이 zone의 형제 도구인 텍스트 정리 도구가 다룹니다.
- DEL(127)은 제어문자인데 왜 맨 끝에 있나요?
- 천공 카드(종이 테이프)의 흔적입니다. 다른 제어문자는 0~31에 모여 있는데 DEL만 127, 즉 2진수로 1111111(일곱 비트 전부 1)입니다. 종이 테이프에 이미 뚫은 구멍은 메울 수 없으니, 잘못 친 자리는 구멍 일곱 개를 전부 뚫어 '삭제(DEL)'로 표시했습니다. 그 값이 그대로 127에 남은 것입니다. 그래서 DEL은 제어문자면서도 코드표의 맨 끝에 홀로 있습니다.
- 숫자 '5'와 숫자 5는 왜 다른가요?
- 문자 '5'의 아스키코드는 53(16진 0x35)이고, 정수 5는 그냥 5입니다. 둘은 완전히 다른 값입니다. 그래서 문자로 받은 '5'를 숫자로 쓰려면 코드에서 48('0'의 코드)을 빼야 합니다 — 53 − 48 = 5. 숫자 문자 0~9가 48~57에 연속으로 놓인 덕분에 이 뺄셈 하나로 어떤 숫자 문자든 값으로 바뀝니다. 텍스트로 들어온 숫자를 계산에 바로 썼다가 틀리는 버그가 이 차이를 몰라서 납니다.