[Trouble Shooting] RefreshTokenService가 필요한 이유
·
Trouble Shooting
문제 상황오늘은 JWT 로그인 유지 흐름을 확장하면서 RefreshTokenService를 만들었다.처음에는 Refresh Token을 생성하는 것까지만 생각했는데, 막상 구현하려고 보니 한 가지가 더 필요했다.Refresh Token을 발급만 하면 끝나는 것이 아니라, 서버가 이 토큰을 저장하고 조회하고 삭제할 수 있어야 했다.그래서 RefreshTokenService를 따로 만들었다.RefreshTokenServiceRefreshTokenService는 Refresh Token을 Redis에 저장하고 관리하는 역할을 한다.로그인에 성공하면 서버는 Refresh Token을 생성하고, 이 값을 Redis에 저장한다.예를 들어 다음과 같은 형태이다.key: refresh:{loginId}value: re..
[Trouble Shooting] Access Token과 Refresh Token은 왜 나눠서 보관할까?
·
Trouble Shooting
문제 상황이번 프로젝트에서는, 로그인 유지 방식을 JWT 방식을 이용했다. JWT 방식으로 구현하던 와중 궁금한 점이 생겼다.Access Token과 Refresh Token을 왜 굳이 나눠서 관리하지?그냥 토큰 하나만 오래 쓰면 안 되나?처음에는 토큰을 두 개로 나누는 구조가 오히려 복잡해 보였다.하지만 각각의 역할을 나눠보니 이유가 조금씩 이해됐다. Access Token의 역할Access Token은 실제 API 요청에 사용하는 토큰이다. 예를 들어 로그인한 사용자가 내 정보를 조회할 때는 요청 헤더에 Access Token을 담아 보낸다.GET /api/user/meAuthorization: Bearer accessToken백엔드는 이 Access Token을 검증해서 사용자가 인증된 사용자인지 ..
[Trouble Shooting] JWT 필터에서 토큰이 없는데 바로 401을 던지지 않는 이유
·
Trouble Shooting
문제 상황JWT 인증 필터를 만들면서 이런 코드를 작성했고, 이 부분이 이상하게 느껴졌다.토큰이 없다는 건 인증되지 않은 요청이라는 뜻인데, 왜 바로 예외를 던지거나 401 Unauthorize 응답을 던지지 않고 다음 필터로 넘기는 걸까?JWT가 없으면 잘못된 요청이 아닐까, 바로 막아야 하는 게 아닐까?라는 생각을 했지만 Spring Security의 인증 흐름을 조금 더 보니 잘못된 생각이었음을 깨달았다.String authorization = request.getHeader("Authorization");if (authorization == null || !authorization.startsWith("Bearer ")) { filterChain.doFilter(request, respons..
[TownTalk] - 기술 스택 고민과 선택
·
Project
프로젝트 기술 스택 선정이번 프로젝트는 지역 기반 커뮤니티 서비스이며, 초기에는 REST API 기반 백엔드 서버를 구축하고 이후 모바일 앱 연동까지 고려하고 있다. 그래서 단순히 익숙한 기술을 고르기보다는, 확장성, 유지보수성, 앱 연동 가능성, 배포 편의성을 기준으로 기술 스택을 선택했다. Java 21이전 프로젝트에서는 Java 17을 사용했지만, 이번 프로젝트에서는 Java 21을 선택했다. Java 21도 Java 17과 마찬가지로 LTS 버전이기 때문에 장기적으로 안정적인 유지보수가 가능하다.vs Java 17Java 17과 비교했을 때 Java 21의 가장 큰 장점은 최신 기능들이 더 안정적으로 반영되었다는 점이다. 대표적으로 Virtual Thread가 정식 기능으로 포함되어, 많은 요청을..
[Trouble Shooting] Spring Security formLogin이 React JSON API와 맞지 않았던 이유
·
Trouble Shooting
로그인에서 formLogin 대신 AuthenticationManager를 사용한 이유TownTalk 프로젝트에서 로그인 기능을 구현하고 있던 와중 처음에는 Spring Security의 formLogin 설정을 사용하려고 했다. formLogin을 사용하면 Spring Security가 로그인 요청을 직접 처리해주기 때문이다.예를 들어 loginProcessignUrl을 지정하면 URL에 대한 컨트롤러를 따로 만들지 않아도 Security Filter가 요청을 가로채서 인증을 수행한다.처음에는 이 구조가 편해 보여서 formLogin을 사용하려고 했다.하지만 실제로 적용해보니 현재 프로젝트 구조와는 잘 맞지 않았다. 이 프로젝트는 React에서 JSON 형식으로 로그인 요청을 보내고, 백엔드는 그 요청..
[Migration] Spring Boot 마이그레이션 1단계 - 테스트 코드 작성
·
Migration
들어가며Spring MVC 프로젝트를 Spring Boot로 마이그레이션하면서 가장 먼저 고민한 것은 "마이그레이션 후 기존 기능이 정상적으로 동작하는지 어떻게 검증할 것인가"였다.기존 방식대로라면 마이그레이션 후 브라우저를 열고 하나하나 클릭하며 확인해야 했다. 로그인, 회원가입, 관리자 페이지, 마이페이지 등 모든 기능을 수동으로 검증하는 것은 시간이 오래 걸리고, 놓치는 부분이 생길 수밖에 없었다.특히 이번 마이그레이션은 단순히 프로젝트를 Spring Boot에서 실행되게 만드는 작업이 아니었다. 이후 Spring Security 도입, JPA 전환, Redis 세션 적용처럼 내부 구조를 계속 바꿔야 하는 작업 이었다.겉으로 보이는 화면과 기능은 그대로 유지되어야 하지만, 내부 구현은 계속 달라질 ..
[회고] 첫 팀 프로젝트를 마치며
·
Migration
첫 팀 프로젝트를 마치며첫 팀 프로젝트를 시작하기 전에는 내가 맡은 역할에 맞춰 충분히 공부했다고 생각했고, 어느 정도 자신감도 있었다. 실무에 가까운 구조와 간결한 코드를 목표로 삼고 프로젝트를 시작했다. 하지만 실제로 프로젝트를 진행해보니 생각처럼 쉽지 않았다. 처음 진행하는 팀 프로젝트였고, 기능 구현 자체가 막히는 순간도 많았다. 그럴 때마다 조급함이 앞섰고, 설계나 구조를 충분히 고민하기보다 일단 기능을 완성하는 데 집중하게 되었다. 그 결과 많은 로직이 컨트롤러에 몰리는 비효율적인 구조가 만들어졌다. 프로젝트를 완성한 뒤 다시 코드를 돌아보니, 내가 직접 작성한 코드임에도 흐름을 한눈에 파악하기 어려웠고 수정하기도 부담스러웠다. 팀 프로젝트였기 때문에 팀원의 코드를 이해하고 활용해야 하는 상황..
[개념 정리] 포트
·
개념 정리
포트(Port)컴퓨터 한 대에서는 지금도 브라우저, 카카오톡, Spring Boot 서버 등 수 많은 프로그램이 동시에 실행되고 있다. 그러면 외부에서 데이터가 들어올 때 운영체제는 이걸 어느 프로그램한테 전달해야 하는지 어떻게 알까?포트는 컴퓨터 안에서 실행 중인 각 프로그램에게 붙여주는 고유한 번호이다. 0 ~ 65535까지 존재하며, 외부에서 데이터가 들어오면 운영체제가 포트 번호를 보고 '8080으로 왔으니 Spring Boot에게 전달'이라고 판단을 한다.ex) IP 주소는 '서울시 강남구 xx아파트' 같은 건물 주소이고, 포트는 '110동 201호' 같은 호실 번호이다.✔️ 즉, 주소(IP)만 있으면 건물까지는 찾아가지만, 호실(포트)이 없으면 어디로 가야하는지 모른다.IP주소와 포트의 관계..