Spring 7기 프로젝트/일정관리 프로젝트

Spring Security와 쿠키+세션 기반 로그인 인증, 인가 간결 구현

JuNo_12 2025. 5. 23. 21:19

 프로젝트를 진행 중, Spring Security라는 개념을 알게 되었고

이를 잘만 활용하면 이전에 구현했던 로그인필터 및 여러 클래스들을 과감히 삭제하고,

Security Config + 인증/인가 예외처리 클래스 이 2개만으로 간단하게 인증 / 인가 시스템을 구현할 수 있을거같다는 생각이 들어서 공부해보고 적용해보기로 했습니다.

 

 하지만, 기존의 것들을 다 삭제하고 새로 만들고 컨트롤러와 서비스 레이어에서의 로직들을 다 수정을 해주는 작업이 생각보다 쉽지 않았습니다. 하지만 노력끝에 완성하고 보니 정말 하길 잘했다고 생각이 듭니다. 코드의 간결함이 차원이 달라졌습니다!

쓰기 쉬운 코드보다는 읽기 쉬운 코드가 좋다고 생각하는데 이에 맞게 수정을 잘 한 것 같습니다.

 

1. 왜 Spring Security인가?

웹 애플리케이션의 인증과 인가는 보안상 가장 중요한 영역입니다. 직접 세션, 쿠키, 사용자 관리 로직을 구현하기 쉽지 않고, 보안 취약점 발생 가능성도 높습니다. Spring Security는 검증된 보안 프레임워크로서, 복잡한 인증, 인가 절차를 자동화하고, 보안 취약점을 줄여 줍니다.

 

2. 프로젝트 요구사항과 구현 방향

  • 쿠키 + 세션 기반 인증
    사용자가 로그인하면 서버에서 세션을 생성하고, 클라이언트에 세션 ID가 담긴 쿠키를 전달하여 이후 요청 시 자동 인증 유지
  • 커스텀 로그인 API
    REST API 기반 로그인 요청 처리, JSON 응답 제공
  • 사용자 정보를 DB에서 조회하여 인증
    UserDetailsService 인터페이스 구현체를 만들어 인증 사용자 정보 제공
  • 비밀번호 암호화
    BCryptPasswordEncoder 사용

3. 핵심 코드 구성 소개

3-1. UserDetailsService 구현체

@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
    private final UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        User user = userRepository.findByEmailAddress(email)
            .orElseThrow(() -> new UsernameNotFoundException("사용자 없음: " + email));
        return new UserDetailsImpl(user);
    }
}
  • DB에서 유저 조회, Spring Security 인증을 위해 UserDetails 반환

3-2. AuthenticationManager와 로그인 서비스

@Service
@RequiredArgsConstructor
public class AuthService {
    private final AuthenticationManager authenticationManager;
    private final UserService userService;

    public LoginResponseDto login(LoginRequestDto loginRequestDto, HttpServletRequest request) {
        Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(loginRequestDto.getEmailAddress(), loginRequestDto.getPassword()));

        SecurityContext context = SecurityContextHolder.getContext();
        context.setAuthentication(authentication);

        HttpSession session = request.getSession(true);
        session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context);

        User user = userService.findByEmailAddressOrThrow(loginRequestDto.getEmailAddress());

        return new LoginResponseDto(user.getUserName(), "로그인 성공");
    }
}
  • AuthenticationManager를 활용해 인증 처리
  • 인증 정보를 SecurityContext에 저장하고 세션에 바인딩하여 쿠키+세션 인증 완성

3-3. SecurityConfig 설정

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
    private final UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
        authBuilder.userDetailsService(userDetailsService)
                   .passwordEncoder(passwordEncoder());
        return authBuilder.build();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/login", "/api/users/signup").permitAll()
                .anyRequest().authenticated())
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED));
        return http.build();
    }
}
  • AuthenticationManager 빈에서 UserDetailsService와 PasswordEncoder를 등록해 Spring Security 내부 인증 로직에 활용
  • 세션 정책 및 URL 접근 권한 설정

4. 구현의 장점과 배운 점

  • Spring Security가 제공하는 인증 흐름과 세션 관리를 활용하여 코드가 간결해집니다.
  • 직접 세션, 쿠키 관리하지 않고 SecurityContext와 세션 연동으로 보안성과 유지보수성 향상
  • UserDetailsService와 AuthenticationManager를 통해 인증 로직을 표준화
  • 확장성 높은 구조 (OAuth, JWT 등으로도 자연스러운 전환 가능)

5. 마무리 및 앞으로 할 일

  • 필요에 따라 로그인 실패 핸들링, 권한(Role) 분기 추가 가능
  • JWT 토큰 기반 인증에 대해 공부
  • Spring Security를 최대한 활용하여 안정적이고 확장 가능한 인증 시스템 구현 목표