분산 처리 환경

스프링 분산 처리 환경 10: 중간 정리

ohji52 2025. 11. 23. 14:01

깃허브 주소

 

GitHub - 0hj1hyeon/distributed

Contribute to 0hj1hyeon/distributed development by creating an account on GitHub.

github.com

 

1. 로그인 환경 구현

 

스프링 분산 처리 환경 1: 로그인 구현

분산 처리 환경을 진행하기 전에 로그인 환경을 먼저 구현한다. controllerpackage com.example.distributed.controller;import com.example.distributed.dto.LoginRequest;import com.example.distributed.dto.LoginResponse;import com.example.di

ohji52.tistory.com

계층형 아키텍쳐:

 

  • Controller (LoginApiController): 사용자의 요청을 받아 적절한 서비스로 전달하고, 결과를 응답하는 역할
  • Service (UserService): 핵심 비즈니스 로직을 수행하는 역할
  • Repository (UserRepository): 데이터 저장소에 접근하는 역할

REST API

 

자원(Resource)을 이름으로 구분하고 상태를 주고받는 웹 아키텍처 스타일

 

 

2. JWT

 

스프링 분산 처리 환경 2: JWT

스프링 분산 환경을 만들기 전에 JWT를 도입해야한다JWT란 JSON Web Token으로 두 개체 사이에서 정보를 JSON 객체 형태로 안전하게 전송하기 위한 간결하고 자체 포합적인 방식이다. JWT는 무상태 인증

ohji52.tistory.com

 

JWT (JSON Web Token)

  •  당사자 간에 정보를 JSON 객체로 안전하게 전송하기 위한 컴팩트하고 독립적인 표준
  •  기존의 세션(Session) 방식 대신 사용된 인증 수단. 로그인 성공 시 서버가 발급해주며, 이후 클라이언트가 이 토큰을 가지고 서버에 요청을 보냄

JWT의 구조 (Structure)

  • JWT는 점(.)으로 구분된 세 부분으로 구성
    1. Header: 토큰의 타입(JWT)과 서명 알고리즘 정보
    2. Payload: 실제 전달할 데이터. 사용자 ID, 유효기간 등
    3. Signature: Header와 Payload가 변조되지 않았음을 검증하는 서명 데이터

무상태 인증 (Stateless Authentication)

  • 서버가 클라이언트의 상태(로그인 여부 등)를 서버 메모리나 DB에 저장하지 않는 방식
  • 분산 환경을 위한 핵심 전제 조건. 서버가 상태를 저장하지 않으므로, 트래픽이 늘어나 서버(인스턴스)를 여러 대 늘려도(Scale-out) 로그인 정보 공유 문제(세션 불일치)가 발생하지 않음

 

3. Spring Security

 

스프링 분산 처리 환경 3: Spring Security

Spring Security를 분산처리환경에서 사용하는 이유는 무상태 기반의 토큰 검증 및 인가를 효율적으로 처리하기 위해서이다. JWT를 발급하는 것은 쉽지만, 사용자가 다음 요청부터 헤더에 보낸 토큰

ohji52.tistory.com

 

Spring Security & Security Filter Chain

  •  Spring 기반 애플리케이션의 보안(인증/인가)을 담당하는 표준 프레임워크, 요청이 들어오면 여러 개의 필터들이 사슬처럼 연결되어 순차적으로 보안 검사를 수행
  • SecurityConfig 클래스에서 SecurityFilterChain을 정의하여, 어떤 요청을 허용하고 막을지 그리고 어떤 필터를 적용할지를 설정

세션 정책 (Session Management Policy - STATELESS)

  • 서버가 클라이언트의 세션을 생성하거나 유지하지 않도록 설정
  • SessionCreationPolicy.STATELESS 설정이 핵심, 이는 Spring Security가 더 이상 JSESSIONID 쿠키를 만들지 않고, 오직 들어오는 요청의 JWT 토큰만으로 매번 새롭게 인증을 처리하겠다는 선언

CSRF (Cross-Site Request Forgery) 비활성화

  • 사용자가 의도치 않게 공격자가 만든 위조 요청을 서버로 보내게 만드는 공격, 보통 브라우저의 쿠키/세션 기반 인증에서 발생
  • 이 프로젝트는 세션을 사용하지 않고 JWT(Header)를 사용하기 때문에 CSRF 공격에 안전, 따라서 불필요한 연산을 줄이고 REST API 설정을 위해 csrf.disable() 처리

OncePerRequestFilter

  • 서블릿 필터의 한 종류로, 하나의 요청에 대해 단 한 번만 실행됨을 보장하는 필터

SecurityContextHolder & Authentication

  • SecurityContextHolder: 현재 요청을 보내는 사용자의 보안 정보를 담고 있는 저장소
  • Authentication: 현재 접근한 주체(User)의 정보와 권한을 담은 객체

 

4. BCryptPasswordEncoder

 

스프링 분산 처리 환경 4: BCryptPasswordEncoder

BCryptPasswordEncoder란?BCryptPasswordEncoder는 비밀번호를 일방향으로 암호화하여 저장하는 해시 함수를 구현한다.일방향 해시는 문자열을 입력하면 정해진 길이의 암호화된 문자열이 출력된다. 이 해

ohji52.tistory.com

 

패스워드 인코딩 (Password Encoding)

  • 사용자의 비밀번호를 있는 그대로(Plain Text) DB에 저장하지 않고 알아볼 수 없는 문자열로 변환하는 과정
  •  SecurityConfig에서 PasswordEncoder를 Bean으로 등록하여, 애플리케이션 전역에서 비밀번호 변환 기능을 사용할 수 있게 설정

단방향 해시 함수 (One-way Hash Function)

  • 입력값(비밀번호)을 암호화된 출력값(해시값)으로 바꿀 수는 있지만, 반대로 해시값을 다시 원본 비밀번호로 복구하는 것은 수학적으로 불가능한 함수

솔트 (Salt)

  • 해시 함수를 돌리기 전에 원본 비밀번호에 무작위 데이터(Salt)를 덧붙이는 기법

키 스트레칭 (Key Stretching) & 워크 팩터 (Work Factor)

  • 해시 함수를 일부러 수천 번 반복 실행하여 계산 속도를 느리게 만드는 기법

matches() 메소드

  • 인코딩된 비밀번호는 매번 값이 달라지므로(Salt 때문에), 단순 문자열 비교(equals)로는 일치 여부를 알 수 없습니다. 내부적으로 원본 암호와 저장된 해시의 Salt를 이용해 연산한 뒤 일치하는지 확인해 주는 메소드

 

5. DB

 

스프링 분산 처리 환경 5: DB 연동

분산환경에서의 데이터베이스 연동DB연동은 서비스 독립성과 확장성을 확보하는 데에 필수적이다.데이터 독립성을 확보하여 DB변경이 다른 서비스에 영향이 주지 않도록 해 안정성을 높인다.메

ohji52.tistory.com

 

JPA 

  • ORM : 객체 지향 언어(Java)와 관계형 데이터베이스(SQL)의 패러다임 불일치를 해결하여, 객체와 테이블을 자동으로 매핑
  • JPA: 자바 진영의 ORM 기술 표준 명세
  • 본문 내 역할: 개발자가 복잡한 SQL 쿼리(INSERT INTO..., SELECT...)를 직접 짜지 않고, Java 클래스(User)를 다루듯 DB 조작 가능

Spring Data JPA (JpaRepository)

  • JPA를 더 쉽게 사용할 수 있도록 스프링이 감싸서 제공하는 모듈입니다. 리포지토리 패턴을 추상화하여 제공

 

6. Spring Cloud Gateway

 

스프링 분산 처리 환경 6: Spring Cloud Gateway

Spring Cloud GatewaySpring Cloud Gateway는 MSA에서 클라이언트 요청의 단일 진입점 역할을 수행클라이언트의 요청을 받아 라우팅 규칙에 따라 적절한 서비스로 요청을 전달하고 응답을 다시 클라이언트

ohji52.tistory.com

 

API 게이트웨이 (API Gateway)

  • MSA 환경에서 클라이언트와 백엔드 서비스 사이 위치하는 단일 진입점
  • 클라이언트는 내부의 수많은 서비스 주소를 알 필요 없이, 게이트웨이으로만 요청을 보냄, 게이트웨이가 이를 적절한 서비스로 라우팅

Spring WebFlux & Netty

  • 기존의 Spring MVC(Blocking I/O)와 달리, 비동기-논블로킹(Asynchronous Non-blocking) 방식을 사용하는 리액티브 웹 프레임워크
  • Spring Cloud Gateway는 높은 트래픽을 효율적으로 처리하기 위해 기본적으로 WebFlux 기반으로 동작

ServerWebExchange & Reactor (Mono/Flux) 

  • ServerWebExchange: HTTP 요청과 응답을 담고 있는 컨테이너 
  • Mono: 0 또는 1개의 데이터를 비동기적으로 발행하는 리액티브 타입

 

7. Spring Cloud Gateway 환경에서 JWT 인증

 

스프링 분산 처리 환경 7: Spring Cloud Gateway 환경에서 JWT 인증

1. 핵심 목표: WebFlux 환경에 맞는 인증 파이프라인 구축 AuthIntegrationTests package com.example.distributed;import com.example.distributed.domain.User;import com.example.distributed.dto.LoginRequest;import com.example.distributed.reposito

ohji52.tistory.com

WebTestClient

  • Spring WebFlux 환경에서 HTTP 요청을 테스트하기 위한 비동기, 논블로킹 웹 클라이언트
  •  WebTestClient를 사용하여 비동기적으로 /login 엔드포인트를 호출하고, 응답값(Status, Body)을 검증하는 통합 테스트 도구

블로킹 로직의 래핑 (Wrapping Blocking Calls)

  • UserService는 여전히 JPA(블로킹 기술)를 사용하고 있어 WebFlux 컨트롤러에서 이를 그냥 호출하면 스레드가 중단됨. 따라서 fromCallable을 사용해 동기 코드를 리액티브 흐름 안으로 삽입

스케줄러 (Schedulers.boundedElastic)

  • 리액티브 프로그래밍에서 작업이 실행될 스레드 풀(Thread Pool)을 지정
  • WebFlux의 기본 스레드(Event Loop)는 블로킹 작업(DB 조회 등)을 하면 전체 서버가 멈춰 별도의 전용 스레드 풀에서 실행해 게이트웨이 성능 저하를 막음

리액티브 에러 처리 (onErrorResume)

  • 스트림 처리 도중 에러가 발생했을 때, 흐름을 끊지 않고 대체 동작(Fallback)을 수행하는 연산자
  • 기존의 try-catch 문 대신 사용, 로그인 실패 예외(RuntimeException)가 발생하면 이를 잡아서 401 Unauthorized 응답으로 변환하여 반환

테스트 설정 (@TestConfiguration)

  • 테스트 실행 시에만 적용되는 추가적인 Bean 설정
  • 테스트를 위해 매번 실제 회원가입을 할 수 없으므로, 테스트 시작 전에 미리 userRepository에 테스트용 유저("valid_user")를 저장해두는 데이터 셋업(Fixture Setup) 역할을 수행

 

8. Spring Cloud Gateway 환경에서 JWT 인가 필터 및 라우팅 검증 테스트

 

스프링 분산 처리 환경 8: Spring Cloud Gateway, JWT 인가 필터 및 경로별 라우팅 검증 테스트

package com.example.distributed;import com.example.distributed.domain.User;import com.example.distributed.repository.UserRepository;import com.example.distributed.util.JwtTokenProvider;import org.junit.jupiter.api.BeforeAll;import org.junit.jupiter.api.Dis

ohji52.tistory.com

 

헤더 전파 (Header Propagation) & 요청 변조 (Mutation)

  • 게이트웨이가 클라이언트의 요청을 받아, 뒷단의 마이크로서비스에게 필요한 정보를 헤더에 심어서(Inject) 넘겨주는 기술

라우팅 검증을 위한 상태 코드 활용 (Status Code Inference)

  • 개념: 실제 연결 대상(Target Service)이 없는 상태에서, 라우팅 규칙이 맞는지 추론하는 기법

JUnit 5 생명주기 (@TestInstance)

  • 테스트 클래스의 인스턴스 생성 주기를 설정
  • @TestInstance(Lifecycle.PER_CLASS)를 사용하여 @BeforeAll 메소드를 static이 아닌 일반 메소드로 정의, 이를 통해 jwtTokenProvider 같은 의존성을 주입받아 테스트 시작 전에 토큰을 미리 생성(setupTokens)함

 

9. Resilience4j 서킷 브레이커

 

스프링 분산 처리 환경 9: Resilience4j 서킷 브레이커 적용

서킷 브레이커(Circuit Breaker) 마이크로서비스 아키텍처(MSA)에서 특정 서비스에 장애가 발생했을 때 아무런 조치가 없다면 게이트웨이는 계속 요청을 보내고, 스레드는 대기하다 고갈되며 시스템

ohji52.tistory.com

 

서킷 브레이커 패턴 (Circuit Breaker Pattern)

  •  특정 서비스에 장애가 발생하면 연결을 즉시 차단하여 더 큰 사고를 막는 디자인 패턴
  • 게이트웨이가 응답 없는 서비스(Backend)를 계속 호출하다가, 게이트웨이 자신의 스레드까지 모두 소진되어 시스템 전체가 멈추는 현상(Cascading Failure, 연쇄 장애)을 방지

Resilience4j

  • Netflix Hystrix가 지원 중단(EOL)된 이후, Spring Cloud 진영에서 표준으로 채택한 경량화된 결함 감내(Fault Tolerance) 라이브러리
  •  spring-cloud-starter-circuitbreaker-reactor-resilience4j 의존성을 통해, WebFlux(Reactor) 환경에 맞는 비동기 서킷 브레이커를 구현

슬라이딩 윈도우 (Sliding Window)

  • 전체 데이터를 다 보는 것이 아니라, 최근 N개의 데이터만 창문(Window)을 통해 보듯 잘라서 통계를 내는 기법

실패율 임계치 (Failure Rate Threshold)

  • 어느 정도 망가져야 회로를 끊을 것인가에 대한 기준점

서킷의 상태 (State: Open vs Closed)

  • Closed: 정상 상태(요청 허용)
  • Open: 장애 상태(요청 차단 및 바로 에러 반환)
  • Half-Open: 테스트 상태, 일정 시간 후 살짝 연결해 보고 성공하면 Closed, 실패하면 다시 Open

타임 리미터 (Time Limiter)

  • 개념: 응답이 오기를 무한정 기다리는 것이 아니라, 정해진 시간이 지나면 시간 초과(Timeout)로 간주하고 실패 처리
  • 본문 내 역할: timeoutDuration(Duration.ofSeconds(4)) 설정입니다. 서비스가 아예 죽은 게 아니라 느려진 경우(Latency)에도 장애로 판단, 4초 안에 답이 안 오면 실패로 카운트

7폴백 (Fallback)

  • 주(Main) 로직이 실패했을 때 실행되는 대체 경로(Plan B)
  • 사용자에게 500 Internal Server Error나 멈춰있는 화면을 보여주는 대신, FallbackController로 리다이렉트하여 안내 메시지를 JSON으로 반환