Skip to content

인증 방식 (세션 · 토큰 · API Key · OAuth) ​

인증 방식은 서버가 "이 요청을 보낸 사람(또는 프로그램)이 누구이고, 무엇을 해도 되는지"를 확인하는 방법입니다. 대표적으로 Basic 인증, 세션, 토큰(JWT), API Key, OAuth가 있고, 각각 어디에 정보를 두고 무엇을 주고받는지가 다릅니다.

한눈에 보기 ​

  • 먼저 비슷해 보이는 두 단어를 구분해야 합니다.
    • 인증(Authentication): "당신은 누구인가요?" 를 확인하는 것
    • 인가(Authorization): "당신은 무엇을 해도 되나요?" 를 확인하는 것
  • 비유: 회사 출입을 떠올려 보면 쉽습니다.
    • 사원증을 찍어서 "홍길동 사원이 맞다"를 확인하는 것이 인증입니다.
    • 그 사원증으로 서버실 문까지 열 수 있는지 확인하는 것이 인가입니다.
  • 순서는 항상 인증이 먼저, 인가가 나중입니다. 누구인지 모르면 무엇을 허락할지도 정할 수 없기 때문입니다.

인증과 인가 ​

구분인증 (Authentication)인가 (Authorization)
묻는 것누구인가요?무엇을 해도 되나요?
확인 방법비밀번호, OTP, 지문, 토큰역할(관리자/일반), 권한 목록, 소유자 여부
실패했을 때 HTTP 상태 코드401 Unauthorized403 Forbidden
예로그인관리자만 글 삭제 가능, 내 글만 수정 가능

401의 이름이 "Unauthorized"라서 헷갈리기 쉽지만, 실제 의미는 "인증이 안 됐다(누군지 모른다)" 입니다. 누구인지는 알지만 권한이 없을 때는 403을 씁니다. 상태 코드는 HTTP 상태 코드 글에서 더 자세히 다룹니다.

방법 1: HTTP Basic 인증 ​

가장 단순한 방식으로, 요청할 때마다 아이디와 비밀번호를 그대로 헤더에 실어 보냅니다.

Authorization: Basic MW1vOm15LXBhc3N3b3Jk

MW1vOm15... 부분은 아이디:비밀번호를 Base64로 바꾼 값입니다. Base64는 암호화가 아니라 단순한 글자 변환이라 누구나 바로 원래대로 되돌릴 수 있습니다(아래 코드에서 직접 확인합니다).

브라우저에서는 보통 아래 순서로 진행됩니다. 서버가 먼저 401과 WWW-Authenticate 헤더로 "아이디와 비밀번호가 필요합니다"라고 알리면, 브라우저가 입력창을 띄우고 Authorization 헤더를 붙여 다시 요청합니다.

HTTP Basic 인증 흐름: 서버가 401과 WWW-Authenticate로 자격 증명을 요구하고, 클라이언트가 Authorization 헤더를 붙여 다시 요청하면 서버가 확인 후 200 또는 401로 응답

그림 출처: MDN, HTTP authentication (CC BY-SA 2.5)

  • 장점: 구현이 매우 간단하고 표준이라 거의 모든 도구가 지원합니다.
  • 단점: 요청마다 비밀번호가 오가므로 HTTPS 없이 쓰면 매우 위험하고, 로그아웃 개념이 없습니다.
  • 쓰임: 사내 도구, 테스트 서버, 간단한 관리 페이지 정도에만 씁니다.

방법 2: 세션 기반 인증 ​

로그인할 때 한 번만 비밀번호를 확인하고, 이후에는 서버가 발급한 세션 ID로 사용자를 알아보는 방식입니다. 동작 과정은 쿠키와 세션 글에 자세히 정리했습니다.

로그인 → 서버가 세션 저장소에 {세션ID: 사용자} 기록 → Set-Cookie로 세션 ID 전달
이후 요청 → 브라우저가 Cookie로 세션 ID 전송 → 서버가 저장소에서 사용자 조회
  • 서버가 상태를 들고 있는(stateful) 방식입니다.
  • 서버에서 세션만 지우면 즉시 로그아웃시킬 수 있어 통제가 쉽습니다.

방법 3: 토큰 기반 인증 ​

로그인에 성공하면 서버가 토큰을 발급하고, 클라이언트는 이후 요청마다 그 토큰을 헤더에 실어 보냅니다.

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Bearer는 "이 토큰을 가진 사람에게 권한을 준다"는 뜻입니다. 그래서 토큰을 도둑맞으면 도둑도 같은 권한을 갖게 됩니다.

토큰에는 두 종류가 있습니다.

종류생김새서버가 확인하는 방법
불투명 토큰 (Opaque Token)의미 없는 임의 문자열저장소에서 찾아봐야 누구 것인지 알 수 있음 (세션과 비슷)
자체 포함 토큰 (JWT)사용자 정보와 서명이 들어 있는 문자열서명만 확인하면 되므로 저장소를 찾지 않아도 됨

JWT처럼 토큰 안에 정보가 들어 있으면, 서버는 사용자 정보를 따로 저장할 필요가 없는 상태를 들고 있지 않은(stateless) 방식이 됩니다.

세션 기반 vs 토큰 기반 비교 ​

구분세션 기반토큰 기반 (JWT)
사용자 정보 위치서버의 세션 저장소토큰 안 (클라이언트가 보관)
서버 상태있음 (stateful)없음 (stateless)
요청마다 보내는 것Cookie: session_id=... (자동 전송)Authorization: Bearer ... (보통 직접 붙임)
서버 확장서버끼리 세션 저장소를 공유해야 함비밀키(또는 공개키)만 공유하면 어느 서버든 검증 가능
강제 로그아웃세션 삭제로 즉시 가능만료 전까지 유효. 막으려면 차단 목록 등 별도 장치 필요
네트워크 비용쿠키에 짧은 ID만 오감토큰이 길어서 요청마다 데이터가 더 큼
잘 맞는 곳일반 웹사이트, 서버 한 곳에서 화면까지 그리는 서비스모바일 앱, 여러 서버로 나뉜 서비스(MSA), 외부에 여는 API

어느 쪽이 무조건 낫다기보다, 즉시 통제가 중요하면 세션, 확장성과 여러 클라이언트 지원이 중요하면 토큰으로 고르는 경우가 많습니다. 실무에서는 둘을 섞어 쓰기도 합니다(예: JWT를 HttpOnly 쿠키에 담기).

방법 4: API Key ​

사람이 아니라 프로그램(애플리케이션)이 API를 쓸 때 주로 쓰는 방식입니다. 공공데이터 API, 지도 API, AI 모델 API처럼 서비스에 가입하면 키를 발급해 주는 경우가 대표적입니다.

동작 방식 ​

  1. 사용자가 서비스에서 API Key를 발급받습니다. (공공기관 API처럼 신청서를 내고 관리자 승인을 받는 경우도 있습니다.)
  2. API를 부를 때 키를 함께 보냅니다. 보통 X-API-Key: ... 같은 헤더나 Authorization: Bearer ...에 담습니다.
  3. 서버는 키로 누구의 키인지, 어떤 권한이 있는지, 사용량이 얼마나 남았는지를 확인합니다.
  4. 확인되면 데이터를 돌려줍니다.

문제점과 주의할 점 ​

  • 키 하나가 곧 신분증 겸 열쇠라서, 유출되면 누구나 그 키의 주인 행세를 할 수 있습니다.
  • 그래서 키를 주기적으로 바꿔야 하는데, 바꾸는 도중 한쪽만 바뀌어 서로 맞지 않는 사고가 생기기도 합니다.
  • 키를 프론트엔드 코드나 GitHub 저장소에 그대로 넣으면 누구나 볼 수 있습니다. 키는 서버 쪽 환경 변수에 두고, 브라우저에서는 내 서버를 거쳐 호출하는 것이 안전합니다.
  • 키가 털렸을 때 피해를 줄이도록 허용 도메인/IP 제한, 권한 범위 제한, 사용량 제한을 함께 걸어 둡니다.
  • URL 쿼리(?api_key=...)에 키를 넣으면 서버 로그나 브라우저 기록에 남기 쉬우므로, 가능하면 헤더로 보냅니다.

방법 5: OAuth 2.0 ​

"카카오로 로그인", "구글로 로그인"처럼, 내 비밀번호를 알려 주지 않고도 다른 앱에 내 정보 일부를 쓸 권한을 주는 방식입니다.

  • API Key는 "키를 가진 프로그램"에 권한을 주지만, OAuth는 사용자가 직접 동의한 범위(scope)만큼만 권한을 줍니다.
  • 앱은 비밀번호 대신 Access Token을 받아서 정해진 범위의 데이터만 가져옵니다.
  • OAuth는 원래 인가(권한 위임)를 위한 규칙입니다. "누구인지 확인하는 로그인" 용도로 쓸 때는 그 위에 얹은 OpenID Connect를 씁니다.

자세한 흐름은 OAuth 글에서 다룹니다.

방식별 비교 ​

방식무엇을 보내나요서버 상태주로 쓰는 곳주의할 점
Basic아이디:비밀번호 (Base64)없음사내 도구, 테스트반드시 HTTPS, 비밀번호가 매번 오감
세션세션 ID 쿠키있음일반 웹사이트서버 확장 시 저장소 공유, CSRF 대비
토큰 (JWT)Bearer 토큰없음모바일 앱, API 서버탈취 시 만료 전까지 유효, 저장 위치
API Key발급받은 키키 목록만 보관서버 간 통신, 공개 API유출 시 즉시 교체, 코드에 넣지 않기
OAuth 2.0Access Token인가 서버가 관리소셜 로그인, 외부 앱 연동범위(scope) 최소화, PKCE 사용

코드로 감 잡기: Base64는 암호화가 아니다 ​

Basic 인증 헤더를 직접 만들고 되돌려 보고, API Key를 확인하는 간단한 함수도 만들어 봅니다.

python
import base64
import hmac

# Basic 인증: "아이디:비밀번호"를 Base64로 바꿔 헤더에 실어 보냄
token = base64.b64encode(b"1mo:my-password").decode()
print("Authorization: Basic " + token)

# 하지만 Base64는 암호화가 아니라서 누구나 바로 되돌릴 수 있음
print(base64.b64decode(token).decode())

# API Key 확인: 서버가 저장해 둔 키와 비교 (비교 시간이 새지 않는 함수 사용)
SAVED_KEYS = {"demo-key-1234": "1mo"}

def check_api_key(key):
    for saved, owner in SAVED_KEYS.items():
        if hmac.compare_digest(saved, key):
            return f"{owner}의 키, 요청 허용"
    return "401 Unauthorized"

print(check_api_key("demo-key-1234"))
print(check_api_key("wrong-key"))

실행 결과:

Authorization: Basic MW1vOm15LXBhc3N3b3Jk
1mo:my-password
1mo의 키, 요청 허용
401 Unauthorized
  • 두 번째 줄처럼 Base64는 한 줄로 원래 비밀번호가 드러납니다. 그래서 Basic 인증은 HTTPS가 필수입니다.
  • 키를 비교할 때 == 대신 hmac.compare_digest를 쓴 이유는, ==는 앞 글자부터 비교하다 다르면 바로 멈추기 때문에 응답 시간 차이로 키를 한 글자씩 알아내는 공격(타이밍 공격)이 가능하기 때문입니다. compare_digest는 항상 같은 시간이 걸리도록 비교합니다.
  • 실제 서비스에서는 비밀번호처럼 API Key도 원본 대신 해시 값으로 저장해 두는 것이 더 안전합니다.

면접에서 자주 나오는 질문 ​

Q. 인증과 인가의 차이는 무엇인가요? A. 인증은 사용자가 누구인지 확인하는 것이고, 인가는 확인된 사용자가 특정 자원에 접근할 권한이 있는지 확인하는 것입니다. 인증 실패는 401, 인가 실패는 403으로 응답합니다.

Q. 세션 기반 인증과 토큰 기반 인증의 차이는 무엇인가요? A. 세션은 서버가 사용자 상태를 저장해 두고 세션 ID로 찾아보는 stateful 방식이고, 토큰(JWT)은 사용자 정보와 서명을 토큰 안에 담아 서버가 저장소 없이 검증하는 stateless 방식입니다. 세션은 강제 로그아웃이 쉽고, 토큰은 서버 확장이 쉽습니다.

Q. API Key 방식의 단점은 무엇인가요? A. 키 하나로 신원과 권한이 모두 결정되기 때문에 유출되면 그대로 악용됩니다. 키 주기적 교체, 허용 IP·도메인 제한, 권한 범위와 사용량 제한, 서버 환경 변수에만 보관하는 식으로 위험을 줄입니다.

Q. Basic 인증은 왜 HTTPS 없이 쓰면 안 되나요? A. Base64는 암호화가 아니라 인코딩이라 누구나 원래 값으로 되돌릴 수 있고, 요청마다 비밀번호가 실려 가므로 통신을 엿보면 바로 비밀번호가 노출됩니다.

정리 ​

개념한 줄 요약
인증 (Authentication)누구인지 확인. 실패하면 401
인가 (Authorization)무엇을 해도 되는지 확인. 실패하면 403
Basic 인증아이디:비밀번호를 Base64로 매번 전송. HTTPS 필수
세션 기반서버가 상태 보관, 세션 ID 쿠키로 식별. 강제 로그아웃 쉬움
토큰 기반토큰을 Bearer로 전송. JWT면 서버가 상태를 몰라도 검증 가능
API Key프로그램용 발급 키. 유출 대비가 핵심
OAuth 2.0비밀번호 대신 사용자가 동의한 범위의 토큰을 받아 쓰는 권한 위임