개발을 하면서 Spring Security 7 변경후 느낀점

궁금하면 500원·2025년 12월 17일

미생의 스프링

목록 보기
47/48

[Spring Security 7] Spring Boot 4.0 시대의 보안

Spring Framework가 7.0으로, Spring Boot가 4.0으로 메이저 업데이트되면서 Spring Security 또한 7.0 버전으로 진화했습니다.

이번 업데이트는 단순한 버전 올림이 아니라, 보안 설정의 모듈화, 최신 표준 준수, 그리고 개발자 경험 개선에 초점을 맞추고 있습니다.

이번 포스팅에서는 실무 개발자 관점에서 Spring Security 7.0의 핵심 변경 사항과 마이그레이션 포인트를 상세히 정리해 보았습니다.


1. Spring Boot 4.0 Base 기반 환경의 변화

Security 7을 이해하기 위해서는 먼저 기반이 되는 Spring Framework 7.0의 변화를 알아야 합니다.

  • Java 버전: 최소 JDK 17을 지원하지만, JDK 25 LTS 사용을 강력히 권장합니다.
    JDK 25의 객체 헤더 압축 기술 등을 통해 별도 코드 수정 없이 약 10~15%의 성능 향상과 메모리 절감 효과를 얻을 수 있습니다.
  • JSON 라이브러리: Jackson 2.x에서 Jackson 3.x로 강제 전환되는데
    패키지명이 변경되므로 JSON 직렬화/역직렬화 커스텀 설정이 있다면 점검이 필요 하다고합니다.
  • HTTP Client: RestTemplate은 더 이상 기능 개발이 이루어지지 않으며, RestClient 또는 WebClient로의 전환이 필수적입니다.
    OAuth2 통신 구현 시 주의가 필요합니다.

2. 설정의 패러다임 변화

가장 피부로 와닿는 변화는 보안 설정을 작성하는 방식입니다. 가독성과 타입 안전성을 위해 람다(Lambda) 스타일이 강제되며, 설정을 분리할 수 있는 기능이 추가되었습니다.

2.1. .and()의 종말과 람다 체이닝 강제

기존의 .and() 메서드를 통한 체이닝 방식은 완전히 제거되었습니다.
모든 설정은 독립적인 람다 블록 안에서 이루어져야 합니다.

Security 6.x 이전 스타일 사용 불가하게 되다

// 더 이상 작동하지 않음
http.csrf().disable()
    .and()
    .authorizeRequests()
    .anyRequest().authenticated();

Security 7.0 스타일

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .csrf(csrf -> csrf.disable())
        .authorizeHttpRequests(auth -> auth
            .anyRequest().authenticated()
        )
        .formLogin(Customizer.withDefaults()); // 기본값 사용 시

    return http.build();
}

2.2. 설정의 모듈화

Security 7에서는 거대한 SecurityFilterChain 빈 하나에 모든 설정을 때려 넣는 대신, 기능별로 설정을 쪼개어 빈으로 등록할 수 있는 Customizer<HttpSecurity> 방식을 공식 지원합니다.

@Configuration
public class SecurityConfig {

    // 메인 필터 체인에서는 모듈화된 설정들이 자동으로 취합됨
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        // 별도 설정 없이 http.build()만 해도 등록된 Customizer들이 적용됨
        return http.build();
    }

    // CSRF 설정 분리
    @Bean
    Customizer<HttpSecurity> csrfCustomizer() {
        return http -> http.csrf(csrf -> csrf.disable());
    }

    // 로그인 설정 분리
    @Bean
    Customizer<HttpSecurity> formLoginCustomizer() {
        return http -> http.formLogin(login -> login.loginPage("/login"));
    }
}

이 방식은 팀 단위로 보안 설정을 나누어 관리하거나, 복잡한 설정을 기능별로 파일로 분리할 때 매우 유용합니다.


3. 인가 API의 완전한 대체

3.1. authorizeHttpRequests 표준화

오랫동안 사용되던 authorizeRequests()antMatchers()가 완전히 제거되었습니다.

  • 변경 전: authorizeRequests(), antMatchers()
  • 변경 후: authorizeHttpRequests(), requestMatchers()

3.2. 복합 권한 조건

기존 hasAnyRole은 OR 조건이었습니다.
여러 권한을 모두 가지고 있어야 접근 가능한 AND 조건을 위한 매니저가 추가되었습니다.

  • AllAuthoritiesAuthorizationManager: 명시된 모든 권한을 가져야 통과.
  • API: .hasAllRoles(...), .hasAllAuthorities(...)

3.3. AuthorizationManager 인터페이스 변경

커스텀 인가 로직을 작성할 때 사용하던 check() 메서드가 제거되고, authorize() 메서드로 통일되었습니다.
authorize()는 단순 boolean 결과뿐만 아니라 인가 결정의 맥락과 이유를 포함하여 리턴하므로 디버깅과 감사에 유리합니다.


4. 최신 보안 트렌드 반영

4.1. Multi-Factor Authentication 워크플로우 지원

이전 버전에서는 2차 인증를 구현하려면 필터 체인을 복잡하게 커스텀해야 했습니다.
Security 7은 1차 인증 성공 → MFA 필요 → 2차 인증 페이지 이동 → 최종 인증으로 이어지는 흐름을 프레임워크 차원에서 지원합니다.

Note: Spring Security는 '흐름'을 제어해 줄 뿐, 실제 SMS 발송이나 OTP 생성 로직은 개발자가 구현해야 합니다.

4.2. Single Page App 의 CSRF 지원

React, Vue.js 등 SPA 환경에서는 HTML Form을 쓰지 않아 CSRF 토큰 처리가 까다로웠습니다. 이를 위해 SPA 전용 핸들러가 추가되었습니다.

http.csrf(csrf -> csrf.spa());

이 설정을 사용하면, CSRF 토큰을 쿠키나 헤더를 통해 SPA 클라이언트가 쉽게 다룰 수 있도록 자동으로 구성해 줍니다.

4.3. 암호화 강화

Password4j 기반의 암호화가 통합되어 더 강력한 해싱 알고리즘을 지원합니다.

  • 지원: Argon2, BCrypt, SCrypt, PBKDF2, Balloon Hashing
  • 기존처럼 {id}encodedPassword 형태의 저장 방식을 유지하되, 내부 엔진이 업그레이드되었습니다.

5. OAuth 2.0 및 연동성 강화

  • Authorization Server 통합: 별도 프로젝트였던 Spring Authorization Server가 Spring Security 코어에 통합되었습니다. 이제 별도 의존성 관리 없이 통합 구축이 가능합니다.
  • PKCE 기본 활성화: 보안성이 높은 Proof Key for Code Exchange 방식이 Authorization Server의 기본값으로 설정됩니다.
  • Password Grant 제거: 보안 취약점으로 지적되던 리소스 오너 패스워드 자격증명이 완전히 제거되었습니다.
  • OAuth2 Client API: HTTP 요청이 빈번한 OAuth2 흐름을 위해 내부적으로 RestClient 기반의 설계를 강화했습니다.

6. 마이그레이션 요약 체크리스트

  1. JDK 업그레이드: 프로젝트 JDK를 17 이상 ~ 권장 25 으로 설정했는가?
  2. 설정 리팩토링: SecurityConfig의 모든 .and()를 제거하고 람다 DSL로 변환했는가?
  3. API 교체: authorizeRequestsauthorizeHttpRequests, antMatchersrequestMatchers로 변경했는가?
  4. JSON 라이브러리: Jackson 3.x 호환성을 확인했는가?
  5. 커스텀 인가: AuthorizationManager 구현체에서 check() 대신 authorize()를 사용하도록 수정했는가?
  6. OAuth2 점검: Password Grant 방식을 사용하는 레거시 클라이언트가 없는지 확인했는가?

마치며

Spring Security 7.0은 초기 설정 문법이 바뀌어 낯설 수 있지만, 결과적으로 더 안전하고, 읽기 쉽고, 유지보수하기 좋은 코드를 작성하도록 유도합니다.
특히 MFA 워크플로우설정 모듈화는 복잡한 엔터프라이즈 애플리케이션 보안을 구축하는 데 큰 도움이 될 것입니다.

새로운 프로젝트를 시작한다면 주저 없이 Spring Boot 4 & Security 7 조합을 선택하시고, 기존 프로젝트는 위 체크리스트를 바탕으로 점진적인 전환을 준비하시기 바랍니다.


출처: 스프링 프레임워크 7 대비 영상: 스프링 프레임워크 7 대비 (스프링 부트 4)

profile
에러가 나도 괜찮아 — 그건 내가 배우고 있다는 증거야.

0개의 댓글