진수 변환은 같은 숫자 값을 다른 위치 기수법으로 표현하는 과정입니다. 모든 정수는 하나의 참값을 가지며, 진수는 그 값을 어떻게 쓰는지만 결정합니다. 10진수 255, 16진수 0xFF, 2진수 0b11111111, 8진수 0377은 모두 같은 수량을 네 가지 표기법으로 나타낸 것입니다.
숫자 진수(기수)란?
숫자 진수(기수)는 시스템이 다음 자리로 “올림”하기 전에 사용할 수 있는 고유 숫자의 수를 정의합니다. 자리 값은 오른쪽에서 왼쪽으로 진수의 거듭제곱입니다.
2진수 (기수 2)
0과 1만 사용합니다. 자리 값은 2의 거듭제곱: 1, 2, 4, 8, 16, 32, 64, 128, …
2진수는 디지털 하드웨어의 고유 언어입니다. 모든 논리 연산, 메모리 셀, CPU 명령어는 궁극적으로 비트 시퀀스로 귀결됩니다. 비트 연산, 네트워크 마스크, 하드웨어 레지스터를 다룰 때 2진수를 직접 접하게 됩니다.
8진수 (기수 8)
0~7 숫자를 사용합니다. 자리 값은 8의 거듭제곱: 1, 8, 64, 512, …
8진수는 2진수의 컴팩트한 축약형으로, 1자리 8진수는 정확히 3비트를 나타냅니다. 일반적인 용도에서는 사라졌지만 Unix 파일 권한 마스크에서는 여전히 매우 관련이 있습니다 — chmod 755와 chmod 644는 8진수 값입니다.
10진수 (기수 10)
0~9 숫자를 사용합니다. 사람이 기본으로 쓰는 시스템입니다. 대부분의 프로그래밍 언어는 접두사가 없으면 숫자 리터럴을 10진수로 파싱합니다.
16진수 (기수 16)
0~9와 A~F 문자를 사용합니다. 1자리 16진수는 정확히 4비트를 나타내며, 2진수 데이터의 가장 컴팩트한 사람이 읽을 수 있는 인코딩입니다.
16진수는 소프트웨어 전체에서 쓰입니다: CSS 색상(#FF5733), 메모리 주소(0x7ffee4b2c8a0), SHA 해시, MAC 주소, UUID 필드, 바이너리 파일 검사 모두 16진수 표기를 사용합니다.
진수 간 변환 방법
수동 계산
10진수에서 다른 진수로 — 반복 나눗셈:
10진수 42를 2진수로 변환하려면:
42 ÷ 2 = 21 나머지 0
21 ÷ 2 = 10 나머지 1
10 ÷ 2 = 5 나머지 0
5 ÷ 2 = 2 나머지 1
2 ÷ 2 = 1 나머지 0
1 ÷ 2 = 0 나머지 1
나머지를 아래에서 위로 읽습니다: 101010. 따라서 10진수 42 = 2진수 101010.
다른 진수에서 10진수로 — 위치 전개:
16진수 2A를 10진수로 변환하려면:
2A = (2 × 16¹) + (10 × 16⁰)
= 32 + 10
= 42
JavaScript에서
JavaScript의 parseInt와 toString이 진수 변환을 기본으로 처리합니다:
// 10진수에서 다른 진수로
const n = 255;
console.log(n.toString(2)); // "11111111" (2진수)
console.log(n.toString(8)); // "377" (8진수)
console.log(n.toString(16)); // "ff" (16진수)
// 임의 진수에서 10진수로
console.log(parseInt("11111111", 2)); // 255
console.log(parseInt("377", 8)); // 255
console.log(parseInt("ff", 16)); // 255
// 진수 간 변환 (10진수 경유)
function convertBase(value, fromBase, toBase) {
return parseInt(value, fromBase).toString(toBase);
}
console.log(convertBase("ff", 16, 2)); // "11111111"
console.log(convertBase("377", 8, 16)); // "ff"
Python에서
Python은 내장 함수와 접두사 리터럴을 제공합니다:
# 10진수에서 다른 진수로
n = 255
print(bin(n)) # '0b11111111'
print(oct(n)) # '0o377'
print(hex(n)) # '0xff'
# 접두사가 필요 없으면 제거
print(format(n, 'b')) # '11111111'
print(format(n, 'o')) # '377'
print(format(n, 'x')) # 'ff'
print(format(n, 'X')) # 'FF' (대문자)
# 임의 진수에서 10진수로
print(int('11111111', 2)) # 255
print(int('377', 8)) # 255
print(int('ff', 16)) # 255
# 직접 접두사 리터럴
print(0b11111111) # 255
print(0o377) # 255
print(0xFF) # 255
프로그래밍에서 각 진수의 사용 시기
2진수 — 비트 연산과 플래그
2진수는 비트 수준에서 작업할 때 자연스러운 선택입니다:
// 비트 마스크를 사용한 권한 플래그
const READ = 0b100; // 4
const WRITE = 0b010; // 2
const EXECUTE = 0b001; // 1
const userPerms = READ | WRITE; // 0b110 = 6
const canRead = userPerms & READ; // 권한 설정 시 truthy
const canExec = userPerms & EXECUTE; // 0 — 실행 권한 없음
네트워크 프로그래밍은 서브넷 계산에 2진수 마스크를 사용합니다. 하드웨어 드라이버는 레지스터의 개별 제어 비트를 설정하는 데 2진수를 사용합니다.
8진수 — Unix 파일 권한
chmod 명령어는 8진수 인수를 받습니다. 세 자리 8진수로 소유자/그룹/기타 권한을 인코딩하며, 각 숫자는 r=4, w=2, x=1입니다:
chmod 755 script.sh # rwxr-xr-x
chmod 644 config.txt # rw-r--r--
chmod 600 id_rsa # rw------- (개인 키)
Python에서 os.open과 os.chmod에 전달되는 파일 모드는 8진수 리터럴이어야 합니다:
import os
os.chmod('script.sh', 0o755)
16진수 — 색상, 주소, 바이너리 데이터
CSS와 디자인: RGB 색상은 세 16진수 바이트 쌍으로 직접 매핑됩니다.
/* #RRGGBB */
color: #FF5733; /* R=255, G=87, B=51 */
color: #1a1a2e; /* 다크 네이비 */
메모리와 포인터: 디버거와 크래시 덤프는 4비트 니블과 8비트 바이트에 깔끔하게 정렬되기 때문에 16진수로 주소를 표시합니다.
해시와 인코딩: SHA-256 출력, git 커밋 해시, UUID, API 키는 관례적으로 16진수로 인코딩된 바이너리 데이터입니다.
import hashlib
h = hashlib.sha256(b"hello").hexdigest()
print(h) # 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
네트워크 프로토콜: 이더넷 프레임, IP 헤더, TLS 레코드는 Wireshark 같은 도구에서 16진수로 검사됩니다.
온라인으로 숫자 변환
코드 없이 빠르게 변환하려면 ZeroTool의 진수 변환기로 브라우저에서 2진수, 8진수, 10진수, 16진수 간에 즉시 변환할 수 있습니다. 임의의 필드에 값을 붙여넣으면 다른 모든 진수가 실시간으로 업데이트됩니다 — 서버 요청 없음, 데이터 전송 없음.
유용한 경우:
- 16진수 색상 값을 10진수 RGB로 디코딩
- chmod 8진수 값을 확인해 권한 검증
- 비트 연산 로직을 위한 2진수 표현 탐색
- 형식 간 메모리 주소 변환