안녕하세요! 이번 블로그 포스트에서는 스프링 부트를 활용한 백엔드 개발 과정에서 JSON Web Token(JWT)을 사용하여 로그인 및 로그아웃 기능을 구현하는 방법에 대해 자세히 알아보겠습니다. 웹 애플리케이션 개발에서 인증과 권한 부여는 중요한 요소이며, JWT는 이를 효과적으로 관리하는 데 도움을 줍니다. 본 강좌에서는 JWT의 개념, 스프링 부트 설정, 의존성 추가 방법 등을 단계별로 설명하겠습니다.
1. JWT란 무엇인가?
JWT는 JSON Web Token의 약자로, 사용자 인증 정보를 안전하게 전송하기 위한 표준입니다. JWT는 세 가지 부분으로 구성되어 있습니다:
- Header: 토큰의 타입과 해싱 알고리즘 정보를 담고 있습니다.
- Payload: 사용자 정보와 같은 클레임을 포함합니다. 이 클레임은 공개된 정보(API 호출 시 필요한 정보)를 포함할 수 있습니다.
- Signature: 헤더와 페이로드 정보를 기반으로 비밀 키를 사용하여 서명합니다. 이는 데이터의 무결성을 보장하며, 누군가 토큰을 위조했는지를 확인하는 데 사용됩니다.
JWT의 가장 큰 장점은 스테이트리스(stateless) 특성을 가진다는 것입니다. 서버에서 세션 상태를 유지할 필요가 없기 때문에, 확장성과 성능이 뛰어납니다.
2. 스프링 부트 프로젝트 생성
스프링 부트를 사용하여 새로운 프로젝트를 생성합시다. 먼저, Spring Initializr(https://start.spring.io/)를 방문합니다. 아래의 설정을 적용하여 프로젝트를 생성합니다:
- Project: Maven Project
- Language: Java
- Spring Boot: 2.6.0 (최신 버전 선택)
- Group: com.example
- Artifact: jwt-demo
- Dependencies: Spring Web, Spring Security, Spring Data JPA, H2 Database
프로젝트를 생성한 후, IDE에서 해당 프로젝트를 열고 필요한 디렉토리 구조를 설정합니다.
3. 의존성 추가하기
먼저, pom.xml
파일에 필요한 의존성을 추가합니다:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jwt</artifactId>
<version>0.9.1</version>
</dependency>
이외에도 스프링 시큐리티와 데이터 JPA는 이미 추가되어 있으므로 추가 의존성은 필요하지 않습니다. H2 데이터베이스는 개발과 테스트 환경에 유용하게 사용할 수 있습니다.
4. 스프링 시큐리티 설정
JWT를 사용하기 위해 스프링 시큐리티를 설정해야 합니다. 먼저 SecurityConfig
클래스를 생성합니다:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated();
}
}
위의 설정에서, 모든 사용자는 /api/auth/**
경로에 접근할 수 있습니다. 다른 모든 요청은 인증을 요구합니다.
5. JWT 생성 및 검증
JWT를 생성하고 검증하는 클래스를 작성합니다. 여기에 필요한 메서드를 정의합니다:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
public class JwtUtil {
private String secretKey = "YourSecretKey"; // 비밀 키는 외부에 노출되지 않게 관리해야 합니다
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10시간
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
}
public boolean validateToken(String token, String username) {
final String extractedUsername = extractUsername(token);
return (extractedUsername.equals(username) && !isExpired(token));
}
public String extractUsername(String token) {
return extractAllClaims(token).getSubject();
}
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
}
private boolean isExpired(String token) {
return extractAllClaims(token).getExpiration().before(new Date());
}
}
위의 JwtUtil
클래스는 토큰 생성, 유효성 검증 및 사용자 이름 추출을 위한 메서드를 포함하고 있습니다.
6. 인증 및 로그아웃 구현
이제 인증 및 로그아웃을 처리할 컨트롤러를 작성해보겠습니다. AuthController
클래스를 생성하세요:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/login")
public ResponseEntity login(@RequestBody AuthRequest authRequest) {
// 사용자 인증 로직 추가
String token = jwtUtil.generateToken(authRequest.getUsername());
return ResponseEntity.ok(token);
}
@PostMapping("/logout")
public ResponseEntity logout() {
// JWT를 블랙리스트에 추가하는 등의 로직 추가
return ResponseEntity.ok("로그아웃 성공");
}
}
위의 코드에서 AuthRequest
는 사용자 이름과 비밀번호를 담는 DTO 클래스이며, 사용자 인증 로직은 구체적으로 구현해야 합니다. 일반적으로는 데이터베이스에서 인증 정보를 확인합니다.
7. 최종 테스트
이제 모든 설정을 마쳤습니다. Postman과 같은 도구를 사용하여 API를 테스트할 수 있습니다:
- 로그인:
POST /api/auth/login
- 로그아웃:
POST /api/auth/logout
로그인 API의 요청 본문에서 사용자 이름과 비밀번호를 전달하면, 성공적으로 JWT를 반환받을 수 있습니다. 반환된 JWT는 이후 API 호출 시 Authorization
헤더에 포함하여 전달해야 합니다.
8. 마무리
스프링 부트를 사용한 JWT 기반의 로그인 및 로그아웃 기능 구현에 대해 알아보았습니다. 인증 및 권한 부여는 웹 애플리케이션 개발에서 중요한 부분이며, JWT는 이를 간편하고 안전하게 처리할 수 있도록 돕습니다. 추가 기능으로는 JWT 블랙리스트 처리, 리프레시 토큰 구현 등을 고려해볼 수 있습니다.
이번 강좌가 스프링 부트 백엔드 개발에 도움이 되었기를 바랍니다. 더 많은 정보와 자료는 공식 문서와 커뮤니티를 통해 확인할 수 있습니다. 감사합니다!