MSA에서 인증을 처리하는 방식은 크게 완전 재검증 방식과 신뢰 기반 방식으로 나뉜다. 이번 학습에서는 성능과 관리 효율성을 위해 신뢰 기반 방식을 채택하여 구현했다.
장점 : 코드 중복 감소, 성능 향상, 일관된 보안 모델 유지.
기존 Monolithic 또는 개별 인증 방식에서 Gateway 중심 인증으로 변경하며 다음과 같은 코드 수정이 이루어졌다.
API Gateway : JWT 유효성 검증 및 정보 추출(Parsing) 후 Request Header에 추가.
User Service (Spring Security)
삭제: JwtAuthenticationFilter, CustomUserDetailsService (더 이상 DB 조회 불필요).
추가: HeaderAuthenticationFilter (헤더 값을 읽어 PreAuthenticatedAuthenticationToken 생성).
Controller : @AuthenticationPrincipal을 사용해 userId를 바로 주입받도록 변경.
Eureka Client : 서비스 기동 시 Eureka Server에 등록되어 Gateway가 로드밸런싱 할 수 있도록 설정.
Client: JWT를 담아 Gateway로 요청.
Gateway: 토큰 검증 후 X-User-Id 헤더 추가하여 라우팅.
Service: 헤더 정보를 바탕으로 인증 처리 후 비즈니스 로직 수행.
Discovery Client: 직접 인스턴스 리스트를 조회하여 호출. (URL 생성 등 개발자 책임이 큼)
RestTemplate (@LoadBalanced): URL을 추상화하여 호출하지만, 여전히 코드가 길어질 수 있음.
Feign Client (@FeignClient) : 인터페이스 선언만으로 구현 가능
Spring MVC 어노테이션(@RequestMapping)을 그대로 사용 가능하여 가독성과 생산성이 높음.
예시) Order Service에서 User Service의 등급 조회 API를 마치 로컬 메서드처럼 호출.
REST API 설계: 표준화된 인터페이스(Swagger 활용), 자원 중심 설계, 버전 관리.
Gateway 설정: 보안, 로드 밸런싱, 인증/인가 집중 처리, 요청 라우팅.
구성 외부화: 환경별 설정 분리 및 중앙 관리.
모니터링: 데이터 수집(Prometheus), 시각화(Grafana), 경고 시스템.
내결함성 (Resilience): 장애 전파 방지(Circuit Breaker), 대체 로직(Fallback).
로깅 및 분산 추적: 중앙 집중식 로그 관리, Zipkin 등을 통한 트랜잭션 추적.
CI/CD: 자동화 파이프라인 및 테스트 검증.
이번주는 프로젝트 기간이라 배운것은 크게 없고 msa 배운 내용을 더 심화적으로 배웠다!
이론을 제대로 이해하기 전에 프로젝트에서 실제로 써보고 느꼈지만 아직 이론적으로는 많이 부족한 것 같아서 추가적으로 시간을 갖고 공부해야겠다!
데이터의 흐름(Controller -> Service -> Repository -> DB)을 스스로 밑바닥부터 구현해보기 위해 시작한 사이드 프로젝트였다. 거창한 기능보다는 ai 의존도를 줄이면서 모르는건 구글링하고 최대한 생각해보고 코드를 직접 작성해보고 싶어서 시작했다.
프로젝트명: TodayMemo (나만의 할 일 메모장)
소요 시간: 약 3시간
기술 스택: Spring Boot 3.x, Java 17, JPA(Spring Data JPA), MariaDB, Thymeleaf
Entity 설계 : 디테일의 중요성
처음엔 막연하게 int completed 같은 필드를 생각했지만, JPA Entity로 구현하면서 명확한 타입(Boolean, LocalDateTime)의 중요성을 배웠다. 특히 memoTitle처럼 중복된 접두사를 제거하고 title로 깔끔하게 리팩토링하는 과정을 통해 Clean Code에 대해 고민해볼 수 있었다.
Service Layer 구현 : 비즈니스 로직의 분리
컨트롤러에 모든 로직을 때려 넣는 게 아니라, Service 계층을 따로 두어 역할을 분리했다. 가장 기억에 남은건 Update(수정) 기능이었다.
@Transactional
public TodoEntity updateTodo(...) {
TodoEntity todo = repository.findById(id).orElseThrow(...);
todo.setTitle(newTitle);
// repository.save(todo) 호출 안 함!
}
Dirty Checking을 이론적으로는 나름 잘 알고있다고 생각했고 수업시간에 강사님과 같이 코드도 써보면서 혼자 사이드 프로젝트를 하면서 쉽게쉽게 할 수 있을거라고 생각했는데 제일 오래 막히고 생각해본 부분이였다.
문제 : Port 8080 was already in use
원인 분석: 아까 실행하다가 에러 나서 멈춘 줄 알았던 서버가, 실은 백그라운드에서 계속 실행중이였다. 에러코드를 분명히 읽었고, 어떻게 해결하는지도 잘 아는데 왜 그렇게 고민하고 당황했는지 모르겠다 ㅠ
해결 : 포트번호를 8081로 변경하여 시작하니 손쉽게 해결했다...!
이번 프로젝트때 ai에게 의존을 너무 많이해서 ai의존도를 줄이고자 시작한 프로젝트였다.
주제가 어렵지 않아도 강사님과 ai 도움 없이 db 생성부터 직접 혼자 하는 과정이 쉽지 않을줄은 알았는데 생각보다 많이 어려웠다.
이미 다 아는 개념이였지만 직접 하나하나 생각하면서 쓰는건 또 다른 영역이라는 생각이 들었고, 1~2주에 한번씩은 주제 바꿔가면서 해보고 싶다! 오늘도 결국 ai를 사용하긴 했지만 그래도 내가 직접 고민하고 작성한게 훨씬 많았어서 그런가 엄청 뿌듯했다!!!
이번주는 수업시간에 배운 개념보단 프로젝트를 복기하고 사이드 프로젝트도 해보면서 주말을 보냈는데 생각보다 더 의미있는 주말이였던것 같아서 뿌듯하다!
그동안 열심히만 한 것 같고 스스로 잘했다고 느낄만한 부분이 없어서 많이 속상했는지만 (조금 울었움🥲) 아직까진 초심을 잃지 않고 열심히 노력하니까 수료하기 전엔 스스로 내가 잘해졌다고 느껴질 수 있도록 더 노력해야겠다!
그리구 백엔드 지필평가 생각보다 높은 점수가 나와서 뿌듯했다 우하하하하하!😆😆