ABOUT

성능과 운영 안정성을 함께 끌어올리는 개발자입니다.

92% Positional Error Reduction
79% p95 Latency Improvement
90%+ Long Tasks Reduction

2022.02 · 한국장학재단

우수 멘티

한국장학재단 사회 리더 대학생 멘토링 IT

2022.10 · 동작구청

우수 인재상

동작구청 우수 SW 인재

2025.05 · (주) 그랩

프로그래밍 우수상

(주) 그랩 우수 프로그램 개발

2025.05 · AWSKRUG

AWS한국사용자모임 발표

AI agent 스크립트 튜닝 관련 발표

ComputerScience

Development

Engineering

Trouble Shooting

GUESTBOOK

첫 마음부터
함께 나누는 온기

방명록 작성하러 가기

SUBSCRIBE

최신소식을
편하게 만나보세요.

진법

도입

숫자를 표현하는 방식입니다.

우리가 일상에서 쓰는 숫자는 대부분 10진수입니다.

0,1,2,3,4,5,6,7,8,9

컴퓨터 내부에서는 전기적 상태를 기준으로 데이터를 표현하기 때문에 0과 1만 사용하는 2진수가 훨씬 자연스럽습니다.

문제는 2진수만 그대로 읽고 쓰기에는 길이가 너무 길어진다는 점입니다. 그래서 사람이 보기 편한 표현으로 8진수나 16진수를 함께 사용합니다. 특히 16진수는 4비트 단위와 정확히 대응되기 때문에 메모리 주소, 바이트 값, 색상 코드, 디버깅 출력에서 자주 등장합니다.

즉 진법을 이해한다는 것은 단순히 숫자 변환 공식을 외우는 것이 아니라, 컴퓨터가 숫자를 어떻게 표현하고 사람이 그것을 어떻게 읽기 쉽게 바꿔 쓰는지 이해하는 일에 가깝습니다.

필요성

컴퓨터 과학에서 진법이 중요한 이유는 숫자의 값 자체보다, 같은 값을 어떤 표현 체계로 읽고 저장하고 변환할 것인지가 프로그램 동작과 디버깅에 직접 연결되기 때문이다

예를 들어 10진수 255 는 2진수로 11111111, 16진수로 FF 입니다. 값은 같지만 표현 방식이 다릅니다.

컴퓨터 내부 비트 패턴을 확인할 때는 2진수가 직접적이고, 바이트 단위 값을 짧게 표현할 때는 16진수가 편합니다. 반면 사용자가 보는 수량이나 금액, 카운트는 보통 10진수로 표현하는 편이 자연스럽습니다.

그래서 진법은 저수준 비트 표현, 메모리 주소, 문자 인코딩, 색상 코드, 네트워크 패킷, 파일 포맷, 디버깅 로그를 이해하는 기본 도구가 됩니다.

진법이 특히 중요한 지점
  • 비트와 바이트 단위의 내부 표현을 이해할 때
  • 2진수와 16진수로 메모리 값이나 주소를 읽을 때
  • Java 같은 언어에서 정수 리터럴을 여러 진법으로 표현할 때
  • 색상 코드, 문자 코드, 네트워크 패킷, 바이너리 포맷을 분석할 때

정의

진법은 하나의 수를 표현하기 위해 사용할 수 있는 숫자 기호의 개수와, 각 자리가 어떤 가중치를 갖는지 정하는 숫자 표현 체계다

진법은 영어로 base 또는 radix 라고 부릅니다. 예를 들어 10진수는 base 10, 2진수는 base 2, 16진수는 base 16입니다.

base가 10이면 사용할 수 있는 기본 숫자는 0 부터 9 까지 10개입니다. base가 2이면 0, 1 두 개만 사용합니다. base가 16이면 0 부터 9 까지와 A 부터 F 까지를 함께 사용합니다.

중요한 점은 숫자 기호만 달라지는 것이 아니라, 자리의 가중치도 진법에 따라 달라진다는 것입니다. 10진수에서는 오른쪽부터 10^0, 10^1, 10^2 이고, 2진수에서는 2^0, 2^1, 2^2 입니다.

핵심 메시지

"진법의 본질은 숫자 모양이 아니라

각 자리가 몇의 거듭제곱을 의미하는지 정하는 자릿값 체계에 있습니다."

핵심 원리

위치적 기수법에서는 각 자리의 값이 숫자 기호 자체와 그 자리의 위치가 함께 결정하며, 오른쪽에서 왼쪽으로 갈수록 진법의 거듭제곱이 커진다

10진수 345 는 단순히 3, 4, 5라는 숫자를 붙인 것이 아닙니다. 실제 값은 3 × 10^2 + 4 × 10^1 + 5 × 10^0 입니다.

같은 원리로 2진수 10111 × 2^3 + 0 × 2^2 + 1 × 2^1 + 1 × 2^0 이며, 10진수로는 11 입니다.

즉 어떤 진법이든 각 자리의 가중치는 오른쪽부터 base^0, base^1, base^2 순서로 커집니다. 이 원리만 이해하면 모든 진법 변환의 핵심은 거의 잡은 것입니다.

자리값 계산 공식

(dn ... d2 d1 d0)_base

= dn × base^n
+ ...
+ d2 × base^2
+ d1 × base^1
+ d0 × base^0

주요 진법

컴퓨터 과학에서는 2진수, 8진수, 10진수, 16진수를 가장 자주 사용하며, 각각 내부 표현·압축 표현·일상 표현·디버깅 표현이라는 역할이 다르다
진법 Base 사용 기호 예시 실무 해석
2진수 2 0, 1 1011₂ 비트 단위 내부 표현에 가장 직접적
8진수 8 0~7 13₈ 3비트 단위 표현과 연결되지만 현대 실무에서는 16진수보다 덜 자주 사용
10진수 10 0~9 11₁₀ 사람이 읽는 일반적인 수량 표현
16진수 16 0~9, A~F B₁₆ 4비트 단위 표현과 연결되어 바이트, 주소, 색상 코드 표현에 편리

변환 1. 다른 진법에서 10진수로

다른 진법의 수를 10진수로 바꾸는 핵심은 각 자리 숫자에 해당 진법의 거듭제곱 가중치를 곱해 모두 더하는 것이다

2진수 1011₂ 을 10진수로 바꿔 보겠습니다.

1011₂
= 1 × 2^3 + 0 × 2^2 + 1 × 2^1 + 1 × 2^0
= 8 + 0 + 2 + 1
= 11₁₀

16진수 2A₁₆ 도 같은 방식입니다. 여기서 A 는 10을 의미합니다.

2A₁₆
= 2 × 16^1 + A × 16^0
= 2 × 16 + 10 × 1
= 32 + 10
= 42₁₀

변환 2. 10진수에서 다른 진법으로

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

나머지를 아래에서 위로 읽기
42₁₀ = 101010₂

같은 값을 16진수로 바꿀 때는 16으로 나눕니다.

42 ÷ 16 = 2 ... 10

10은 16진수에서 A
42₁₀ = 2A₁₆

변환 3. 2진수와 16진수

2진수와 16진수 변환은 4비트 단위로 끊으면 되기 때문에, 컴퓨터 내부 값을 사람이 읽기 쉽게 표현할 때 매우 자주 사용된다

16은 2^4 이므로, 16진수 한 자리는 정확히 2진수 4자리와 대응됩니다.

16진수 2진수 10진수
0 0000 0
1 0001 1
2 0010 2
3 0011 3
4 0100 4
5 0101 5
6 0110 6
7 0111 7
8 1000 8
9 1001 9
A 1010 10
B 1011 11
C 1100 12
D 1101 13
E 1110 14
F 1111 15
1010 1111₂
= A F₁₆
= AF₁₆

반대로

0xAF
= A F
= 1010 1111₂

Java 리터럴

Java에서는 정수 리터럴을 10진수, 16진수, 8진수, 2진수로 표현할 수 있으며, 접두사를 통해 어떤 진법인지 구분한다
int decimal = 42;       // 10진수
int binary = 0b101010;  // 2진수
int octal = 052;        // 8진수
int hex = 0x2A;         // 16진수

System.out.println(decimal); // 42
System.out.println(binary);  // 42
System.out.println(octal);   // 42
System.out.println(hex);     // 42
실전 포인트
Java에서 052 는 10진수 52가 아니라 8진수 52입니다. 즉 값은 5 × 8 + 2 = 42 입니다. 앞에 붙은 0 하나가 의미를 바꾸므로, 실무에서는 8진수 리터럴을 조심해서 써야 합니다.

Java 변환

Java에서는 Integer.toString(value, radix)Integer.parseInt(text, radix) 로 원하는 진법의 문자열 변환과 해석을 처리할 수 있다
int value = 42;

String binary = Integer.toString(value, 2);
String octal = Integer.toString(value, 8);
String decimal = Integer.toString(value, 10);
String hex = Integer.toString(value, 16);

System.out.println(binary);  // 101010
System.out.println(octal);   // 52
System.out.println(decimal); // 42
System.out.println(hex);     // 2a

int parsed = Integer.parseInt("2A", 16);
System.out.println(parsed); // 42

패턴 1. 2진수는 비트 이해의 기본이다

2진수는 컴퓨터가 내부적으로 데이터를 표현하는 가장 기본적인 관점이며, 비트 연산과 플래그 처리, 마스크 계산을 이해하려면 반드시 필요하다

2진수는 01 만 사용합니다. 그래서 한 자리는 하나의 비트와 직접 대응됩니다.

예를 들어 권한 플래그, 상태 비트, 네트워크 프로토콜 필드처럼 각 비트가 별도의 의미를 가지는 경우 2진수로 보면 훨씬 직관적입니다.

예시: 권한 플래그

읽기  = 001₂
쓰기  = 010₂
실행  = 100₂

읽기 + 쓰기 = 011₂

패턴 2. 16진수는 2진수를 사람이 읽기 쉽게 압축한다

16진수 한 자리는 정확히 4비트와 대응되므로, 긴 2진수를 짧고 안정적으로 표현하는 데 매우 유리하다

예를 들어 1바이트는 8비트입니다. 이것을 2진수로 쓰면 8자리지만, 16진수로 쓰면 2자리면 충분합니다.

1111 1111₂
= FF₁₆
= 255₁₀

이 때문에 16진수는 메모리 덤프, 색상 코드, 문자 코드, 해시 값, 바이너리 데이터 출력에서 매우 자주 등장합니다.

패턴 3. 8진수는 3비트 단위와 연결된다

8진수 한 자리는 3비트와 대응되며, 현대 일반 프로그래밍에서는 16진수보다 덜 자주 쓰이지만 Unix 권한 표기처럼 여전히 등장하는 영역이 있다

8진수는 0 부터 7 까지의 숫자를 사용합니다. 8은 2^3 이므로 8진수 한 자리는 2진수 3자리와 대응됩니다.

111 101 100₂
= 754₈

예를 들어 Unix 계열 파일 권한에서 755, 644 같은 표기는 8진수 기반으로 읽는 것이 자연스럽습니다.

핵심 포인트
2진수는 내부 표현을 직접 보여 주고, 16진수는 그 내부 표현을 읽기 쉽게 줄여 줍니다. 10진수는 사람이 읽는 값이고, 8진수는 특정 시스템 표기에서 여전히 보입니다. 각 진법은 우열 관계가 아니라 사용 목적이 다릅니다.

한계와 주의점

진법은 숫자의 표현 방식일 뿐 값 자체를 바꾸는 것은 아니며, 접두사와 문맥을 잘못 읽으면 같은 문자열을 전혀 다른 값으로 해석할 수 있다

10 이라는 문자열은 10진수에서는 십이지만, 2진수에서는 이, 8진수에서는 팔, 16진수에서는 십육입니다. 즉 같은 문자열이라도 어떤 진법으로 읽느냐에 따라 값이 달라집니다.

또 프로그래밍 언어마다 접두사 규칙이 다를 수 있습니다. Java에서는 0b 가 2진수, 0x 가 16진수, leading 0 이 8진수를 의미합니다. 따라서 010 을 10진수 10으로 착각하면 버그가 생길 수 있습니다.

마지막으로 진법 변환은 표현을 바꾸는 일이지, 정수 타입의 범위나 오버플로 문제를 없애 주는 것이 아닙니다. 같은 값이라도 타입이 표현할 수 있는 범위를 넘어가면 문제가 됩니다.

주의해야 할 지점
  • 같은 숫자 문자열도 진법에 따라 전혀 다른 값을 의미할 수 있음
  • Java에서 leading 0 은 8진수 리터럴로 해석될 수 있음
  • 16진수의 A~F 는 10~15를 뜻함
  • 진법 변환은 표현 변환이지 타입 범위 문제를 해결하는 것은 아님

자주 하는 실수

진법을 어렵게 만드는 가장 흔한 원인은 변환 공식보다도, 숫자 문자열과 실제 값과 프로그래밍 언어의 리터럴 표기를 서로 섞어 생각하는 데 있다
  • 1010 을 항상 천십으로만 생각함
  • 2진수의 자리값을 10^n 으로 계산함
  • 16진수 A, B, F 를 문자로만 보고 숫자 값으로 읽지 못함
  • Java에서 010 을 10진수 10으로 착각함
  • 2진수와 16진수 변환에서 4비트 단위로 끊지 않음
  • 진법 변환과 부호 표현, 보수 표현, 오버플로 문제를 한꺼번에 섞어 생각함

실무 루틴

진법을 다룰 때는 먼저 어떤 진법으로 쓰인 값인지 확인하고, 그다음 자리값 계산이나 언어별 파싱 규칙을 적용하는 습관이 안전하다
  1. 먼저 숫자 문자열이 몇 진법인지 확인한다.
  2. 접두사 0b, 0x, leading 0 같은 언어별 표기 규칙을 확인한다.
  3. 10진수로 바꿀 때는 각 자리 × 진법의 거듭제곱으로 계산한다.
  4. 10진수에서 다른 진법으로 바꿀 때는 목표 진법으로 반복 나누기와 나머지를 사용한다.
  5. 2진수와 16진수는 4비트 단위로 직접 묶어 변환한다.
  6. 실무 코드에서는 직접 계산보다 표준 라이브러리의 parse/format 함수를 우선 사용한다.

디버깅

진법 관련 버그를 볼 때는 값이 틀린 것인지, 표현이 틀린 것인지, 언어의 리터럴 해석이 기대와 달랐던 것인지 먼저 나눠 봐야 한다
1
먼저 숫자 문자열이 실제로 몇 진법으로 해석되고 있는지 확인한다.
2
Java라면 0b, 0x, leading 0 접두사를 확인한다.
3
2진수와 16진수 변환은 4비트 단위 그룹이 맞는지 확인한다.
4
문자열 파싱 함수에 넘긴 radix 값이 기대한 값인지 확인한다.
5
값 표현 문제가 아니라 타입 범위나 signed/unsigned 문제는 아닌지 분리해서 확인한다.
점검 체크리스트
- 이 숫자는 몇 진법으로 쓰였는가
- 언어별 접두사 규칙이 적용되었는가
- 자리값 계산에서 base^n 을 제대로 사용했는가
- 2진수 ↔ 16진수 변환에서 4비트 그룹이 맞는가
- parseInt / toString 의 radix 인자가 맞는가
- 진법 문제가 아니라 오버플로 또는 부호 표현 문제는 아닌가

요약

진법의 핵심은 숫자를 어떤 base로 해석할지 정하는 것이며, 컴퓨터에서는 2진수가 내부 표현, 16진수가 사람이 읽기 쉬운 압축 표현, 10진수가 일상적 표현으로 서로 다른 역할을 가진다
  • ✅ 진법은 숫자를 표현할 때 사용하는 base 또는 radix 다.
  • ✅ 위치적 기수법에서는 각 자리의 값이 숫자 × base의 거듭제곱으로 계산된다.
  • ✅ 2진수는 0, 1 두 기호만 사용한다.
  • ✅ 8진수는 0~7 을 사용하며 3비트 단위와 대응된다.
  • ✅ 10진수는 일상에서 가장 일반적으로 쓰는 base 10 표현이다.
  • ✅ 16진수는 0~9, A~F 를 사용하며 4비트 단위와 대응된다.
  • ✅ Java 정수 리터럴은 10진수, 16진수, 8진수, 2진수로 표현할 수 있다.
  • ✅ 같은 문자열도 진법이 다르면 실제 값이 달라질 수 있다.
  • ✅ 실무에서는 직접 계산보다 표준 라이브러리의 parse/format 기능을 우선 사용하는 편이 안전하다.
728x90