Topic (오늘의 주제)
Spring Security: 인증(Authentication)과 인가(Authorization)
Why (왜 사용하는가? 왜 중요한가?)
- 실무: 보안 기능을 직접 구현하는 것은 매우 위험하고 어렵습니다. Spring Security는 검증된 보안 표준을 제공하여, SQL 인젝션, 세션 고정, CSRF 등 일반적인 보안 위협으로부터 시스템을 보호합니다.
- 구조적 의미: 보안 로직을 비즈니스 로직에서 분리(Filter 기반)하여, 개발자가 비즈니스 로직에만 집중할 수 있는 환경을 제공합니다.
- 면접 의도: "인증(누구인가)"과 "인가(권한이 있는가)"의 명확한 차이를 이해하는지, 그리고 Spring Security의 핵심인 Filter Chain의 동작 흐름을 설명할 수 있는지 확인합니다.
Core Concept (핵심 개념 정리)
Spring Security는 Servlet Filter를 기반으로 동작하며, 크게 두 단계로 나뉩니다.
| 요소 | 인증 (Authentication) | 인가 (Authorization) |
| 개념 정의 | "당신은 누구인가?" 사용자의 신원(Identity)을 입증하는 과정. (예: 로그인) |
"당신은 무엇을 할 수 있는가?" 인증된 사용자가 특정 리소스에 접근할 권한이 있는지 확인하는 과정. |
| 핵심 컴포넌트 | 1. AuthenticationManager: 인증 처리의 총괄자. 2. AuthenticationProvider: 실제 인증 로직(DB 대조 등) 수행. 3. UserDetailsService: DB에서 유저 정보를 가져오는 역할. 4. SecurityContextHolder: 인증된 정보를 저장하는 저장소. |
1. SecurityFilterChain: URL 별 권한 설정. 2. AuthorizationManager: 접근 허용 여부 결정. 3. GrantedAuthority: 사용자에게 부여된 권한(Role). |
| 동작 흐름 | 로그인 요청 → AuthenticationFilter → AuthenticationManager → Provider가 DB 확인 → 성공 시 SecurityContext에 저장. | 인증된 사용자 요청 → FilterSecurityInterceptor(또는 AuthorizationFilter)가 가로챔 → 권한 확인 → 접근 허용/거부(403). |
| 장점/단점 | 장점: 강력한 보안, 확장성(OAuth2, JWT 등 연동 용이). 단점: 초기 설정 및 구조 이해의 장벽이 높음(러닝 커브). |
Interview Answer Version (면접 답변식 요약)
"Spring Security에서 **인증(Authentication)**은 '사용자의 신원을 확인하는 로그인 과정'이고, **인가(Authorization)**는 '인증된 사용자가 특정 리소스에 접근 가능한지 권한을 확인하는 과정'입니다.
Spring Security는 Filter Chain을 통해 요청을 가로채어 처리하며, 인증 시에는 AuthenticationManager와 UserDetailsService를 통해 DB의 정보와 대조하고, 성공 시 **SecurityContextHolder**에 인증 객체를 저장하여 전역적으로 사용합니다."
Practical Tip (사용시 주의할 점 or 활용 예)
1. 비밀번호 암호화는 필수 (PasswordEncoder)
- 비밀번호를 DB에 평문(Plain Text)으로 저장하면 절대 안 됩니다.
- Spring Security는 BCryptPasswordEncoder 등을 빈으로 등록해두면, 로그인 시 입력된 비밀번호와 DB의 암호화된 비밀번호를 알아서 비교(matches())해줍니다.
2. UserDetailsService 커스터마이징
- 실무에서는 UserDetailsService 인터페이스를 구현하여, 우리 시스템의 DB(MemberRepository 등)에서 유저 정보를 조회해 반환하는 로직을 반드시 작성해야 합니다.
- Java
@Service public class CustomUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) { // DB에서 회원 조회 후 UserDetails(Security 전용 객체)로 변환 반환 return memberRepository.findByEmail(username) .map(member -> new CustomUserDetails(member)) .orElseThrow(() -> new UsernameNotFoundException("유저 없음")); } }
3. @PreAuthorize 활용 (메서드 시큐리티)
- URL 기반 설정(requestMatchers("/admin/**").hasRole("ADMIN"))도 좋지만, 세밀한 제어를 위해 메서드 위에 애노테이션을 붙이는 방식을 많이 씁니다.
- @EnableMethodSecurity를 설정 클래스에 붙이고, @PreAuthorize("hasRole('ADMIN')") 처럼 사용합니다.
예상 꼬리질문 정리
- Q: SecurityContextHolder의 전략(Strategy)에 대해 아시나요? (ThreadLocal)
- 핵심 키워드: 기본적으로 ThreadLocal을 사용하여 한 요청(스레드) 내에서는 어디서든 인증 정보를 공유합니다. 비동기 처리 시에는 전략을 바꿔야 정보가 전달됩니다.
- Q: 세션 기반 인증과 토큰 기반 인증(JWT)의 차이를 Spring Security 관점에서 설명해주세요.
- 핵심 키워드: 세션은 SecurityContext를 세션(HttpSession)에 저장하지만, JWT는 Stateless하므로 요청마다 토큰을 파싱해서 SecurityContext를 매번 새로 만들어 넣어주는 필터가 필요합니다.
- Q: 인증에 실패하면 어떤 예외가 발생하고 어떻게 처리하나요?
- 핵심 키워드: AuthenticationException이 발생하며, AuthenticationEntryPoint 인터페이스를 구현하여 커스텀 에러 응답(401 Unauthorized)을 내려줍니다.
'Archive > Daily Dev Q&A' 카테고리의 다른 글
| Daily Dev Q&A: RESTful API 설계 원칙과 애매한 상황(Edge Case)의 현실적 해결 전략 (0) | 2025.12.31 |
|---|---|
| Daily Dev Q&A: session 로그인 방식과 token 로그인 방식 (0) | 2025.12.31 |
| Daily Dev Q&A: @SpringBootApplication은 필수인가? (1) | 2025.12.30 |
| Daily Dev Q&A: Spring의 예외 처리 방식 (0) | 2025.12.29 |
| Daily Dev Q&A: Spring Stereotype Annotations (0) | 2025.12.29 |