• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

@PathVariable name 생략 질문 드립니다.

23.11.28 23:04 작성 조회수 1.69k

4

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.

1. 강의 내용과 관련된 질문을 남겨주세요.
2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.
(자주 하는 질문 링크: https://bit.ly/3fX6ygx)
3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.
(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)

질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.
=========================================
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)

[질문 내용]
여기에 질문 내용을 남겨주세요.

@GetMapping("/{itemId}")
public String item(@PathVariable("itemId") Long itemId, Model model) {
Item item = itemRepository.findById(itemId);
model.addAttribute("item", item);
return "basic/item";
}

제가 알기론 Mapping 의 경로와 변수명이 같다면 name을 생략 가능한걸로 알아 원래 예제에선 PathVariable 뒤에 ("itemId") 를 생략하여도 잘 작동하지만, 따라해보니 name을 생략하면 아래와 같은 오류가 발생합니다.
java.lang.IllegalArgumentException: Name for argument of type [java.lang.Long] not specified, and parameter name information not found in class file either

왜 이런걸까요>?

답변 2

·

답변을 작성해보세요.

5

김영한님의 프로필

김영한

지식공유자

23.12.02 16:51

안녕하세요. co-account님 다음을 참고해주세요

그리고 스프링 부트 3.2를 사용하시는 것을 권장합니다. 🙂

자주하는 질문 링크: https://docs.google.com/document/d/1j0jcJ9EoXMGzwAA2H0b9TOvRtpwlxI5Dtn3sRtuXQas/edit#heading=h.b1yk4ued1pxo

주의! 스프링 부트 3.2 파라미터 이름 인식 문제

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

발생하는 예외

java.lang.IllegalArgumentException: Name for argument of type [java.lang.String] not specified, and parameter name information not found in class file either.

 

주로 다음 두 애노테이션에서 문제가 발생한다.

@RequestParam, @PathVariable

@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) {

   ...

}

 

해결 방안1

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

@RequestParam("username") String username

@PathVariable("userId") String userId

 

해결 방안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이 컴파일 시점에 해당 옵션을 자동으로 적용해준다.

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

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

 

감사합니다.

안녕하세요 영한님

설명해주신 해결방안들 잘 읽어 보았는데

해결방안 1을 다른 해결방안보다 권장해주신 이유가 궁금합니다!!

 

김영한님의 프로필

김영한

지식공유자

24.01.13 19:24

안녕하세요. villa95님 해결3을 권장하도록 변경했습니다.

해결1이 좋은 이유는 자바 컴파일 상황과 무관하게 항상 작동하기 때문입니다.

그런데 스프링 3.2에서 관련된 이슈가 이것 뿐만 아니라 너무 많아서 해결 3을 사용하는 것을 권장합니다.

감사합니다.

0

codesweaver님의 프로필

codesweaver

23.11.29 21:10

안녕하세요. co-account님, 공식 서포터즈 코즈위버입니다.

도움을 드리고 싶지만 질문 내용만으로는 답변을 드리기 어렵습니다.

실제 동작하는 전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx


주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요


추가로 다음 내용도 코멘트 부탁드립니다.

1. 문제 영역을 실행할 수 있는 방법

2. 문제가 어떻게 나타나는지에 대한 상세한 설명

감사합니다.

co-account님의 프로필

co-account

질문자

23.11.29 21:39

https://drive.google.com/file/d/1UFCLpIaWds7UPQoe0BT1o2kC66r1Be7z/view?usp=sharing

  1. Spring boot 로 ItemServiceApplication 실행 후 http://localhost:8080/basic/items 에서 상품명 혹은 ID 클릭.

  2. java.lang.IllegalArgumentException: Name for argument of type [java.lang.Long] not specified, and parameter name information not found in class file either 에러 발생

Jaehak Park님의 프로필

Jaehak Park

23.11.29 22:52

settings - gradle에서 build and run 설정이 gradle이실까요?

제가 겪은 문제랑 같으신 것 같네요

co-account님의 프로필

co-account

질문자

23.11.30 00:45

원래는 세팅이 IntelliJ IDEA 였는데 Gradle 로 바꾸니 해결됐네요. 감사합니다. 혹시 IntelliJ IDEA 로 세팅하면 왜 안되는지 아시나요?

Jaehak Park님의 프로필

Jaehak Park

23.11.30 09:03

다행입니다

저도 이부분이 왜 안되는진 모르겠으나

intellij에서는 pathvariable 어노테이션을 시용하였을때 컴파일시 자동으로 인식하지 못하는 문제가 있는것 같네요

sylimi2r2님의 프로필

sylimi2r2

23.11.30 13:19

https://github.com/spring-projects/spring-boot/issues/38536

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

위의 두 링크 들어가 보시면 스프링 부트 3.2.0부터 컴파일 argument를 추가해야 한다고 하네요.

저는 그냥 build.gradle 파일의

 

plugins { 
    id 'java' 
    id 'org.springframework.boot' version '3.1.5' 
    id 'io.spring.dependency-management' version '1.1.4'
}

 

스프링 부트 버전을 3.1.5로 수정해서 컴파일했더니 해결되었습니다.

sylimi2r2님의 프로필

sylimi2r2

23.11.30 16:31

조금 더 찾아보니 스프링 부트 3.2.0부터 -parameters 라는 자바 컴파일 옵션을 설정해야 파라미터 이름을 생략할 수 있나 보네요.

intellij idea로 build 시 -parameters 옵션이 설정되어 있지 않기 때문에 안되는 것이고

gradle로 build 시에는 -parameters 옵션이 자동 설정되어서 따로 build.gradle에 따로 등록하지 않아도 되는 것 같습니다.

Jaehak Park님의 프로필

Jaehak Park

23.11.30 16:54

혹시 -parameter 옵션이라는게 아래의 코드 말씀하시는걸까요??

제가 아래코드 build.gradle에 추가하였을때에도 정상작동을 하지 않아서 그러는데 확인한번 부탁드려도 될까요?

 

compileJava { options.compilerArgs << '-parameters' }

 

 

sylimi2r2님의 프로필

sylimi2r2

23.11.30 17:03

build and run 이 intellij idea로 설정되어 있으면 build.gradle의 컴파일 옵션이 적용이 안되더라고요

build and run 을 gradle로 해야 적용이 되는데 gradle 2.x 버전 이후부터 -parameter 옵션이 자동 적용되어 있어서 위의 옵션을 추가하지 않아도 되네요.

Jaehak Park님의 프로필

Jaehak Park

23.11.30 17:14

그럼 결국 build를 gradle로 하거나

말씀해주신 것 처럼 부트버전을 낮추거나인 거네요? .. 감사합니다

sylimi2r2님의 프로필

sylimi2r2

23.11.30 17:17

build를 gradle로 하니까 영한 님이 말씀하신 것처럼 꽤 느려서 부트 버전을 그냥 낮추는 게 마음 편할 것 같아요 :)