- 할 일 목록 관리 서비스 만들어보기
- 아주 느리고 미세하지만 조금씩 진행을 해나가고 있다.
- 오늘은 로그인, 회원가입 페이지의 UI 이벤트 처리 작업을 완료했다
Input
컴포넌트의 Validation 경고 메시지와Button
컴포넌트의 disable 처리, 그리고 각 상태의 초기값 설정 등을 일치시키느라 어제 새벽에 애를 먹었는데, 막상 오늘 다시 고민해 보니 꽤 쉽게 풀렸다. 좀 억울하긴 했는데, 맑은 정신으로 생각하면 안 풀리던 것도 풀린다는 걸 경험적으로 배울 수 있어서 (나름) 괜찮았다.- 이제 로그인 API 요청을 보내는 걸 구현해야 하는데, 아직 인증/인가에 대한 지식이 거의 없다싶이해서, 개발에선 손을 떼고 인증/인가 구현에 대한 이런저런 자료들을 찾아봤다. 아직 100% 완벽히 소화하진 못해서 틀린 내용이 있을 수 있는데, 일단 오늘 자료 찾아보면서 알게 된 내용들 쭉 나열해 둔다.
- 인증/인가는 쉽게 얘기해서 '이 클라이언트 유저가 권한을 인증받은 사람이고, 이 사람이 받은 권한은 A, B, C... 등이다'라는 정보를 관리하는 방식을 의미한다.
- http 통신은 Stateless 한 특성이 있다고 한다. Stateless는 특정한 정보를 저장하고 관리하지 않는다는 뜻이다. 즉, 한번 요청을 보내고 응답을 받으면 요청-응답에 담겨있던 정보들은 클라이언트-서버에서 각각 처리하지 않는 이상 휘발된다.
- 이런 http 통신의 특성 때문에, '이 사람은 어드민 페이지에 접근해도 되는 사람입니다'라는 걸 클라이언트-서버가 함께 증명하는 것은 어려운 일이다. 인증/인가는 여러 방식을 통해 이 문제를 해결한다.
- 인증/인가 방식에는 크게 세션 방식과 토큰 방식이 있다. 클라이언트에서도 적절한 대응을 해야 하지만, 사실 둘 다 서버에서 어떻게 처리되는지가 사실 좀 더 중요한 것 같다.
- 토큰 방식에는 또 여러 가지가 있는 것 같은데, 최근엔 JWT 토큰이라는 게 가장 많이 사용되는 것 같다(관련해서 아직 더 공부해보진 못했다).
- 세션 방식은 서버에서 세션 DB를 별도로 두고, 유저가 로그인을 하면 로그인에 대한 세션 정보를 DB에서 별도로 관리하는 방식이다.
- 토큰 방식은 서버에서 '이 접근하는 클라이언트가 인증/인가받은 이력이 있습니다'라는 걸 서버에서 정보로 저장해두지 않고, 대신 첫 로그인 시 토큰을 발행한 다음, 그 토큰에 대한 암호화 규칙을 서버에 갖고 있는 방식으로 처리된다. 클라이언트는 서버에서 받은 토큰 정보를 저장하고 있다가, 권한 인증이 필요한 상황에서 토큰 정보를 서버로 보내면 서버는 사전에 정해둔 암호화 규칙으로 Decoding을 하여 그 사람의 권한 정보를 확인한다.
- 세션 방식은 로그인된 유저가 어떤 사람인지 특정할 수 있고, 필요할 경우 그 유저의 로그인을 푸는 등(세션 정보를 지워버리면 됨) 처리를 해줄 수 있다. 그래서, 좀 더 유저 인증/인가 권한을 타이트하게 관리해야 하는 곳에서 사용이 적합하다.
- 반면, 토큰 방식은 '이 토큰을 들고 온 클라이언트가 누구이다'라고 특정할 수 없다. 그래서, 특정한 사람을 Ban 하거나 강제 로그아웃 시키는 것이 불가능하다(우회하는 방법이 있는 것 같긴 함).
- 세션 방식은 유저 관리를 더 철저하게 할 수 있다는 장점은 있지만, 별도의 DB를 둬야 하기 때문에 서버 비용이 들고, 유저가 많아지면 서버 확보에 문제가 생길 수 있다는 단점이 있다.
- 토큰 방식은 '이게 어떤 클라이언트다'라는 건 특정할 수 없지만, DB를 별도로 두고 세션 정보를 저장할 필요가 없기 때문에 훨씬 간편하게 구현이 가능하다.
- 인증/인가는 유저의 개인 정보와 연결되는 경우가 많고, 따라서 보안에 특히 주의해야 함. 세션 정보와 토큰 정보 모두 다 통신하는 과정에서 악의적인 접근으로 해킹당할 수 있고, 예를 들어 금융 서비스 인증/인가 과정에서 해킹을 당하면 개인의 자산이 다 털릴 수도 있다. 보안에 있어 특히 신경 써서 관리해야 한다.
- 토큰 방식으로 인증/인가를 처리할 땐 Access Token과 Refresh Token이라는 걸 보통 함께 사용한다. Access Token은 실제 인증/인가에 필요한 정보가 담긴, 높은 보안 수준으로 관리돼야 하는 토큰이다. Refresh Token은 서버에 Access Token 재발급을 요청하기 위한 정보가 담긴 토큰이고, 인증/인가를 위한 필수 정보는 아니기 때문에 보안 수준이 Access Token보다는 낮다.
- 탈취될 시 위험도가 높은 Access Token은 보통 만료 기간을 짧게 설정하고(몇 시간 정도? 정책에 따라 다르다), 대신 Refresh Token의 만료 기간은 조금 더 길게 설정해서(며칠? 몇 주?), Access Token이 만료되면 클라이언트에서 Refresh Token 정보를 관리해 서버로부터 새로운 Access Token을 받아오도록 한다. 상대적으로 위험도가 높은 Access Token의 만료 주기를 더 짧게 가져가서(토큰 방식은 서버에서 임의 로그아웃 시키는 것도 불가능하기 때문에, 만료 주기가 중요하다) 해킹을 당했더라도 상대적으로 덜 위험할 수 있게 처리한다.
- 또한, 보안을 철저하게 지켜야 하는 Access Token은 외부에서 접근하는 것이 어렵게 Javascript 변수에 값을 넣어놓고 관리하는 것이 일반적이고, Refresh Token은 서버와 주고받을 수 있는 쿠키에 정보를 넣는 것이 일반적인 것 같다(반드시 그래야만 하는 건 아닌 것 같긴 하다).
- 프로젝트 내에서 로그인 후 Access Token을 받아왔다면, 해당 값을 프로젝트 전역에서 공유될 수 있게 해야 필요한 권한 인증 처리를 할 수 있기 때문에, 어디서 어떻게 Access Token을 관리할지를 잘 고민하는 게 중요하다.
- 변수에 저장한 Access Token은 페이지 새로고침 시마다 값이 날아갈 수 있기 때문에, 새로고침 시 서버로 Refresh Token을 다시 보내서 Access Token을 재발급받는 과정을 처리해 주는 것도 필요하다.
- 정리해 보면, 클라이언트에서 토큰 방식으로 로그인을 처리할 때 아래와 같은 내용들을 잘 관리해줘야 한다.
- 로그인 시 인가되면 발급되는 Access Token과 Refresh Token 정보를 적당한 곳에 저장하고, 필요할 경우 서버로 보내주기(보안 취약점이 적어지면서 동시에 사용이 편리하려면 어디서, 어떻게 관리해야 할지를 잘 고민해야 한다).
- 새로고침 또는 Access Token 유효 시간 만료 시 서버로 Refresh Token을 다시 보내서 Access Token을 새로 받기
- 인증/인가가 필요한 API 요청 시 토큰 정보를 헤더에 담아서 같이 보내주기
- 유저가 로그아웃을 하면 로컬에서 관리해 주던 토큰 정보 삭제시키기
- 각 단계를 실제 코드로 어떻게 구현해야 하는지는 주말 중에 좀 더 공부해 봐야겠다.
- 순수 함수,
useState
-useEffect
-클린업 함수
실행 순서 관련 내용 학습- 순수 함수와, 리액트 상태 관리-리렌더링 관련 훅에 대해 이런저런 자료를 많이 찾아보고 싶었는데, 그동안 우선순위에서 계속 밀렸었다.
- 오늘 인증/인가 공부 위해 이런 저런 자료들 찾아보면서, 생각난 김에 같이 공부를 좀 더 했다(여기에 좀 더 많은 시간을 쓴 것 같다).
- 각각에 대해 블로그에 포스팅까지 작성했다. 앞으론 이 맥락을 좀 더 잘 이해하고, '바람직한 코드'에 대해 좀 더 배경을 갖고 코드를 짜야겠다.
- 테오 스프린트 18기 참여
- 일주일 동안 진행되는 스프린트 경험에 중반부를 넘어섰다.
- 기획 아이디어를 어떻게 발산하고, 수렴하고, 기능으로 정리하고, 등등 MVP 제작까지의 일련의 과정을 경험해 보는 중이다.
- 어느 정도 기획이 잡혔고, 내일부터는 처음 개발에 들어간다.
- 현업에서 개발을 하고 계신 분들과 페어 프로그래밍을 하는데, 기대가 많이 된다. 내가 제일 못하겠지만, 자존감 잘 챙기고, 최선을 다해서 배워봐야겠다.
지쳐하지 말고, 계속 도전자의 마음가짐으로 최선을 다하자.
끝.
'TIL' 카테고리의 다른 글
241208 TIL (1) | 2024.12.09 |
---|---|
241207 TIL (2) | 2024.12.08 |
241205 TIL (0) | 2024.12.06 |
241204 TIL (1) | 2024.12.05 |
241203 TIL (0) | 2024.12.04 |