MyBatis → Jpa 과정에 대한 전반적인 과제 기본 요건 수정이 이뤄지면서 새로운 형식의 과제를 구현하게 되었고
그에 따른 트러블 슈팅 및 해결방법을 기록하고자 한다.
☠️ 트러블 슈팅
발생한 Issue
- ① 회원가입 API 구현 이후 포스트맨으로 Request Body를 전송해도 응답이 되지 않는 (401 error) 현상이 발생
- Spring Security 의존성을 추가하게 되며 모든 요청이 Security에 막힌 상황

- ② JwtUtil에서 선언한 필드(@Value)에 왜 final이 붙으면 에러가 뜨는지 이유가 궁금했음
- 인증(Authentication)과 인가(Authorization) 의 개념과 정의에 대해 명확히 알지 못해 필터를 구현할때 메서드 선언부에서 혼선이 발생
- ③ DB 테이블 기준으로는 Round-Menu의 값이 직접적으로 테이블 컬럼이 없는데 라운드 생성 과정에서는 메뉴를 담는 과정이 필요했고, 어떻게 표현해야 하는지에 대해 이해가 가지않아 개념 정리가 필요했음
해결방법 / 찾아본 내용
- ① 과제의 의도 자체가 결국엔 Jwt 인증 인가 기능을 구현하는 과정이기 때문에 우선적으로 초기 개발단계에서는 SecurityConfig 임시파일을 통해 기본적으로 구현 및 동작해야할 API에 대해 권한을 풀어주는 과정이 필요
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.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain FilterChain(HttpSecurity http) throws Exception {
http
// csrf 비활성화
.csrf(csrf -> csrf.disable())
// 요청 권한 설정
.authorizeHttpRequests(auth -> auth
// 회원가입, 로그인 API는 인증 없이 접근 허용
.requestMatchers("/api/auth/**").permitAll()
// 나머지 요청은 인증 및 권한 필요
.anyRequest().authenticated()
);
return http.build();
}
}
위 과정을 구현하고 난 이후 Postman에서 요청 처리 시

정상적으로 201 created 된 부분을 확인할 수 있었다.
- ② @Value로 주입받는 필드에는 final을 사용하면 안됨
- @Value는 런타임 도중에 값이 주입되기 때문에
쉽게 말해 객체가 만들어진 다음에 값이 들어가는 구조이기 때문에 final(생성자에서 한번만 값이 초기화되어야 한다) 과 충돌하여 오류가 발생하게 되는 상황
👉 대체하여 사용할 수 있는 방법은 어떤 것들이 있을까? - final을 사용하고 싶다면 @Value 대신 @ConstructorBinding 또는 @ConfigurationProperties 방식을 사용해야 함
- @Value는 런타임 도중에 값이 주입되기 때문에
@Component
@ConfigurationProperties(prefix = "jwt")
@Getter
public class JwtProperties {
private final String secret;
private final long accessExpMs;
private final long refreshExpMs;
public JwtProperties(String secret, long accessExpMs, long refreshExpMs) {
this.secret = secret;
this.accessExpMs = accessExpMs;
this.refreshExpMs = refreshExpMs;
}
}
를 생성한 이후 JwtUtil에서 아래와 같이 받으면 됨
@Component
@RequiredArgsConstructor
public class JwtUtil {
private final JwtProperties props;
public String generateAccessToken(Long id, String email) {
String secretKey = props.getSecret();
...
}
}
이런 과정을 거치면 정적 타입 안정성과 불변성을 보장받을 수 있음
@Value의 경우는 대규모 설정 관리와 안정성 측면에서 떨어지기 때문에 @ConfigurationProperties를 통해 타입 안정성을 보장받을 수 있도록 리팩토링 계획을 수립
- 인증(Authentication)
- 요청을 보낸 사람이 유효한 사용자(로그인한 사용자) 인가? 에 대한 검증을 하는 단계
- Spring Security에서는 다음과 같은 단계로 진행됨
- 로그인 시 ID/PW로 사용자 확인 → 인증완료
- JWT 기반에서는 "토큰 유효성 검사" 가 바로 인증 과정을 의미
- 인증이 성공하면 SecurityContext에 사용자 정보(Authentication) 저장
- 요청마다 로그인된 사용자로 인식
- 인가(Authorization)
- 사용자가 특정 자원(API, 페이지)에 접근할 권한이 있는가 를 검사하는 단계
- 인증 , 인가 순서의 관계를 정리하자면 아래와 같이 예시로 적용되는 과정을 알 수 있음
[1] 요청 들어옴
↓
[2] JwtAuthenticationFilter에서 JWT 토큰 검증 (Authentication)
↓
[3] SecurityContext에 로그인 사용자 저장
↓
[4] Spring Security가 권한 규칙 확인 (Authorization)
↓
[5] 접근 허용 or 차단 (403 Forbidden)
- ③ DB 상으로는 직접적인 Menu 컬럼이 없어야 하는 것은 맞지만, 엔티티에는 리스트 필드가 있어야 맞는 구조

'Spring > Spring 실습' 카테고리의 다른 글
| [프로젝트] 포인트 기반 결제 시스템 프로젝트 회고 (0) | 2025.11.28 |
|---|---|
| [Spring 실습] 이커머스 백오피스 프로젝트 (0) | 2025.11.03 |
| [Spring 실습] 점심 추천 & 투표 서비스 만들기 v1 (0) | 2025.10.27 |
| [Spring 실습] 강의 내용 진행 중 문제점 정리 (0) | 2025.10.21 |
| [Spring] 일정 관리 앱 만들기 (0) | 2025.10.20 |