@PathVariable에 대한 기술 블로그 정리

이동영·2024년 3월 15일
0

스프링

목록 보기
17/17

@PathVariable은 요청 URI 매핑에서 템플릿 변수를 처리하고 이를 메서드 매개변수로 설정하는데 사용된다.

무슨말일 까?

  • 웹 애플리케이션에서 사용자 요청 정보를 처리할 때 URI(Uniform Resource Identifier, 전체 자원 식별자)를 이용한다.
  • 이 URI에는 고정적인 부분과 변하는 부분이 함께 존재할 수 있다.
  • 고정적인 부분 : 자원의 종류를 나타내는 부분으로 /users는 사용자 정보를 나타내는 자원이다.
  • 변하는 부분 : 특정 자원을 구별하는 데, 사욛되는 부분이다. 예를들어 /users/{id}에서 {id}는 특정 사용자를 식별하는 데 사용되는 변하는 부분이다.
  • @PathVariable은 URI의 변하는 부분을 템플릿 변수라고 부르며, 이 변수를 매서드의 매개변수로 받을 수 있게 해준다.
  • 예를 들아, /users/{id}와 같은 URI가 있으면 {id}는 템플릿 변수이다.

@PathVariable는 URI의 변하는 부분을 이용하여 엔티티의 주요 키 값을 메서드의 입력값으로 받을 수 있게 해준다.

@GetMapping("/api/employees/{id}")
@ResponseBody
public String getEmployeesById(@PathVariable String id) {
    return "ID: " + id;
}

이 예제에서는 @PathVariable을 사용하여 {id}에서 값을 추출하여 매개변수에 주입한다.

다음 결과는 /api/employees/111 로 요청을 하였을 때 위의 예제에서 return되는 값을 출력한 결과이다.

http://localhost:8080/api/employees/111 
---- 
ID: 111

api/employees/111 중에서 111은 {id}를 통하여 값을 받아 매개변수인 String id에 주입하여 id변수를 출력한 결과는 ID: 111이다.

@PathVariable 이름지정

이전 예제에서는 매개변수와 @PathVariable dml {id} 가 동일하여 템플린 경로 변수의 이름 정의를 건너뛰었다. 하지만 경로 변수 이름이 과 매개변수 이름이 다른경우 @PathVariable에 속성으로 이름을 지정할 수 있다.

@GetMapping("/api/employeeswithvariable/{id}")
@ResponseBody
public String getEmployeesByIdWithVariableName(@PathVariable("id") String employeeId) {
    return "ID: " + employeeId;
}

좀더 명확하게 하기 위해 경로 변수 이름을 PathVariable(“id”) 대신 @PathVariable(value=”id”)로도 정의할 수 있다.

단일 요청의 다중 경로 변수

사용 사례에 따라서 컨트롤러 메서드에 대한 요청 URI에 둘 이상의 경로 변수가 들어있을 수 있다. 이 예제에는 URI에 여러개의 템플릿 변수가 있는 예제이다.

@GetMapping("/api/employees/{id}/{name}")
@ResponseBody
public String getEmployeesByIdAndName(@PathVariable String id, @PathVariable String name) {
    return "ID: " + id + ", name: " + name;
}
http://localhost:8080/api/employees/1/bar 
---- 
ID: 1, name: bar

Map형식인 MapM<String,String> 형태의 매개변수를 사용하여 둘 이상의 @PathVariable을 사용할 수 있다.

@GetMapping("/api/employeeswithmapvariable/{id}/{name}")
@ResponseBody
public String getEmployeesByIdAndNameWithMapVariable(@PathVariable Map<String, String> pathVarsMap) {
    String id = pathVarsMap.get("id");
    String name = pathVarsMap.get("name");
    if (id != null && name != null) {
        return "ID: " + id + ", name: " + name;
    } else {
        return "Missing Parameters";
    }
}
http://localhost:8080/api/employees/1/bar 
---- 
ID: 1, name: bar

http://localhost:8080/api/employees/1/bar 로 입력한 경우 1은 {id} 파라미터가 담당하고 bar는 {name}변수가 담당하였다. 그래서 String타입 변수인 id에 pathVarsMap.get("id")로 파라미터로 받은 값을 꺼내 초기화 하며 name도 마찬가지 이다. 그랬더니 예제의 밑에 출력결과인 ID: 1, name: bar처럼 받아지는것을 확인할 수 있다.

하지만 경로 변수에 문자열이 아닌 도트(.)가 찍힌경우 @PathVariable 매개변수를 처리하는 동안 에러가 발생할 수 있다. 이에 대한 문제는 https://www.baeldung.com/spring-mvc-pathvariable-dot여기서 확인할 수 있다.

선택적 경로 변수(Optional Path Variables)

spring에서는 기본적으로 @PathVariable 어노테이션이 달린 메서드 매개변수가 필요하다

@GetMapping(value = { "/api/employeeswithrequired", "/api/employeeswithrequired/{id}" })
@ResponseBody
public String getEmployeesByIdWithRequired(@PathVariable String id) {
    return "ID: " + id;
}

위 컨트롤러는 /api/employeeswithrequired 및 /api/employeeswithrequired/1 요청 경로를 모두 처리해야 한다. 그러나 @PathVariables 어노테이션이 붙은 메소드 매개변수는 기본적으로 필수처리 이기 때문에 /api/employees로 전송된 요청을 처리하지 않습니다.

http://localhost:8080/api/employeeswithrequired 
---- 
{"timestamp":"2020-07-08T02:20:07.349+00:00","status":404,"error":"Not Found","message":"","path":"/api/employeeswithrequired"} 

http://localhost:8080/api/employeeswithrequired/1 
---- 
ID: 111

하지만 이것을 2가지의 방법으로 해결할 수 있다.

@PathVariable가 필수가 아니라고 셋팅

@PathVariable에 필수 속성을 false라고 설정할 수 있다. 따라서 수정된 예제에서는 경로 변수가 있거나 없어도 두가지의 URI를 처리할 수 있다.

@GetMapping(value = { "/api/employeeswithrequiredfalse", "/api/employeeswithrequiredfalse/{id}" })
@ResponseBody
public String getEmployeesByIdWithRequiredFalse(@PathVariable(required = false) String id) {
   if (id != null) {
       return "ID: " + id;
   } else {
       return "ID missing";
   }
}
http://localhost:8080/api/employeeswithrequiredfalse 
---- 
ID missing

해당 결과는 경로 변수에 id를 지정하지 않으면 기본 응답을 얻을 수 있다.

메소드 파라미터에 Map<Stirng,String>의 형태로 사용

앞의 예제에서 본것처럼 java.Util.Map 유형의 단일 메소드 매개변수를 사용하여 요청 URI의 모든 경로 변수를 처리할 수 있다. 또한 이 방법을 사용하여 선택적으로 경로 변수를 처리할 수 있다.

@GetMapping(value = { "/api/employeeswithmap/{id}", "/api/employeeswithmap" })
@ResponseBody
public String getEmployeesByIdWithMap(@PathVariable Map<String, String> pathVarsMap) {
    String id = pathVarsMap.get("id");
    if (id != null) {
        return "ID: " + id;
    } else {
        return "ID missing";
    }
}

@PathVariable의 기본값

기본적으로 @PathVariable 어노테이션이 달린 메서드 매개변수의 기본값을 정의하는 조항이 없다. 하지만 위에서 설명한 것과 동일한 방법을 사용하여 @PathVariable의 기본값을 지정할 수 있다. 경로 변수에서 Null체크만 하면 된다.

각 인스턴스에 Map<Stirng,String>을 사용하여 경로변수가 Null혹은 NotNull인지 체크하여 Null인 경우 기본값을 설정하여 응답할 수 있다.

@GetMapping(value = { "/api/defaultemployeeswithoptional", "/api/defaultemployeeswithoptional/{id}" })
@ResponseBody
public String getDefaultEmployeesByIdWithOptional(@PathVariable Optional<String> id) {
    if (id.isPresent()) {
        return "ID: " + id.get();
    } else {
        return "ID: Default Employee";
    }
}

isPresent() 메소드

  • Boolean 타입

  • Optional 객체가 값을 가지고 있다면 true, 값이 없다면 false 리턴

profile
가치를 제공하는 개발자

0개의 댓글