기존 아키텍쳐에서 스프링 부분, 리버스 프록시를 담당하는 부분을 구현했다.
텀이 좀 길었는데, 퇴사 과정이 생각보다 복잡해서 시간을 너무 많이 잡아먹혔다...

우선 내 스프링 프로젝트의 시퀀스 다이어그램은 위와 같다.
다 짜고나서 GPT에게 부탁했다.
원래는 그냥 OAuth2나 폼 형식으로 세션에 접근하는 JWT, 둘 중 하나만 쓰려고 했는데
OAuth2 사용했을때의 세션관리를 쿠키로 하기에는 모바일 대응이 안되서 JWT를 섞어가지고 세션관리를 하기로 했다.
이후에 Reverse Proxy 구성하고 LLM+RAG 쪽 작업이 마무리 되면 이제 로그아웃같은 기능들을 Redis를 도입하여 추가할 예정이다.
파이썬만 하던 사람에게 솔직히 쉽지 않았다.
그나마 스프링 빼고는 알고있던 내용들이라 구조, 틀 잡는것은 오래 걸리지 않았다.
디렉토리 구조도 몇번씩 갈아엎고 잘 분리했다고 생각했는데 의존성 꼬이고..
가장 고통받았던건 아무래도 JPA가 아니었나 싶다.
Repository 레이어에 인터페이스 만들고 안에 쿼리 대신해주실 메소드님 만들어드려야 하고
Entity는 또 신중하게 안하면 DB 테이블 스키마가 이상해져버리고
막상 또 필드명이 어긋나면 당연하게도 안되더라....
그런데 이제 무서운건 런타임을 돌리지 않으면 알수가 없었다.
분명 IDE상에서는 괜찮았는데 런타임 돌리자마자 JVM이 화를 잔뜩내더라.
그리고 좀 멍청하게도
처음 연습용으로 만든 JWT + form 형식으로 로그인 하던 부분의 Entity를 OAuth2로 로그인하는 부분이 의도치않게
잔뜩 의존해버려서 디렉토리 구조 갈고, 클래스 파일 다듬고, 컨트롤러에서 제대로 분기처리 진행했다...
더불어 JWT 세션을 유지할때 사용하기 위해 만든 테이블에 더해
사용자 정보 자체를 저장하는 테이블을 만들어서 나중에 LLM+RAG 사용시 머 질문 내용이라던가 마이페이지라던가 그런 기능으로 확장이 가능하게 만들었다.
디렉토리 구조, 클래스 리팩토링 하면서 JWT를 username 베이스가 아니라 userid 베이스로 만들었다.
가볍게 그냥 loaduserbyusername 해가지고 하면 될줄 알았는데 DB의 PK를 박아버려서 타입이 Long이었다.
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
AppUser user = appUserRepository.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("사용자 없음"));
return new AppUserDetails(user);
}
처음에는 진짜 가볍게 이렇게 오버라이드 해가지고 했었다. 그런데 Exception 엄청 내면서
제 발 타입 좀 맞 춰 주세요 !!!!!!!!!!! 하고 JVM이 울부짖길래
public AppUserDetails loadUserById(Long id) {
AppUser user = appUserRepository.findById(id)
.orElseThrow(() -> new UsernameNotFoundException("사용자 없음"));
return new AppUserDetails(user);
}
이렇게 커스텀 해서 진행했다.
try {
String token = resolveToken(request);
if (token != null && jwtProvider.validateToken(token)) {
Long userId = jwtProvider.getUserId(token);
UserDetails userDetails = appUserDetailsService.loadUserById(userId);
UsernamePasswordAuthenticationToken auth =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities()
);
SecurityContextHolder.getContext().setAuthentication(auth);
}
실제 사용 부분
UserDetails userDetails = appUserDetailsService. ~ 을 교체해주니까 정상 작동 하였다.
오버라이드 한걸 쓰니까 어쩔수없이 파라미터에 String을 박아야 하는데 JWT를 써서 세션까지 관리하려면 임의로 만든 String이든, 진짜 username, email보다는 DB Key를 쓰는게 user 정보를 나중에 추가할 LLM + RAG 세션, 정보들까지 관리하려면 더 낫다고 생각했다.
이런 문제들 말고도 기초적인 DTO 관리라던가... 하여튼 쉽지 않았다.
그래도 인증이라는, 그것도 스프링으로 인증하는 미들웨어 만드는 큰 산을 드디어 넘었다.
JPA나 Spring Security는 주기적으로 딥다이브 할 필요가 있어 보인다.
파면 팔수록 뭐가 자꾸 나온다...
다음은 여기에 깔끔하게 리버스프록시 붙이고 핵심 부분인 FastAPI 기반 LLM+RAG 작업을 해야겠다.
'개인 프로젝트' 카테고리의 다른 글
| LLM + RAG 프로젝트 [3.1] 프론트 - 미들웨어 인증 로직 수정 (2) | 2025.08.19 |
|---|---|
| LLM + RAG 프로젝트 [4] 데이터 수집 (0) | 2025.08.08 |
| LLM + RAG 프로젝트 [2] 아키텍쳐 설계 (0) | 2025.06.23 |
| LLM + RAG 프로젝트 [1] (1) | 2025.06.18 |
| LLM + RAG 프로젝트 시작 [0] (0) | 2025.06.15 |