스프링 부트 3.2 매개변수 이름 인식 문제

젤리젤링텀·2024년 1월 18일
6

Spring, SpringBoot

목록 보기
6/8

Spring Boot JWT Tutorial을 수행하는 도중 회원가입 API까지 다 구현하고 발생한 오류..

2024-01-18T20:34:26.838+09:00 ERROR 31880 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.IllegalArgumentException: Name for argument of type [java.lang.String] not specified, and parameter name information not available via reflection. Ensure that the compiler uses the '-parameters' flag.] with root cause

스프링 부트 3.2부터 매개변수의 이름을 인식하지 못하는 문제가 있다고 한다.

스프링 부트 3.2부터 자바 컴파일러에 -parameters 옵션을 넣어주어야 어노테이션의 이름을 생략할 수 있다.

주로 아래의 어노테이션을 사용할 때 문제가 발생한다.

@RequestParam, @PathVariable, @Autowired, @ConfigurationProperties

@RequestParam 관련

어노테이션에 username이라는 이름이 명확하게 있다. 문제 없이 작동한다.

@RequestMapping("/request")
public String request(@RequestParam("username") String username) {
   ...
}

어노테이션에 이름이 없다. -parameters 옵션 필요

@RequestMapping("/request")
public String request(@RequestParam String username) {
   ...
}

어노테이션도 없고 이름도 없다. -parameters 옵션 필요

@RequestMapping("/request")
public String request(String username) {
   ...
}

@PathVariable 관련

어노테이션에 userId라는 이름이 명확하게 있다. 문제 없이 작동한다.

public String mappingPath(@PathVariable("userId") String userId) {
    ...
}

어노테이션에 이름이 없다. -parameters 옵션 필요

@RequestMapping("/request")
public String request(@RequestParam String username) {
   ...
}

@Autowired 관련

MemberRepository를 구현한 빈이 여러개 있다면 다음 코드에서 MemberRepository를 주입 받을 때 변수 이름인 memberRepository를 통해서 memberRepository라는 이름의 스프링 빈을 찾는다. 하지만 매개변수 이름을 사용할 수 없기 때문에 이름으로 대상을 찾을 수 없다.

@Component
public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository;

    @Autowired
    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}

해결 방안1

어노테이션에 이름을 생략하지 않고 다음과 같이 항상 적어준다.

@RequestParam("username") String username
@PathVariable("userId") String userId
@Qualifier("memberRepository") MemberRepository memberRepository

해결 방안2

컴파일 시점에 -parameters 옵션 적용

  1. IntelliJ IDEA에서 File -> Settings를 연다. (Mac은 IntelliJ IDEA -> Settings)
  2. Build, Execution, Deployment → Compiler → Java Compiler로 이동한다.
  3. Additional command line parameters라는 항목에 다음을 추가한다.
    -parameters
  4. out 폴더를 삭제하고 다시 실행한다. 꼭 out 폴더를 삭제해야 다시 컴파일이 일어난다.

해결 방안3(권장)

Gradle을 사용해서 빌드하고 실행한다.

참고로 이 문제는 Build, Execution, Deployment -> Build Tools -> Gradle에서
Build and run using를 IntelliJ IDEA로 선택한 경우에만 발생한다. Gradle로 선택한 경우에는 Gradle이 컴파일 시점에 해당 옵션을 자동으로 적용해준다.

해결방안 3번을 선택하시면 코드 변경없이 문제를 해결할 수 있습니다. 3번을 권장합니다.

문제 원인

공식 링크: https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-6.x#parameter-name-retention

자바를 컴파일할 때 매개변수 이름을 읽을 수 있도록 남겨두어야 사용할 수 있다. 컴파일 시점에 -parameters 옵션을 사용하면 매개변수 이름을 사용할 수 있게 남겨둔다.

스프링 부트 3.2 전까지는 바이트코드를 파싱해서 매개변수 이름을 추론하려고 시도했다. 하지만 스프링 부트 3.2 부터는 이런 시도를 하지 않는다.

[출처] 인프런 김영한님의 자주 하는 질문https://docs.google.com/document/d/1j0jcJ9EoXMGzwAA2H0b9TOvRtpwlxI5Dtn3sRtuXQas/edit#heading=h.b1yk4ued1pxo

profile
열심히 살자

1개의 댓글

comment-user-thumbnail
2024년 4월 24일

이틀간 골머리 아팠는데 덕분에 해결했습니다.
out 폴더를 삭제해야만 -parameters가 적용이 되는거였군요!

답글 달기