TL;DR
- RESTful의 특징 중 하나는 Stateless이다.
- 세션은 인증 정보를 서버가 보관하기 때문에 Stateless를 위반한다.
- sakd.uk은 JWT 방식을 채택하였다.
세션 vs JWT
2014년 말, sakd.uk을 싱글 페이지로 띄웠습니다.
그리고 본격적으로 개발을 시작하는 첫 단계로 회원제를 도입하기로 했습니다.
그리고 바로 사용자 인증을 위해 어떤 방식을 써야할지부터 고민이 시작되었습니다.
인증과 인가의 차이
인증(Authentication)과 인가(Authorization)는 서로 다른 의미이다.
인증은 사용자의 신원을 검증하는 행위이고, 인가은 접근 권한을 확인하는 행위이다.
즉, 로그인을 하지 않고 비밀글을 열어보고자 했다면 인증 단계에서 거부가 발생한 것이고,
로그인은 했으나 다른 사람의 비밀글을 열어보고자 했다면 인가 단계에서 거부가 발생한 것이다.
세션 인증 방식과 토큰 인증 방식의 장단점을 비교해보았습니다.
세션 인증 방식 | 토큰 인증 방식 | |
인증 정보 저장 위치 | 서버 | 클라이언트 |
인증 정보의 형태 | 쿠키 | 토큰 문자열 |
인증 정보 검증을 위해 서버가 수행하는 작업 |
쿠키와 함께 보내준 세션 ID를 이용하여 DB에서 사용자 정보 조회 |
전달된 토큰 복호화 |
서버에서 사용자 인증 정보를 무효화 할 수 있는가 |
가능. 세션 정보가 서버에 저장되어 있음. |
불가능. 토큰 정보가 클라이언트에 저장되어 있음. |
취약한 공격 | 중간자 공격, 크로스 사이트 요청 위조(CSRF) | 중간자 공격, 토큰 탈취, 비밀키 유출 |
적합한 연결 형태 | 서버-사용자간 통신 | 서버간 통신 |
장단점과 구현 용이성을 종합적으로 고려해봤을 때, sakd.uk에는 세션 인증 방식이 더 적합하다 판단되었습니다.
다만, sakd.uk 서비스를 클라이언트 서버와 API 서버로 분리하면서,
API 서버는 최대한 RESTful하게 구현해보고픈 생각이 들었습니다.
REST API의 대표적 특징
REST API는 HTTP를 기반으로, URI는 자원을 명시하고, Method로 행위를 정의하는 API를 말합니다.
때문에 REST API를 개발할 때에는 HTTP의 특징을 함께 고려하여야 합니다.
HTTP의 특징 중 대표적인 2개는 아래와 같습니다.
비연결성(Connectionless)
서버가 클라이언트의 요청에 대해 응답을 했다면, 연결을 유지하지 않고 즉시 끊는 특징입니다.
서버는 각각의 요청을 처리하고나면 연결을 끊어버리고 자원을 회수하기 때문에,
서버는 동시에 더 많은 클라이언트의 요청을 처리할 수 있게 됩니다.
무상태성(Stateless)
비연결성 특징을 생각해보면 클라이언트의 상태를 계속 기억하고 있을 수 없습니다.
때문에 한 번의 요청으로 하나의 행위를 할 수 있어야 한다.
만약 sakd.uk의 사용자가 로그인을 하고 나서 나의 sakd.uk URL 목록으로 진입하여 3페이지를 불러오고자 한다고 생각해보면,
각각 아래와 같이 요청을 해야합니다.
- 로그인 후 쿠키 혹은 토큰을 발급받는다. (ID/PW 전달)
- 쿠키 혹은 토큰을 담아, 나의 sakd.uk URL 목록을 요청한다. (Token, 요청 자원명 전달)
- 쿠키 폭은 토큰을 담고, 3페이지를 파라미터에 담아, 나의 sakd.uk URL 목록을 요청한다. (Token, 요청 자원명, 파라미터 전달)
이 무상태성의 특징 때문에 일부 HTTP 메소드는 멱등성을 지니기도 합니다.
예를 들어 동일한 토큰과 동일한 파라미터를 담아 GET 요청을 한다면,
다른 사용자가 데이터를 수정하지 않은 한 항상 같은 결과를 얻게 됩니다.
세션은 RESTful하지 않다
RESTful한 서버를 만드려면 위 대표적 특징을 포함하여 구현을 해야합니다.
무상태성을 준수하기 위해 인증 정보는 클라이언트에 저장하고, 자원을 요청할 때에는 인증 정보와 함께 서버로 요청해야 합니다.
하지만 세션 인증 방식은 인증 정보를 서버가 기억하고 있습니다.
따라서 세션 인증 방식은 무상태성을 위반하는 방식이고, RESTful하지 않습니다.
다만 RESTful한 서버가 그렇지 않은 서버보다 더 좋다는 뜻은 절대 아닙니다.
오히려 RESTful함을 포기함으로서 토큰 인증 방식보다 더 간단하게 구현이 가능하고,
토큰 탈취 등의 위협으로부터 더 안전한 방식을 사용할 수도 있습니다.
결론
저는 sakd.uk 개발에서 API 서버를 최대한 RESTful하게 구현하고자 하였기 때문에 JWT 방식을 채택했습니다.
하지만 만약 실무에서 납품해야 하는 실제 제품이라면 아래 방식을 채택할 것입니다.
- 세션 인증 방식 사용
- 세션 저장을 위해 Redis 사용
참고 문서
- REST API란? REST, RESTful이란? - 히진쓰의 서버사이드 기술 블로그 - (https://khj93.tistory.com/entry/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-REST-API%EB%9E%80-REST-RESTful%EC%9D%B4%EB%9E%80)
- REST API 와 HTTP Stateless 에 대한 고찰 - wally.log (https://velog.io/@yhlee9753/REST-API-%EC%99%80-HTTP-Stateless-%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B3%A0%EC%B0%B0)
- HTTP RESTful API / 안전성과 멱등성 - history dump 🌈 - (https://plustory.tistory.com/entry/REST-API)
- Do Sessions Violate RESTfulness? - Baeldung - (https://www.baeldung.com/cs/rest-sessions)
- Session Vs JWT - Piyali Das(https://medium.com/@piyalidas.it/session-vs-jwt-172d0cd327a1)