어제 오늘 내일

[Spring Security] 1편 - 도대체 왜 쓰는 걸까? (핵심 개념 & 구조 쉽게 이해하기) 본문

IT/SpringBoot

[Spring Security] 1편 - 도대체 왜 쓰는 걸까? (핵심 개념 & 구조 쉽게 이해하기)

hi.anna 2026. 2. 16. 07:55

스프링을 공부하는 많은 분들이 "가장 큰 통곡의 벽"으로 꼽는 것이 바로 Spring Security입니다.
설정할 것도 많고, 용어도 어렵죠 (Principal? GrantedAuthority? FilterChain?).

하지만 한 번 이해하고 나면 이만큼 든든한 보디가드도 없습니다.
오늘은 복잡한 코드를 짜기 전에, Spring Security가 왜 필요하고 어떻게 작동하는지 아주 쉽게 개념부터 잡아보겠습니다.


1. Spring Security, 왜 쓸까?

만약 시큐리티 없이 우리가 직접 로그인과 권한 체크를 구현한다면 어떻게 될까요?
아마 모든 Controller 메소드마다 이런 코드를 넣어야 할 겁니다.

// 시큐리티가 없다면... (끔찍한 상황)
@GetMapping("/admin/members")
public String memberList(HttpSession session) {
    User user = (User) session.getAttribute("LOGIN_USER");

    // 1. 로그인을 안 했으면 튕겨낸다.
    if (user == null) {
        return "redirect:/login";
    }

    // 2. 로그인은 했는데 관리자가 아니면 튕겨낸다.
    if (!user.getRole().equals("ADMIN")) {
        return "error/403";
    }

    // 3. 이제서야 로직 수행...
    return "admin/members";
}

개발자가 실수로 if 문을 하나라도 빼먹는 순간, 보안 구멍이 뻥 뚫리게 됩니다.

Spring Security는 이 귀찮고 위험한 작업을 '서블릿 필터(Filter)'를 이용해 대신 처리해 줍니다.

요청이 Controller에 도착하기도 전에 "너 누구야? 표 보여줘." 라고 검문하는 것이죠.

개발자는 비즈니스 로직에만 집중하면 됩니다.


2. 가장 중요한 두 단어: 인증(Authentication) vs 인가(Authorization)

시큐리티를 이해하려면 딱 두 단어만 구별하면 됩니다. 비슷해 보이지만 완전히 다릅니다.

  1. 인증 (Authentication): "너 누구니?"
  • 사용자의 신원을 확인하는 과정입니다.
  • 예) 로그인 (아이디/비번 입력), 지문 인식
  1. 인가 (Authorization): "너 이거 할 수 있어?"
  • 인증된 사용자가 특정 리소스에 접근할 권한이 있는지 확인하는 과정입니다.
  • 예) '부장님'은 결재 가능, '사원'은 조회만 가능.

순서: 항상 인증(로그인)을 먼저 하고, 그 다음에 인가(권한 체크)가 일어납니다.


3. 시큐리티 동작 원리 (비유)

복잡한 클래스 이름 대신, '회사 건물 출입' 상황에 비유해 보겠습니다.

등장인물 매칭

  • 방문객 (User): 로그인하려는 사람
  • 출입증 발급 데스크 (AuthenticationFilter): 아이디/비번을 받는 곳
  • 보안 팀장 (AuthenticationManager): 출입증을 발급해 줄지 결정하는 실질적인 관리자
  • 인사팀 직원 (UserDetailsService): 직원 명부(DB)를 들고 있는 사람
  • 출입증 (Authentication / SecurityContext): 인증 성공 후 발급받은 목걸이

동작 시나리오

  1. 방문객(User)이 "저 들어가고 싶어요"라며 신청서(아이디/비번)를 제출합니다. (로그인 요청)
  2. 데스크(Filter)가 신청서를 받아서 보안 팀장(Manager)에게 넘깁니다.
  3. 보안 팀장은 인사팀(UserDetailsService)에게 전화를 겁니다. "거기 명부(DB)에 '홍길동'이라는 사람 있나 확인해 줘."
  4. 인사팀은 DB를 뒤져서 그 사람의 정보를 보안 팀장에게 알려줍니다. (UserDetails 반환)
  5. 보안 팀장은 방문객이 낸 비번과 DB의 비번이 일치하는지 확인합니다. (PasswordEncoder)
  6. 일치한다면? 출입증(Authentication)을 발급해서 건물의 보관함(SecurityContextHolder)에 넣어둡니다.
  7. 이제 방문객은 건물을 돌아다닐 때마다 보관함에 있는 출입증을 보여주고 통과합니다. (세션 유지)

4. 실제 클래스 구조 (Architecture)

위 비유를 실제 Spring Security의 핵심 클래스로 바꿔보면 다음과 같습니다.

  1. UsernamePasswordAuthenticationFilter: 아이디와 비밀번호를 가로채서 인증 요청을 만듭니다.
  2. AuthenticationManager: 여러 인증 방법(비번, 토큰, 지문 등) 중 알맞은 것을 찾아 위임하는 관리자입니다.
  3. UserDetailsService: (가장 중요!) 개발자가 직접 구현해야 하는 인터페이스입니다. DB에서 유저 정보를 가져오는 로직이 여기에 들어갑니다.
  4. UserDetails: DB에 있는 유저 정보를 시큐리티가 이해할 수 있게 변환한 객체입니다.
  5. SecurityContextHolder: 인증이 끝난 사용자의 정보를 담고 있는 저장소입니다. 어디서든 SecurityContextHolder.getContext()로 누가 로그인했는지 알 수 있습니다.

마무리

오늘은 코드를 작성하기 전에 Spring Security가 무엇이고 어떤 구조로 되어있는지 알아봤습니다.

결국 우리가 개발하면서 건드려야 할 핵심은 "UserDetailsService를 구현해서 내 DB와 연결하는 것""SecurityConfig로 권한 규칙을 정하는 것"입니다.

다음 2편에서는 실제 프로젝트에 Spring Security 의존성을 추가하고, 기본적인 설정(SecurityConfig)을 잡아보겠습니다.


[Tip]
이 포스팅을 보시고 "아, 필터가 앞에서 막아주는구나", "UserDetailsService가 DB랑 연결해주는구나" 정도만 이해하셨다면 성공입니다!

 

 

반응형
Comments