Tools mentioned in this article
Open the browser-based tool while you read and try the workflow immediately.

“비밀번호를 Base64로 저장하고 있습니다”—이것은 보안상 심각한 오해입니다. 인코딩·해시·암호화는 모두 문자열을 다른 형태로 변환하지만 목적이 완전히 다르며, 혼동하면 데이터 유출이나 결함으로 이어집니다.
이 글에서는 3가지의 차이를 비교표와 구체적 예시로 정리하고, “어떤 상황에서 무엇을 써야 하는지”를 명확히 합니다.
결론부터: 3가지의 차이
| 목적 | 되돌릴 수 있는가? | 키가 필요한가? | 대표 예시 | |
|---|---|---|---|---|
| 인코딩 | 데이터를 다른 표현 형식으로 변환 | 예(누구나) | 불필요 | Base64, URL 인코딩 |
| 해시 | 고정 길이의 지문을 만듦(단방향) | 아니오 | 불필요 | SHA-256, HMAC |
| 암호화 | 비밀로 하여 허가된 사람만 복호화 | 예(키가 있으면) | 필요 | AES, RSA |
핵심은 인코딩은 기밀성이 전혀 없고, 해시는 되돌릴 수 없으며, 암호화만이 “비밀을 지키는” 유일한 방법이라는 것입니다.
인코딩: 가독성·호환성을 위한 변환
인코딩은 데이터를 “다른 표현 방식”으로 바꾸기만 합니다. 키도 비밀번호도 필요 없고, 누구나 되돌릴 수 있습니다. 기밀 기능은 전혀 없습니다.
예를 들어 Base64는 바이너리나 특수문자를 텍스트로 안전하게 운반하기 위한 방식입니다.
Hello, World! →(Base64 인코딩)→ SGVsbG8sIFdvcmxkIQ==
SGVsbG8sIFdvcmxkIQ==는 언뜻 무작위로 보이지만, Base64 변환 도구에 붙여넣으면 누구나 즉시 원래 문자열로 되돌릴 수 있습니다. URL에 한글이나 기호를 담기 위한 URL 인코딩도 같은 부류입니다.
흔한 오용: API 키나 비밀번호를 Base64로 만들어 “숨겼다”고 여기는 것은 위험합니다. Base64는 암호화가 아니므로 기밀 유지에 전혀 도움이 되지 않습니다.
해시: 단방향의 “지문”
해시는 입력 데이터로부터 고정 길이의 값(다이제스트)을 계산하는 단방향 변환입니다. 같은 입력에서는 반드시 같은 값이 나오지만, 해시 값에서 원본 데이터를 복원할 수는 없습니다.
password123 →(SHA-256)→ ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f
입력이 조금만 바뀌어도 출력은 크게 바뀝니다. 이 성질 때문에 해시는 다음 용도로 사용합니다.
- 비밀번호 저장: 평문이 아닌 해시를 저장하고, 로그인 시 입력값의 해시와 대조합니다(실제로는 솔트+bcrypt/Argon2 등을 사용).
- 변조 감지·무결성 확인: 파일이나 메시지의 해시를 비교해 내용이 바뀌지 않았는지 확인합니다.
- 서명의 일부: JWT의 서명이나 HMAC으로 데이터가 변조되지 않았음을 보증합니다.
해시 생성 도구에서 SHA-256이나 HMAC을 시험해보면, 입력을 바꿨을 때 출력이 완전히 달라지는 모습을 확인할 수 있습니다.
중요: 해시는 “되돌릴 수 없다”는 것이 본질입니다. 그렇기 때문에 비밀번호 저장에 적합합니다. 반대로 나중에 원본 데이터가 필요한 용도에는 쓸 수 없습니다.
암호화: 키로 지키는, 되돌릴 수 있는 비밀
암호화는 키를 사용해 데이터를 읽을 수 없는 형태로 변환하고, 올바른 키를 가진 사람만 복호화할 수 있는 구조입니다. 인코딩과 달리 키가 없으면 되돌릴 수 없고, 해시와 달리(키가 있으면) 되돌릴 수 있습니다. 이것이 “비밀을 지키는” 유일한 방법입니다.
- 대칭키 암호(AES 등): 암호화와 복호화에 같은 키를 사용합니다. 빠르며 저장 데이터 암호화 등에 사용합니다.
- 공개키 암호(RSA 등): 공개키로 암호화하고 비밀키로 복호화합니다. 키 교환이나 전자서명에 사용합니다.
HTTPS 통신, 데이터베이스의 저장 시 암호화, 기밀 파일 보호 등은 모두 암호화의 영역입니다. 키 관리(유출하지 않기·적절히 보관하기)가 그대로 안전성을 좌우합니다.
구분 조견표
| 하고 싶은 것 | 사용할 것 |
|---|---|
| URL이나 JSON에 특수문자를 안전하게 담고 싶다 | 인코딩(Base64 / URL 인코딩) |
| 비밀번호를 안전하게 저장하고 싶다 | 해시(bcrypt / Argon2, 솔트 포함) |
| 파일이 변조되지 않았는지 확인하고 싶다 | 해시(SHA-256) |
| 데이터를 나중에 되돌릴 수 있는 형태로 비밀로 하고 싶다 | 암호화(AES / RSA) |
| 통신 내용을 도청으로부터 지키고 싶다 | 암호화(TLS/HTTPS) |
| 토큰이 변조되지 않았는지 검증하고 싶다 | 해시 기반 서명(HMAC / JWT) |
흔히 저지르는 실수
- Base64로 “암호화한 셈 치기”: 앞서 말했듯 기밀성은 전혀 없습니다. 기밀 정보 보호에는 쓸 수 없습니다.
- 비밀번호를 암호화해서 저장: 복호화할 수 있다는 것은 키가 유출되면 모든 비밀번호가 노출된다는 뜻입니다. 비밀번호는 복호화가 필요 없으므로 해시(솔트 포함)가 정답입니다.
- 단순 SHA-256만으로 비밀번호 저장: 너무 빨라서 무차별 대입 공격에 약하고, 레인보우 테이블 공격도 받습니다. 솔트와, bcrypt/Argon2처럼 의도적으로 느린 알고리즘을 사용합니다.
- 직접 암호 알고리즘을 구현: 암호는 “검증된 표준 라이브러리”를 쓰는 것이 원칙입니다. 독자 구현은 거의 확실히 취약해집니다.
정리
이름은 비슷해도 역할은 정반대입니다. 인코딩은 겉모습만 바꿀 뿐(기밀 없음), 해시는 되돌릴 수 없는 지문, 암호화는 키로 지키는 되돌릴 수 있는 비밀. 이 구분만 잡아두면 “비밀번호는 해시, 통신은 암호화, URL 용도는 인코딩”으로 자연스럽게 선택할 수 있게 됩니다. 직접 동작을 확인하고 싶다면 Base64 변환·해시 생성·JWT 디코드를 실제로 써보세요.
자주 묻는 질문
Base64는 왜 암호화가 아닌가요?
Base64는 키를 사용하지 않고 변환 규칙이 공개되어 있어 누구나 즉시 원래대로 되돌릴 수 있습니다. 기밀 요소가 전혀 없기 때문에 “암호화”가 아니라 “인코딩(표현 형식 변환)“으로 분류됩니다. 기밀 정보를 숨기는 목적으로는 쓸 수 없습니다.
비밀번호는 해시와 암호화 중 어느 쪽으로 저장해야 하나요?
해시입니다. 비밀번호는 “나중에 복호화할 필요가 없기” 때문에 단방향 해시(솔트 포함 bcrypt나 Argon2)가 적절합니다. 암호화로 저장하면 복호화 키가 유출되는 순간 모든 비밀번호가 노출될 위험이 있습니다.
해시는 절대 되돌릴 수 없나요?
계산상으로는 해시 값에서 원본 데이터를 역산할 수 없습니다. 다만 흔한 비밀번호는 사전 계산(레인보우 테이블)으로 대조당할 우려가 있습니다. 그래서 사용자마다 다른 솔트를 추가하고, 무차별 대입에 강한 느린 알고리즘을 쓰는 것이 중요합니다.
JWT 토큰은 암호화되어 있나요?
일반적인 JWT(서명이 있는 JWS)는 암호화가 아니라 서명입니다. 페이로드는 Base64URL로 인코딩되어 있을 뿐이며, JWT 디코드 도구로 누구나 내용을 읽을 수 있습니다. 서명은 변조 감지를 위한 것이므로 JWT에 비밀 정보를 그대로 넣으면 안 됩니다. 기밀이 필요하다면 암호화(JWE)를 사용하세요.