그동안 작성한 API들 중에 로그인을 하지 않은 상태에서 사용할 수 있는 API들은 얼마나 있을까? 아마 거의 대부분의 API들이 회원을 위한 API들일 것이다. HTTP의 가장 큰 단점은 상태를 저장하지 않는다는 것이다 (stateless). 이를 보완하기 위한 로그인 상태를 유지하는 방법이 3가지가 있다.
단순히 Session ID
를 가지고 있기만 하면 모든 권한을 갖게 되는 것이다. 그만큼 보안에 취약하기도 하다. 반대로 말하면 Session ID
가 노출되는 순간 주인이 가진 모든 권한을 타인도 가질 수 있다는 뜻이다.
ID
, PWD
를 입력해준다. ID
, PWD
를 DB로 보내 해당 회원이 있는지 조회한다.User Session ID
를 저장한다.User Session ID
는 서버로 보내지고 서버는 이를 클라이언트에게 보낸다.User Session ID
를 Cookie
에 저장한다.User Session ID
를 통해 회원용 API에 접근할 수 있게 된다.User Session ID
가 노출될 경우 보안상 위험도가 증가한다.OAuth
는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로 사용되는 접근 위임을 위한 개방형 표준이다.
ID
,PWD
,권한리스트
를 보낸다. (이 때 클라이언트는 웹, 서버, 안드로이드, IOS 모두 될 수 있고, 서버는 카카오, 네이버, 애플 등이 될 수 있다.)Refresh Token
을 발급해준다. (Refresh Token
을 다시 서버로 보낸다.Refresh Token
을 받은 서버는 클라이언트에게 Access Token
을 발급해준다.Access Token
을 통해 회원용 API에 접근할 수 있게 된다.이 때 Refresh Token
은 등장 횟수는 적지만 Acces Token
발급을 위해 반드시 필요한 존재이고, Acces Token
은 유효기간이 짧은 특징이 있다.
로그인에 성공하면 서버는 인코딩한 문자열을 토큰인것처럼 보내게 되는데, 클라이언트는 요청을 보낼 때마다 이를 헤더에 실어서 같이 보내어 권한을 검증하게 된다. 이를 JWT
라고 하며, 인증에 필요한 정보들을 암호화시킨 토큰을 뜻한다. SSL 통신(HTTPS)
을 통해 패킷 자체를 못 보게 할 수 있다. 그래서 JWT
에는 SSL
을 반드시 적용해주는 것이 좋다.
ID
, PWD
를 입력한다.ID
, PWD
를 DB로 보내 확인한다.JWT
를 서버에서는 저장하지 않고 클라이언트만 저장한다. 클라이언트가 서버에 JWT
를 보낼때마다 이를 검증한다. -> 구현이 쉽다.Token
자체에 데이터가 담긴다. -> Packet
이 크고 해당 데이터를 누구든 볼 수 있기 때문에 HTTPS를 꼭 적용시켜줘야 한다.JWT
= Header
+ Payload
+ Signature
Header
, Payload
와 관리자가 지정한 Secret Key
를 더한 후 서명카카오 로그인을 예로 작성하였다.
클라이언트, 카카오 서버, 서버, DB
로그인
요청 -> 카카오 서버Refresh Token
발급 -> 클라이언트Refresh Token
전송 -> 카카오 서버Access Token
발급 -> 클라이언트Access Token
전송 -> 서버 Access Token
전송 -> 카카오 서버카카오 계정 정보
전송 -> 서버카카오 계정 정보
전송 -> DBResponse
-> 서버배달의 민족에서의 카카오페이 결제를 예로 작성하였다.
클라이언트, 카카오페이, 카드사, 배민 서버, 배민 DB
결제 요청
-> 카카오페이충전 요청
-> 카드사충전
-> 카카오페이영수증
-> 클라이언트영수증
-> 배민 서버영수증 검증
-> 카카오페이검증 결과
-> 배민 서버Data
-> 배민 DBData 저장
+Response
-> 배민 서버Server Response
-> 클라이언트구현하게 된다면 부트페이 문서를 참고하자.
은행의 송금 시스템을 예로 들 수 있다. A가 B에게 100만원을 송금한다고 가정해본다면 다음과 같다.
이 과정 중에서 어느 한 곳에서라도 에러가 발생하게 된다면 상당히 큰 문제가 될 수 있다. 트랜잭션
은 과정 중 에러가 발생하면 작업 전 단계로 DB를 RollBack
시키는 기법이다.
await connection.beginTransaction();
await connection.commit();
await connection.rollback();