1단계: 라이브러리 확인 (build.gradle)

아까 추가하셨겠지만, 혹시 모르니 다시 확인! 없으면 추가하고 코끼리 버튼(Reload) 눌러주세요.

Groovy

dependencies {
    // ...
    // JWT 라이브러리 (jjwt)
    implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
}

2단계: 설정 파일에 암호키 숨기기 (application.yml)

src/main/resources/application.yml 파일을 열어서 맨 아래에 비밀키를 적어줍니다. (HS256 알고리즘은 키가 너무 짧으면 에러가 나니, 아주 길게(32글자 이상) 아무 말이나 적어주세요.)

YAML

jwt:
  secret: "vmfhalwmehvbqwiurnvwnerviunerwiuvneriwuvnreiuwvneriwuvn" # 아무거나 아주 길게!

3단계: 토큰 공장 가동 (JwtUtil.java)

아까 작성했던 코드와 동일합니다. src/main/java/com/csarena/api/global/util/JwtUtil.java 위치에 정확히 있는지 확인해주세요.

Java

package com.csarena.api.global.util;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.nio.charset.StandardCharsets;
import java.util.Date;

@Component // 스프링 빈 등록
public class JwtUtil {

    private final Key key;
    private final long expirationTime = 1000 * 60 * 60 * 24; // 24시간 (1일)

    // application.yml의 jwt.secret 값을 가져옵니다
    public JwtUtil(@Value("${jwt.secret}") String secretKey) {
        this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8));
    }

    public String generateToken(Long userId, String email) {
        return Jwts.builder()
                .setSubject(String.valueOf(userId)) // 토큰 주인(ID)
                .claim("email", email)              // 내용물(Payload)
                .setIssuedAt(new Date())            // 발행 시간
                .setExpiration(new Date(System.currentTimeMillis() + expirationTime)) // 만료 시간
                .signWith(key, SignatureAlgorithm.HS256) // 서명 (도장 쾅!)
                .compact();
    }
}

4단계: 컨트롤러 연결 (AuthController.java)

이제 컨트롤러에서 JwtUtil을 주입받고, 가짜 문자열 대신 진짜 토큰을 발급합니다.

Java

package com.csarena.api.domain.user.controller;

import com.csarena.api.domain.user.dto.SignupRequest;
import com.csarena.api.domain.user.dto.SignupResponse;
import com.csarena.api.domain.user.entity.User;
import com.csarena.api.domain.user.service.UserService;
import com.csarena.api.global.common.dto.ApiResult;
import com.csarena.api.global.util.JwtUtil; // ★ import 확인
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/auth")
public class AuthController {

    private final UserService userService;
    private final JwtUtil jwtUtil; // ★ 1. 주입 받기

    @PostMapping("/signup")
    public ResponseEntity<ApiResult<SignupResponse>> signup(@RequestBody @Valid SignupRequest request) {
        // 1. 회원가입 진행 (DB 저장)
        User newUser = userService.signup(request.getEmail(), request.getPassword(), request.getNickname());

        // 2. ★ 진짜 JWT 토큰 발급!
        String accessToken = jwtUtil.generateToken(newUser.getId(), newUser.getEmail());

        // 3. 응답에 토큰 담기
        SignupResponse responseData = SignupResponse.builder()
                .userId(newUser.getId())
                .email(newUser.getEmail())
                .accessToken(accessToken) // "아직_구현_안함" -> accessToken 변수로 교체
                .message("회원가입이 완료되었습니다.")
                .build();

        return ResponseEntity.ok(ApiResult.success(responseData));
    }
    
    // ... 나머지 check 메서드들 ...
}

🚀 최종 확인 (Postman)

이제 다시 서버를 켜고 Postman으로 회원가입 요청을 보내보세요.

  • 응답 결과:

JSON

{
  "success": true,
  "data": {
    "userId": 1,
    "email": "real@test.com",
    "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiw...", // ★ 이렇게 엄청 긴 외계어가 나와야 성공!
    "message": "회원가입이 완료되었습니다."
  }
}

✅ 꿀팁: 나온 토큰(eyJ...)을 복사해서 jwt.io 사이트에 붙여넣어 보세요. 오른쪽 Payload 박스에 우리가 넣은 이메일과 유저 ID가 보이면 완벽하게 성공입니다!

테스트 코드는 토큰 값 자체를 검사하지 않기 때문에(그냥 성공 여부만 보니까), 기존 테스트들도 여전히 통과할 겁니다. (이게 바로 좋은 설계의 장점이죠! 👍)

잘 되시는지 확인 부탁드려요!