개발자
진법 변환기
2·8·10·16진 변환 + 비트 시각화 + 2의 보수·ASCII·비트 연산.
1111 1111
377
255
FF
- 255 — 8비트 부호 없는 최대값 (2⁸ − 1)
| C / C++ / Java | 0xFF | 0b11111111 | 0377 |
| Python | 0xff | 0b11111111 | 0o377 |
| JavaScript | 0xFF | 0b11111111 | 0o377 |
| CSS 색상 | #0000FF | — | — |
#0000FF 색상 코드 변환기에서 보기 →실무 HEX 덤프 읽기 — 파일 시그니처(매직 넘버)
확장자를 지워도 파일 종류를 알아낼 수 있는 이유는, 대부분의 파일 포맷이 첫머리 몇 바이트에 고유한 식별자(매직 넘버)를 규격으로 못 박아 두기 때문입니다. 업로드 파일의 확장자 위조 검사, 다운로드가 중간에 깨졌는지 확인, 리눅스 file 명령의 포맷 판별이 전부 이 원리로 동작합니다. 16진수 읽기가 실무에서 가장 자주 쓰이는 곳이 바로 이 HEX 덤프입니다.
| 포맷 | 시그니처 (HEX) | ASCII로 읽으면 |
|---|---|---|
| PNG | 89 50 4E 47 0D 0A 1A 0A | .PNG.... — "PNG" 문자 + 전송 손상 감지용 바이트 |
| JPEG | FF D8 FF | SOI 마커 (JFIF는 FF D8 FF E0, EXIF는 FF D8 FF E1) |
| ZIP | 50 4B 03 04 | "PK.." — DOCX·XLSX·APK·JAR도 ZIP 기반이라 동일 |
| 25 50 44 46 2D | "%PDF-" | |
| GIF | 47 49 46 38 | "GIF8" (GIF87a·GIF89a) |
| ELF | 7F 45 4C 46 | ".ELF" — 리눅스 실행 파일 |
- macOS·리눅스: 터미널에서
xxd 파일명 | head -1— 첫 16바이트가 HEX와 ASCII로 나란히 출력됩니다 - 윈도우: HxD 같은 헥스 에디터로 열어 첫 줄을 위 표와 대조하면 됩니다
- PNG의 첫 바이트 89를 위 변환기에 넣으면 10001001 — 최상위 비트가 1인 비(非)ASCII 값입니다. 7비트 채널로 잘못 전송되면 이 비트가 깎여 시그니처가 깨지므로, 손상을 즉시 알아채도록 PNG 규격이 일부러 고른 값입니다
- ZIP의 PK(50 4B)는 PKZIP 개발자 필 카츠(Phil Katz)의 이니셜입니다
진법 간 단축 변환 관계
2진수 ↔ 16진수 (가장 자주)
2진수 4자리 = 16진수 1자리
0000 = 0 / 0001 = 1 / 1010 = A / 1111 = F
8비트(1바이트) = 16진수 2자리 (예: 0xFF)
2진수 ↔ 8진수
2진수 3자리 = 8진수 1자리
000 = 0 / 111 = 7
Unix 권한(rwx)에 자주 사용 (chmod 755)
0xFF가11111111보다 훨씬 읽기 쉽습니다.비트 폭별 표현 범위
| 비트 | 부호 없는 최대 | 부호 있는 범위 |
|---|---|---|
| 8-bit (1B) | 255 | −128 ~ 127 |
| 16-bit (2B) | 65,535 | −32,768 ~ 32,767 |
| 32-bit (4B) | 약 42억 | −약 21억 ~ 약 21억 |
| 64-bit (8B) | 약 1.8 × 10¹⁹ | −9.2 × 10¹⁸ ~ 9.2 × 10¹⁸ |
- 2⁸ = 256 (1바이트)
- 2¹⁰ = 1,024 (1KiB)
- 2¹⁶ = 65,536 (UTF-16 BMP, 16비트 포트)
- 2²⁰ = 1,048,576 (1MiB)
- 2³² = 약 42억 (32-bit 정수 한계, IPv4 주소)
IPv4 주소·서브넷을 진법으로 읽기
192.168.0.1 같은 IP 주소는 사실 32비트 2진수 하나를 8비트씩 네 토막 내어 10진수로 적은 것입니다. 서브넷 마스크와 CIDR 표기(/24)가 어렵게 느껴진다면, 진법으로 풀어서 보는 것이 가장 빠른 이해법입니다.
| CIDR | 서브넷 마스크 | 전체 주소 | 사용 가능 호스트 |
|---|---|---|---|
| /24 | 255.255.255.0 | 256 | 254 |
| /25 | 255.255.255.128 | 128 | 126 |
| /26 | 255.255.255.192 | 64 | 62 |
| /28 | 255.255.255.240 | 16 | 14 |
| /30 | 255.255.255.252 | 4 | 2 |
2의 보수 (Two's Complement)
컴퓨터가 음수를 비트로 표현하는 가장 효율적인 방법입니다. 거의 모든 현대 CPU·언어에서 표준으로 사용됩니다.
✓ 장점 1
0이 단 하나 (+0과 −0이 분리되지 않음, 부호+절대값 방식과 다름)
✓ 장점 2
덧셈·뺄셈을 같은 회로로 처리 (a − b = a + (−b))
✓ 장점 3
비트 반전 후 +1로 매우 간단히 변환
IEEE 754 부동소수점 — 0.1 + 0.2 ≠ 0.3인 이유
브라우저 콘솔에 0.1 + 0.2를 입력하면 0.30000000000000004가 나옵니다. 버그가 아니라 소수를 2진수 비트로 저장하는 IEEE 754 표준의 정상 동작입니다. 1/3을 10진수로 정확히 적을 수 없듯이(0.3333…), 분모에 5가 들어 있는 0.1(= 1/10)은 2진수로 무한 반복 소수가 되어 유한한 비트에 담는 순간 반올림 오차가 생깁니다.
| 형식 | 부호 | 지수 | 가수(유효숫자) | 유효 십진 자릿수 |
|---|---|---|---|---|
| float32 (단정밀도) | 1비트 | 8비트 | 23비트 | 약 7자리 |
| float64 (배정밀도) | 1비트 | 11비트 | 52비트 | 약 15~16자리 |
- 금액 계산은 부동소수점 대신 정수(원 단위)로 처리하고 표시할 때만 변환
- 1 부근 값의 동등 비교는 === 대신
Math.abs(a - b) < Number.EPSILON— 큰 수는 허용 오차를 값 크기에 비례시킬 것 - 분모가 2의 거듭제곱인 소수(0.5, 0.25, 0.125)는 오차 없이 정확히 저장됨 — 0.25 + 0.25 === 0.5 는 true
- 정수도 2⁵³ = 9,007,199,254,740,992부터는 정확히 표현되지 않음 — JS의 Number.MAX_SAFE_INTEGER(2⁵³ − 1)를 넘으면 BigInt 사용
비트 연산 활용 가이드
| 연산 | 동작 | 활용 예시 |
|---|---|---|
| AND (&) | 둘 다 1일 때만 1 | 마스킹 — 0xFF & 0x0F = 0x0F (하위 4비트만 추출) |
| OR (|) | 하나라도 1이면 1 | 비트 설정 — 0x10 | 0x01 = 0x11 (특정 비트 ON) |
| XOR (^) | 다르면 1, 같으면 0 | 토글·암호화 — 같은 값 두 번 XOR하면 원복 |
| NOT (~) | 0↔1 반전 | 비트 반전, 마스크 생성 |
| LSHIFT (<<) | 왼쪽 이동 | x << 1 = x × 2 (빠른 곱셈) |
| RSHIFT (>>) | 오른쪽 이동 | x >> 1 = x ÷ 2 (정수 나눗셈) |
- 플래그 관리 (여러 옵션을 한 변수에):
flags |= READ; if (flags & READ) ... - Linux 파일 권한 (chmod 755 = 0o755 = rwxr-xr-x)
- RGB 채널 분리:
r = (color >> 16) & 0xFF - 비트 연산은 일반 산술보다 훨씬 빠름 — 성능 최적화
ASCII 표준
ASCII = American Standard Code for Information Interchange (1963년 제정). 7비트로 영어·숫자·기본 기호 128개를 표현하는 표준이며, 8비트 확장 ASCII는 256개를 다룹니다.
0~31
제어 문자
NUL, TAB(9), LF(10), CR(13), ESC(27) 등
32
공백 (SPACE)
문자열 구분
48~57
숫자 0~9
ord('0') = 48
65~90
대문자 A~Z
ord('A') = 65
97~122
소문자 a~z
ord('a') = 97 (대문자+32)
127
DEL
구식 천공카드 삭제 표시
U+AC00 ~ U+D7A3 범위에 11,172개가 정의 (가~힣).프로그래밍 언어별 진법 표기
| 언어 | 16진수 | 2진수 | 8진수 |
|---|---|---|---|
| C / C++ / Java | 0xFF | 0b11111111 (C++14+) | 0377 (앞 0) |
| Python | 0xff | 0b11111111 | 0o377 |
| JavaScript / TS | 0xFF | 0b11111111 | 0o377 |
| Rust / Go | 0xFF | 0b1111_1111 | 0o377 |
| CSS 색상 | #FF0000 | — | — |
| HTML 엔터티 | A | — | — |
| URL 인코딩 | %41 | — | — |
자주 묻는 질문 (FAQ)
Q1. 왜 16진수를 자주 사용하나요?
2진수는 길어서 사람이 읽기 어렵지만, 16진수는 짧고 직관적이기 때문입니다. 8비트(1바이트)는 16진수 2자리로 표현되며, 메모리 주소·색상 코드·암호화 키 등에 표준입니다. 또한 16진수와 2진수는 4비트 단위로 직접 변환되어 (1111 = F) 비트 패턴 분석에 매우 편리합니다. 0xFF가 11111111보다 훨씬 읽기 쉽습니다.
Q2. 2의 보수는 왜 사용하나요?
컴퓨터에서 음수를 표현하는 가장 효율적인 방법이기 때문입니다. ① 0이 단 하나(+0과 −0이 구분 X), ② 덧셈·뺄셈을 같은 회로로 처리(a − b = a + (−b)), ③ 비트 반전 후 +1로 간단히 변환. 거의 모든 현대 CPU·프로그래밍 언어에서 표준으로 사용합니다. 부호+절대값 방식이나 1의 보수 방식은 0의 표현이 두 가지가 되거나 회로가 복잡해 거의 쓰이지 않습니다.
Q3. ASCII와 유니코드의 차이는 무엇인가요?
ASCII는 7비트로 영어·숫자·기본 기호 128개를 표현하는 표준입니다(1963년 제정). 유니코드는 전 세계 모든 문자를 표현하기 위해 ASCII를 확장한 표준이며, 약 14만 개 이상의 문자(한글·한자·이모지 포함)를 정의합니다. ASCII 0~127번은 유니코드와 완전히 동일하므로 ASCII 호환성이 보장됩니다. 한글은 U+AC00 ~ U+D7A3 범위에 11,172개가 정의되어 있습니다.
Q4. 비트 연산은 언제 사용하나요?
비트 연산은 다음 상황에 자주 사용됩니다: ① 플래그 관리(여러 옵션을 한 변수에 OR로 설정·AND로 확인), ② 마스킹(특정 비트만 추출), ③ 빠른 곱셈·나눗셈(x << 1 = x×2), ④ 권한 시스템(Linux 파일 권한 0o755), ⑤ 암호화·해시(XOR 활용), ⑥ 그래픽 처리(RGB 채널 분리). 비트 연산은 일반 산술 연산보다 훨씬 빠르므로 성능 최적화에도 사용됩니다.
Q5. 0.1 + 0.2가 0.30000000000000004로 나오는데 버그인가요?
버그가 아니라 IEEE 754 부동소수점 표준의 정상 동작입니다. 10진수 0.1은 2진수로 무한 반복 소수(0.000110011…)여서 64비트에 담는 순간 미세한 반올림 오차가 생깁니다. 실무 회피법: ① 금액은 원 단위 정수로 계산, ② 1 부근 값의 비교는 Math.abs(a - b) < Number.EPSILON(큰 수는 허용 오차를 값 크기에 비례시켜야 정확), ③ 화면 표시 단계에서만 toFixed() 사용. 참고로 0.5·0.25처럼 분모가 2의 거듭제곱인 소수는 오차 없이 정확하게 저장됩니다.
Q6. 16진수에서 A~F는 무엇을 의미하나요?
16진수는 0~15까지 16개 숫자를 사용하는 진법이지만, 한 자리에 두 자리 숫자(10~15)를 넣을 수 없어 알파벳을 빌려 사용합니다: A=10, B=11, C=12, D=13, E=14, F=15. 예를 들어 0xFF = 15 × 16 + 15 = 255입니다. 관습상 대문자(A~F)와 소문자(a~f) 모두 허용되며 같은 값을 의미합니다. CSS 색상은 대문자가 일반적이고, Python·Rust 등은 소문자를 선호합니다.