이롭게 현명하게
[IT노트] 인증과 인가, JWT 정리 본문

목차
인증(Authentication)과 인가(Authorization)
로그인 상태 유지하기
세션 방식 이해하기
토큰 방식
JWT 구조
세션 vs JWT 비교
JWT의 한계와 보완 방법(Refresh Token)
정리
[인증(Authentication)과 인가(Authorization)]
로그인 기능을 구현할 때 단순히 데이터베이스에 있는 내용과 일치하면 로그인이 가능하게 구현하였다.

하지만 이 방식은 보안상 취약하다.
사용자가 입력한 정보로 데이터베이스에서 필드를 찾는 방식은 사용자의 인증 정보를 안전하게 처리하지 못할 뿐 아니라 로그인 상태를 유지하는 데도 한계가 있다.
이러한 기본적인 로그인 구현을 넘어서 마주한 문제는 안전하게 로그인 상태를 유지하는 것이다.
단순히 사용자 인증에 성공하는 것만으로는 충분하지 않다.
사용자가 한 번 로그인을 하면 사용자가 로그인한 상태인 것을 서버가 알고 있어야 한다.
만약 로그인 상태가 유지가 안된다면 사용자가 메일함에 들어갈 때마다, 메일을 읽거나 삭제, 전송을 할 때마다 매번 로그인을 해야 하는 불편함을 겪게 된다.
그래서 인증과 인가를 어떻게 처리할지, 로그인 상태를 유지하는 것이 가장 까다로운 부분이다.
로그인 구현 시 단순한 사용자 확인을 넘어서 세션관리, 토큰 기반 인증 등의 보안 방식을 고려해야 한다.
이때 가장 기본적으로 알아야 하는 것은 인증과 인가이다.
- 인증(Authentication) : "누구세요?"
- 사용자가 본인임을 증명하는 단계
- 예 : 로그인
- 인가(Authorization) : "나 이거 해도 돼?"
- 사용자가 사이트에 대한 권한을 허락하는 것
- 접근 권한을 부여하거나 거부하는 행위
- 예 : 로그인 사용자만 이용 가능, 관리자만 접근 가능한 페이지
| 인증(Authentication | 인가(Authorization) | |
| 의미 | 사용자가 누구인지 확인하는 과정으로 증명을 하는 행위 | 사용자가 사이트에 대한 권한을 허락하는 것으로 접근 권한을 부여하거나 거부하는 행위 |
| 예시 | 회원가입, 로그인 | 관리자 권한 확인 |
| 순서 | 먼저 수행된다. | 인증 후 수행된다. |
[로그인 상태 인식하기]
로그인 상태를 유지하려면 로그인을 한 상태를 인식해야 한다.
<로그인 상태를 인식하는 두 가지 방법>
- 로그인 상태
- 비로그인 상태
사용자 중 로그인을 한 사용자와 로그인을 하지 않은 비로그인 상태의 사용자가 있다.
서버는 사용자가 요청을 보내면 사용자가 로그인이 되어있는 상태인지 먼저 확인을 한 후 로그인한 사용자에게만 허용된 기능을 이용할 수 있도록 응답한다.
예를 들어, 로그인을 한 상태라면 메일을 보내거나 댓글을 작성할 수 있는 기능을 사용할 수 있다.
비로그인 사용자는 이용할 수 없는 기능이다.

이렇게 매번 서버에 요청할 때마다 아이디와 비밀번호를 같이 보내면 서버는 그걸 보고 로그인 여부를 판단할 수 있다.
하지만 이 방식에는 큰 문제점이 있다.
<문제점>
- 성능 문제
- 보안 문제
1. 성능 문제
서버는 로그인 정보를 확인하기 위해 데이터베이스에 있는 사용자 정보를 확인해야 한다.
이때 데이터베이스에 저장된 사용자 정보는 암호화(해시)되어 있다.

단순히 암호화된 데이터를 꺼내서 사용하는 것이 아닌 데이터를 비교할 수 있도록 복잡한 알고리즘으로 계산해서 비교해야 한다.
이 방식은 계산하기에는 많은 시간이 소요된다.
또한 이걸 매번 요청한다면 서버에 부담이 커진다.

2. 보안 문제
만약 요청마다 아이디랑 비밀번호를 계속 보내면 누군가(해커)가 그 요청을 중간에서 가로채면 비밀번호가 유출될 위험이 있다.
특히 보안이 완벽하지 않은 네트워크(예 : 공공 와이파이)에서는 위험하다.

이런 문제를 해결하기 위해 나온 것이 토큰이다.
보통 처음 한 번만 로그인하고 서버가 '이 사용자는 로그인을 한 상태다'라는 것을 나타내는 토큰을 만들어준다.
이 토큰을 브라우저가 저장해 두고 서버에 요청할 때는 아이디/비밀번호 대신 토큰만 보낸다.
그럼 서버는 빠르고 안전하게 로그인한 사용자라는 것을 확인할 수 있다.
[로그인 상태를 유지하는 방식]
로그인 상태를 유지하는 두 가지 방법이 있다.
<로그인 상태를 유지하는 방법>
- 세션(Session) 기반
- 토큰(Token) 기반
로그인 상태를 유지하는 방법으로는 세션과 토큰 방법 중 하나를 이용하면 된다.
둘 다 인증 방식은 유사하다.
사용자가 로그인을 하면 서버는 사용자에게 입장권을 발급해 준다.

사용자가 웹사이트에 게시글을 작성하거나, 데이터를 요청할 때마다 입장권을 함께 보낸다.

그러면 서버는 입장권을 확인하여 인증된 사용자라는 것을 판단한다.

입장권에 문제가 없다면 서버는 요청을 받아들이고 사용자는 정상적으로 웹사이트를 이용할 수 있다.

만약 입장권에 문제가 있다면 웹사이트를 이용할 수 없다.
![]() 유효하지 않은 입장권 |
![]() 인증 실패 |
[세션 방식 이해하기]
사용자가 로그인에 성공하면 서버는 사용자를 기억하기 위해 '세션 id'를 만든다.
이 세션 id는 고윳값으로 세션 id 전체를 사용자 브라우저에 쿠키 형태로 보낸다.



서버는 이 세션 id를 키로 하여 로그인한 사용자 정보를 서버 측 메모리, 하드디스크, 데이터베이스 중 한 곳에 저장해 둔다.
로그인한 사용자는 세션 ID를 받는다.

이후 사용자가 세션 id를 받은 상태로 브라우저를 통해 사이트를 이용한다.
사용자가 사이트의 기능을 이용하여 브라우저에서 서버에 요청을 보낼 때마다 이 세션 ID 쿠키가 서버에 함께 전송된다.

요청을 받은 서버는 전달받은 세션 id와 서버에 저장된 세션 정보와 일치하는지 확인하여 로그인이 된 사용자인지 확인한다.
확인이 되면 로그인 상태를 유지한다.
이처럼 세션 id를 사용해서 사용자가 로그인 상태임을 유지하는 이 상태를 '세션'이라고 한다.
<세션 저장소별 특징>
메모리
- 장점
- 빠르다
- 단점
- 서버가 꺼지면 세션 정보가 날아간다.(휘발성)
- 접속자가 많아지면 메모리가 부족해지고 서버에 부담이 된다.
- 세션 정보가 없어지면 사용자들은 다시 로그인을 해야 한다.
하드디스크
- 장점
- 서버가 꺼져도 세션 정보가 유지된다.
- 상대적으로 메모리보다 안정적이다.
- 단점
- 디스크 입출력으로 인해 처리 속도가 느려 성능에 영향을 줄 수 있다.
데이터베이스
- 장점
- 세션 정보를 안정적으로 저장할 수 있다.
- 다수의 서버에서 세션 공유가 용이하다.
- 단점
- 메모리보다는 속도가 느리다.
- 트래픽이 많아지면 데이터베이스에 부하가 증가할 수 있다.
redis나 Memcached 같은 인메모리 저장소
- 장점
- 메모리 기반이라 빠르다.
- 클러스터링과 확장을 통해 대용량 처리도 가능하다.
- 단점
- 서버가 여러 대일 경우 각 서버가 공유 메모리를 사용하지 않으면 세션 정보가 공유되지 않아 세션 유지에 문제가 발생한다.
- Redis 자체가 장애 시 전체 세션 관리에 문제가 생길 수 있다.
[서버가 여러 대일 때]
서버가 여러 대일 경우 로드밸런싱을 통해 트래픽을 분산시킨다.
서버 1번이 사용자의 로그인 요청을 처리 후 서버 2번으로 가야 할게 서버 3번으로 간다면 서버 3번은 해당 사용자의 세션 정보가 없어 로그인 상태를 확인할 수 없다.
그래서 세션이 유지되지 않는 문제가 발생한다.
이 문제를 해결하려면 다음과 같은 방식이 필요하다.
- 세션 정보를 공통 저장소(Redis,DB 등)에 저장하여 모든 서버가 공유하게 한다.
- 또는 특정 사용자 요청이 항상 같은 서버로 가도록 '세션 스티키(Session Sticky) 전략을 사용한다.
세션은 사용자의 로그인 상태를 유지하기 위한 서버의 기억장치이다.
어디에 세션을 저장하느냐에 따라 속도, 안정성, 확장성이 달라진다.
프로젝트의 규모가 커질수록 이 세션을 안전하고 빠르게 유지하는 게 어려워지고 설계가 중요해진다.
그래서 이런 부담 없이 구현하기 위해 나온 방법이 토큰 방식인 JWT이다.
[JWT 토큰 방식]
JWT(JSON Web Token)란?
JWT는 인증과 인가에 관련된 기술이다.
- 토큰 관련된 인증은 대부분 로그인할 때 사용
- JWT는 웹 표준을 따르고 있다.
- JSON 객체를 사용하여 정보를 전달한다.
- 필요한 모든 정보를 한 객체에 담아서 전달하기 때문에 JWT 한 가지로 인증을 마칠 수 있다.
JWT를 사용한 토큰 방식은 서버가 상태를 저장하지 않는 방식이다.(stateless)
단순히 '이 사용자는 인증됐다'라는 정보를 토큰에 담아서 준다.
사용자는 이 토큰을 들고 다니면서 서버에 요청할 때마다 토큰을 보내면 된다.

사용자가 로그인을 하면 서버는 JWT 토큰을 발급한다. (긴 암호문 같은 문자열)
브라우저는 이 토큰을 쿠키나 로컬스토리지에 저장한다.

사용자가 사이트의 기능을 이용하여 브라우저에서 서버에 요청을 보낼 때마다 이 토큰을 같이 보낸다.
서버는 토큰 안의 정보와 서명으로 유효한 토큰인지 검증만 하면 된다.

<장점>
- 서버가 세션을 저장하지 않아도 됨 → 확장성 뛰어남
- 어떤 서버에 요청이 가도록 처리 가능 → 로드밸런싱에 유리
- 서버 여러 대여도 상관없다. 어디서든 토큰만 있다면 처리 가능
<단점>
- 토큰이 노출되면 위험 → HTTPS로 전송해야 함
- 토큰이 만료되기 전까지는 강제로 무효화하기 어려움(로그아웃 처리 복잡)
[JWT 구조]
JWT는 세 부분으로 구성되며 각 부분은.(dot 점)으로 구분된다.
인코딩 또는 암호화된 3가지 데이터를 이어 붙인 것이다.
HEADER.PAYLOAD.SIGNATURE
- HEADER : 헤더
- PAYLOAD : 내용
- SIGNATURE : 서명
1. HEADER(헤더)
- 이 입장권이 어떤 방식으로 발급되었는지 알려주는 "양식"같은 부분
- 어떤 알고리즘으로 서명되어 있는지 명시(예 : HMAC, SHA256)
- 일반적으로 다음과 같은 정보를 포함
{
"alg" : "HS256",
"typ" : "JWT"
}
- type
- 토큰의 타입을 나타낸다.
- 항상 JWT로 고정하여 JWT임을 나타내는 식별자
- alg
- SIGNATURE(서명) 생성에 사용하는 암호화 알고리즘
- 예 : HS256, RS256 등
2. PAYLOAD(내용)
- 영화관 입장권에 적힌 "티켓의 주인, 어떤 권한이 있는지"에 해당하는 정보
- 토큰에 담길 실제 정보(예: 사용자 ID, 권한 등)
- Base64로 인코딩 되어 있어서 누구나 디코딩하면 읽을 수 있다.
- 클레임(Claim)이라 불리는 사용자 정보 및 기타 데이터가 포함된다.
- Claim : 사용자의 정보를 담고 있는 데이터 조각
- 클라이언트(사용자)가 로그인 후 발급받은 토큰에 이 클레임들이 포함되어 있다.
- 예시
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022
}
3. SIGNATURE(서명)
- 이 티켓이 진짜라는 것을 증명하는 "도장"같은 부분
- 무결성과 위변조 방지를 위해 사용
- 토큰 위변조를 막기 위해 반드시 서버가 서명을 검증해야 한다.
- HEADER + PAYLOAD + 서버만 알고 있는 비밀키(Secret Key) = SIGNATURE
- 이 세 가지를 alg에 명시된 암호화 알고리즘에 넣고 돌리면 SIGNATURE이 생성된다.
- Secret Key는 개발자 마음대로 세팅할 수 있다.
- 예시
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
또는a-string-secret-at-least-256-bits-long
<SIGNATURE가 중요한 이유>
- 사용자가 토큰을 위조하거나 PAYLOAD를 조작하더라도 서버가 서명을 다시 계산해서 검증하면 서명이 일치하지 않으면 즉시 거부된다.
- 이 서명은 비밀키 없이는 절대 만들 수 없다. 토큰을 탈취해도 글자 하나만 바꿔도 서명값은 완전히 달라지기 때문이다.
- 단방향 알고리즘 사용으로 서명값으로부터 비밀키나 원래 데이터를 역산하는 건 사실상 불가능하다.
<전체 예시>
위 JSON의 내용을 암호화하면 다음과 같은 결과가 나타난다.
HEADER와 PAYLOAD를 인코딩한 것이 아래와 같다.
// 원래는 한줄인데 보기 편하게 .에 줄바꿈을 했습니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- HEADER : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
- PAYLOAD : eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
- SIGNATURE : SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c










[세션 vs JWT]
- 세션 방식
- 입장권에 쓰여있는 정보가 많이 없다.
- 입장권 발급 번호 정도로 기본적인 정보들만 적혀있다.
- 사용자가 입장권을 제시하면 서버가 메모리나 DB에 만들어 두었던 입장권 발급 목록 파일(=세션 스토어)에서 발급 번호를 가진 데이터를 조회하여 사용자를 통과시켜 주는 방식으로 진행된다.
- 구현이 복잡하고 부하가 크지만 통제와 보안이 강하다.
- 토큰 방식
- 입장권에 쓰여있는 정보가 많다.
- 사용자 이름, 이메일, 발급일, 유효기간 등이 적혀있다.
- 서버는 입장권을 검사할 때 입장권 자체 하나만으로 검사하여 사용자를 통과시킨다.
- 편리하고 확장성이 좋지만 통제가 어렵다.
그래서 프로젝트 상황에 따라 다르게 사용해야 한다.
| 추천 방식 | 상황 |
| JWT | 단순 로그인, 서버 확장이 중요할 때, 또는 회원이 많아 입장권 목록을 조회하기 힘든경우 |
| 세션 | 민감한 정보를 다루고 통제가 중요할 때 |
<JWT 방식의 장점>
- stateless : 서버가 사용자 상태를 기억하지 않는다.
- 사이트에 사용자가 많아질수록 서버에 부담이 적어진다.
- 기존의 세션 방식은 사용자가 입장권을 제시할 때마다 서버에 있는 입장권 발급 목록 파일(=세션 스토어)에서 조회해야 하기 때문에 힘들어진다.
- JWT는 사용자가 입장권을 제시하면 입장권만 확인하면 되기 때문에 처리가 매우 빨라진다.
- 서버가 매 요청마다 데이터베이스를 조회하지 않아도 된다.(토큰자체에 사용자의 권한 및 상태 정보가 담겨 있으므로)
- 클라이언트가 토큰을 가지고 다니며, 요청 시마다 서버에 함께 전송. 즉, 토큰 === 인증증명서
- 서버는 토큰 자체만 검증하고 그 내용을 신뢰한다.
<JWT 방식의 단점 및 문제>
- 보안 이슈
- PAYLOAD는 암호화되어 있지 않다.
- Base64로 인코딩 되어 있어서 누구나 디코딩하면 읽을 수 있다.
- 그래서 JWT에 민감한 정보를 넣어서는 안 된다. 최소한의 정보만 넣어야 한다.
- 클라이언트가 임의로 PAYLOAD를 조작할 수 있다.
- 예 : isAdmin:false → true로 바꿈, exp(만료시간)을 미래로 설정
- 하지만 서버는 토큰의 SIGNATURE(서명)을 검증하기 때문에 PAYLOAD가 조작되었으면 서명이 일치하지 않게 된다 → 거부됨
- PAYLOAD는 암호화되어 있지 않다.
- 무효화가 불가능하다.
- 이미 발급된 토큰은 서버가 통제할 수 없다.
- 만약 해커가 토큰을 탈취하면 서버가 몰라도 계속 사용이 가능하다.
- 토큰이 탈취되면 그 유효기간 동안은 막을 방법이 없다.
- 세션 방식이면 세션 삭제로 끝나지만 JWT는 그런 중앙제어 포인트가 없다.
- 사용자를 강제로 로그아웃 시키는 기능도 없다.
예시 상황
어떤 유저가 A 기기에서 로그인한 상태에서 B기기에서 로그인을 하면 A기기를 자동로그아웃 시키고 싶다?
→ 세션 방식이면 가능,
→ JWT는 이미 발급된 토큰을 제거 못 해서 불가능
[JWT의 한계와 보완 방법(Refresh Token)]
JWT의 단점을 보완하기 위한 구조로 Access Token과 Refresh Token이 있다.
- Access Token
- 짧은 수명(n분~n시간)
- 인가(Authorization)를 받을 때마다 사용하는 주요 토큰
- 탈취되더라도 금방 만료되므로 위험이 제한적
- Refresh Token
- 긴 수명(보통 2~3주)
- Access Token이 만료됐을 때만 사용
- 서버는 Refresh Token을 DB에 저장하여 관리
- 클라이언트가 Refresh Token을 보내면 서버는 DB에서 검증 후 새 Access Token을 발급
[장점]
- Access Token이 탈취돼도 수명이 짧아 오래 쓸 수 없다.
- Refresh Token을 DB에서 삭제하면 해당 사용자의 인증 갱신은 차단됨 →사실상의 강제 로그아웃 기능
[단점]
- 완전 무효화는 불가능하다.
- Access Token은 만료 전까지 유효
- 탈취 시 일정 시간 동안은 막을 수 없다.
- 구현 복잡도가 증가한다
- 토큰 재발급 로직, 만료처리, 예외 처리 등 추가 작업 필요
- Refresh Token 탈취 시 더 큰 위험
- 긴 수명을 가지므로 탈취되면 지속적으로 Access Token 재발급 가능
- 완전한 Stateless 구조가 아니다
- Refresh Token을 서버(DB)에 저장해야 하므로 상태 관리가 필요
- 기기별 로그인 관리가 복잡하다
- 여러 디바에스에서 로그인 시 토큰 관리 전략이 필요
[정리]
| 항목 | 세션 방식 | JWT 방식 |
| 상태 저장 | 서버가 세션 기억 | 서버는 아무것도 기억 안함 |
| 저장 위치 | 서버 메모리, Redis 등 | 클라이언트가 JWT 보관 |
| 서버 확장성 | 따로 관리 필요 서버 1대면 쉬움 여러대면 복잡 사용자 수가 많아지면 세션 관리 부담 커짐 |
유리 서버 여러대여도 문제 없음 서버 확장에 유리(무상태 처리) |
| 보안 | 상대적으로 안전 세션 ID 만료/삭제로 무효화 가능 |
노출되면 위험함 JT는 한 번 발급되면 서버에서 취소 불가 |
| 로그아웃 | 세션 삭제 | 토큰 만료 기다려야함 |
| 유실 위험 | 서버 꺼지면 세션 날아감 | 토큰은 클라이언트에 있으니 유지됨 |
| 속도 | 빠름(메모리),느림(DB) | 토큰 검증만 하면 되니 빠름 |
| 관리와 제어 | 서버에서 개별 세션을 삭제/제어 가능 | JWT는 한 번 발급되면 서버에서 취소 불가 |
잘못된 정보는 댓글에 남겨주시면 감사하겠습니다!😊
댓글과 좋아요는 큰 힘이 됩니다!

[ 참고자료 ]
JSON Web Tokens - jwt.io
JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature (JWS).
www.jwt.io
https://www.youtube.com/watch?v=XXseiON9CV0
https://www.youtube.com/watch?v=1QiOXWEbqYQ
[아이콘 출처]
<a href="https://www.flaticon.com/kr/free-icons/ui" title="ui 아이콘"> Ui 아이콘 제작자: Freepik - Flaticon </a>
<a href="https://www.flaticon.com/kr/free-icons/" title="암호화 아이콘"> 암호화 아이콘 제작자: Freepik - Flaticon </a>
<a href="https://www.flaticon.com/kr/free-icons/" title="하드디스크 아이콘"> 하드디스크 아이콘 제작자: kerismaker - Flaticon </a>
<a href="https://www.flaticon.com/kr/free-icons/-" title="데이터 베이스 아이콘"> 데이터 베이스 아이콘 제작자: Vectorslab - Flaticon </a>
<a href="https://www.flaticon.com/kr/free-icons/-" title="램 메모리 아이콘"> 램 메모리 아이콘 제작자: Freepik - Flaticon </a>
'IT 노트' 카테고리의 다른 글
| [IT노트] 패키지 매니저란? / npm, yarn, pnpm 정리 (0) | 2026.04.29 |
|---|---|
| [IT 노트] 라이브러리와 프레임워크 (0) | 2023.12.08 |
| [IT 노트] 앱 개발 유형 / 네이티브 앱 / 하이브리드 앱 / 크로스 플랫폼 (1) | 2023.11.20 |
| [IT 노트]오픈 소스와 라이선스 (0) | 2022.11.15 |


