코딩:개발일지

JWT vs OAuth2 정리 - 백엔드 개발자가 알아야 할 개념

ZZJJing 2025. 5. 25. 19:36
반응형

 

■ JWT란?

정의: JSON Web Token의 줄임말, 정보를 안전하게 전송하기 위한 토큰 형식

구조:

Header.Payload.Signature
  • Header: 토큰 타입과 해싱 알고리즘
  • Payload: 실제 데이터 (Claims)
  • Signature: 토큰 검증용 서명

특징:

  • Self-contained (토큰 자체에 정보 포함)
  • Stateless (서버에 상태 저장 안함)
  • Base64로 인코딩됨
  • 만료시간 설정 가능

 OAuth2란?

정의: 인증/인가를 위한 프로토콜, 제3자 앱이 사용자 대신 리소스에 접근할 수 있게 해줌

주요 역할자:

  • Resource Owner: 사용자
  • Client: 앱
  • Authorization Server: 인증 서버
  • Resource Server: 리소스 서버

Grant Types:

Grant Type 용도 보안 수준 적용 대상

Authorization Code 웹앱용 가장 안전 서버 사이드 앱
Implicit SPA용 낮음 (deprecated) 단일 페이지 앱
Client Credentials 서버간 통신 높음 백엔드 서비스
Resource Owner Password 신뢰 앱만 보통 자체 서비스 앱

 핵심 차이점

구분 JWT OAuth2

성격 토큰 형식 인증/인가 프로토콜
용도 정보 전송, 인증 상태 유지 제3자 앱 권한 위임
상태 Stateless Stateful 가능
만료 토큰 자체에 정의 서버에서 관리
취소 어려움 (만료까지 유효) 쉬움 (서버에서 제어)

 언제 사용?

구분 JWT OAuth2

코드 예시 String token = Jwts.builder() <br> .setSubject(userId) <br> .signWith(key).compact(); @GetMapping("/oauth2/google") <br> OAuth2AuthorizedClient client
단순 인증/인가 적합 과도함
마이크로서비스 통신 적합 복잡함
모바일 앱 인증 적합 경우에 따라
소셜 로그인 불가능 필수
제3자 API 연동 불가능 필수
세밀한 권한 제어 제한적 강력함
토큰 취소 어려움 쉬움
서버 확장성 우수 보통

 함께 사용하기

일반적인 패턴: OAuth2로 인증 후 JWT 발급

@RestController
public class AuthController {
    
    @GetMapping("/oauth2/callback")
    public ResponseEntity<TokenResponse> handleCallback(
            @RequestParam String code) {
        
        // 1. OAuth2로 사용자 정보 획득
        OAuth2User userInfo = oAuth2Service.getUserInfo(code);
        
        // 2. JWT 토큰 생성
        String jwtToken = Jwts.builder()
            .setSubject(userInfo.getId())
            .claim("email", userInfo.getEmail())
            .claim("role", userInfo.getRole())
            .setExpiration(new Date(System.currentTimeMillis() + 604800000)) // 7일
            .signWith(jwtSecret)
            .compact();
        
        return ResponseEntity.ok(new TokenResponse(jwtToken));
    }
}

## 보안 고려사항

| 구분 | JWT | OAuth2 |
|------|-----|--------|
| **주요 취약점** | XSS 공격 (localStorage 저장 시) | CSRF 공격 |
| **토큰 크기** | 클 수 있음 (정보 포함) | 작음 (참조용) |
| **토큰 취소** | 만료 전까지 불가능 | 언제든 가능 |
| **필수 요구사항** | Secret key 안전 관리 | HTTPS 필수 |
| **추가 보안** | HttpOnly 쿠키 권장 | State 파라미터 CSRF 방지 |
| **검증 방식** | 서명 검증 | Authorization Server 확인 |
| **만료 관리** | 토큰 자체에 포함 | 서버에서 제어 |

## 실제 구현 팁

### JWT 구현 (Spring Boot)
```java
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, 
            HttpServletResponse response, FilterChain filterChain) 
            throws ServletException, IOException {
        
        String token = extractTokenFromRequest(request);
        
        if (token == null) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return;
        }
        
        try {
            Claims claims = Jwts.parserBuilder()
                .setSigningKey(jwtSecret)
                .build()
                .parseClaimsJws(token)
                .getBody();
                
            String userId = claims.getSubject();
            // SecurityContext에 인증 정보 설정
            
        } catch (JwtException e) {
            response.setStatus(HttpStatus.FORBIDDEN.value());
            return;
        }
        
        filterChain.doFilter(request, response);
    }
    
    private String extractTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

OAuth2 구현 (Spring Security)

@Configuration
@EnableWebSecurity
public class OAuth2Config {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .oauth2Login(oauth2 -> oauth2
                .loginPage("/login")
                .successHandler(customSuccessHandler())
                .userInfoEndpoint(userInfo -> userInfo
                    .userService(customOAuth2UserService())
                )
            );
        return http.build();
    }
    
    @Bean
    public OAuth2AuthorizedClientService authorizedClientService(
            ClientRegistrationRepository clientRegistrationRepository) {
        return new InMemoryOAuth2AuthorizedClientService(
            clientRegistrationRepository);
    }
}

// application.yml 설정
/*
spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: ${GOOGLE_CLIENT_ID}
            client-secret: ${GOOGLE_CLIENT_SECRET}
            scope:
              - profile
              - email
*/

 

JWT: 토큰 형식, 정보 전송 및 상태 유지에 사용

OAuth2: 권한 위임 프로토콜, 제3자 서비스 연동에 사용

둘 다 현대 웹 개발에서 필수적인 기술이며, 상황에 맞게 적절히 조합해서 사용하는 것이 중요함.

 

728x90
반응형