<< 학습 목표 >>
1. 클라이언트가 보낸 값들을 꺼낼 수 있다.
2. 클라이언트가 보낸 JSON 데이터를 꺼낼 수 있다.
3. 파라미터를 선택사항으로 설정할 수 있다.
4. 파라미터의 기본값을 설정할 수 있다.
전 글 ( https://codingaja.tistory.com/104 ) 에서는 클라이언트가 보낸 값을 꺼내봤음
이번에는 전 글의 연장선으로 값들을 꺼내는 방법에 대해서 알아보자
뷰(웹 페이지)에 다음과 같이 체크 박스가 있다고 상상해보자
사용자가 체크한 값을 서버로 보내면 다음과 같이 서버로 보내짐
=> http://localhost:8080/컨트롤러URL?hobby=book&hobby=game
서블릿 컨트롤러에서는 요청 정보(HttpServletRequest) 에 getParameterValues 메서드로 꺼냈는데 Spring Framework는 어떻게 꺼낼 수 있을까?
프로젝트 -> com.example.demo.chapter02 -> TestController03 클래스를 추가하고 아래 코드를 추가하자
package com.example.demo.chapter02;
import java.util.Arrays;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class TestController03 {
@GetMapping("/chapter02/parameters")
public void paramters(String[] hobby) {
System.out.println("<< parameters 메서드 호출 >>");
System.out.println(Arrays.toString(hobby));
}
}
별도의 코드 설명이 필요 없을 정도로 간단함
클라이언트가 hobby 이름에 book, game 두 개의 값을 담아서 보내므로 서버에서는 매개변수의 타입을 배열로 선언하면 됨
프로젝트를 재실행 시킨 후 Postman 에서 아래와 같이 파라미터를 보내보자
자바에서 컬렉션 프레임워크를 배우며 배열 보다 컬렉션 프레임워크를 사용하는게 더 좋다고 배웠음
위와 같이 클라이언트가 hobby들을 보냈을 때 배열이 아닌 List 또는 ArrayList 컬렉션 프레임워크에 hobby들을 담으려면 어떻게 해야할까?
이때는 매개변수에 @RequestParam 애너테이션이 붙어야함
이번에는 다음과 같이 폼에서 회원 정보를 보냈을 때를 상상해보자
회원가입
서버에서는 클라이언트가 보낸 회원 정보를 다음과 같이 꺼낼 수 있을 것
( 바로 위에서 사용했던 컨트롤러에 join 메서드를 추가한 것 )
<< 컨트롤러 >>
package com.example.demo.chapter02;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class TestController03 {
@PostMapping("/chapter02/join")
public void join(String id, String pw, String nickname, String[] hobby) {
// ...
// ...
// 회원 가입
// ...
// ...
}
@GetMapping("/chapter02/parameters")
public void paramters(@RequestParam("hobby") List<String> hobby) {
System.out.println("<< paramters 메서드 호출 >>");
System.out.println(hobby);
}
}
<< 코드 설명 >>
위에서 사용자가 입력한 아이디는 id 매개변수에, 비밀번호는 pw 매개변수에, 닉네임은 nickname 매개변수에, 취미는 hobby 매개변수에 저장되 있음
이렇게 해서 회원 정보(데이터들)을 받을 수 있음
그러나 지금처럼 회원 정보가 흩어져있다면 일반적으로는 회원 정보를 하나로 합쳐서 사용함
하나로 합치기 위해 아래와 같이 Member 클래스를 선언하자
getter, setter 반드시 필요함 / 코드 길이 상 생략한 것
package com.example.demo.chapter02;
public class Member {
String id;
String pw;
String nickname;
String[] hobby;
public Member(String id, String pw, String nickname, String[] hobby) {
super();
this.id = id;
this.pw = pw;
this.nickname = nickname;
this.hobby = hobby;
}
// getter & setter 생략
}
<< 컨트롤러 >>
여기서 잠시 클라이언트가 보낸 정보를 하나로 합쳐 주는걸 클래스, 객체 라고 했지만 MVC 디자인 패턴에서는 M(Model)에 해당함
특히, M 에서도 DTO(Data Transfer Object) 라고 부름
왜 DTO인지는 이 불로그의 글들을 따라오면서 공부하다 보면 알게 됨
이 DTO를 바로 매개변수 자리에 쓸 수도 있음
DTO가 매개변수가 됐을 때는 DTO가 가지고 있는 멤버 변수의 이름과 일치하는 파라미터를 꺼내 멤버 변수에 저장함
프로젝트를 재실행 시키고 다음과 같이 요청을 보내보자
이번에도 hobby들을 배열에 담았는데 hobby들을 List 또는 ArrayList 컬렉션 프레임워크에 담으려면 어떻게 해야할까?
이때는 DTO의 매개변수 타입만 List 또는 ArrayList 로 바꿔주면 됨
클라이언트가 파라미터를 보낼 때 JSON으로 보내는 경우도 있음
클라이언트가 보낸 JSON을 받을 때는 매개변수에 @RequestBody 애너테이션을 붙이면 됨
컨트롤러를 위와 같이 수정 한 후 프로젝트를 재시작하자
Postman 으로 JSON 데이터를 보내보자
( 보내는 방법을 모른다면 https://codingaja.tistory.com/101 글을 참고하자 )
여기까지 클라이언트가 다양한 형태의 값을 보낼 때 컨트롤러에서 이를 꺼내는 방법을 배웠음
지금까지는 클라이언트가 반드시 값을 보낸다는 가정으로 컨트롤러에서 이를 꺼냈는데 클라이언트가 값을 보내지 않으면 어떻게 될까??
프로젝트 -> com.example.demo.chapter02 -> TestController04 클래스를 추가하고 아래 코드를 추가하자
package com.example.demo.chapter02;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class TestController04 {
@GetMapping("/chapter02/controller01")
public void controller01(int param1, double param2, char param3, boolean param4, String param5) {
System.out.println("<< controller01 메서드 호출 >>");
System.out.println("-- 클라이언트가 파라미터를 보내지 않았을 때 --");
System.out.println("param1 => " + param1);
System.out.println("param2 => " + param2);
System.out.println("param3 => " + param3);
System.out.println("param4 => " + param4);
System.out.println("param5 => " + param5);
}
}
프로젝트를 재시작하고 해당 컨트롤러로 접근하는데 파라미터를 아무것도 보내지 않고 접근해보자
클라이언트가 보낸 값을 꺼내기 위해 매개변수가 있는 컨트롤러에 파라미터를 보내지 않으면 아래와 같이 IllegalStateException 이 발생함
왜 이와 같은 예외가 발생하는 것일까?
단순히 클라이언트가 파라미터를 전달하지 않아서 예외가 발생하는건 아님
클라이언트가 매개변수가 있는 컨트롤러에 접근할 때 파라미터를 전달하지 않으면 Spring Framework는 컨트롤러의 매개변수 데이터 타입에 상관없이 매개변수에 null 을 저장함
매개변수 param1의 데이터 타입은 int 인데 int는 null 을 저장할 수 없으므로 InllegalStateException 이 발생하는 것
예외가 발생했으니 예외 처리를 해야할까? 그래도 되지만 @RequestParam 애너테이션을 사용하면 클라이언트가 파라미터를 반드시 보내도록 설정할 수도 있고 클라이언트가 파라미터를 보내지 않았을 때 해당 매개변수에 저장될 기본값을 설정할 수도 있음
먼저 @RequestParam 애너테이션을 사용해 클라이언트가 파라미터를 반드시 보내도록 설정하자
package com.example.demo.chapter02;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class TestController04 {
@GetMapping("/chapter02/controller01")
public void controller01(@RequestParam(name="param1", required=true) int param1,
@RequestParam(name="param2", required=true) double param2,
@RequestParam(name="param3", required=true) char param3,
@RequestParam(name="param4", required=true) boolean param4,
@RequestParam(name="param5", required=true) String param5) {
System.out.println("<< controller01 메서드 호출 >>");
System.out.println("-- 클라이언트가 파라미터를 보내지 않았을 때 --");
System.out.println("param1 => " + param1);
System.out.println("param2 => " + param2);
System.out.println("param3 => " + param3);
System.out.println("param4 => " + param4);
System.out.println("param5 => " + param5);
}
}
<< 코드 설명 >>
각 매개변수에 @RequestParam 애너테이션을 달고 이 애너테이션에 required 속성을 사용해 클라이언트가 파라미터를 반드시 보내도록 설정할 수 있음
전 글에서도 @RequestParam 애너테이션을 사용해봤지만 전 글에서 사용 방법과 달라졌음
(왼쪽) 전 글과 같이 @RequestParam 애너테이션에 속성명 없이 문자열을 넣으면 이름이 "name" 인 파라미터의 값을 꺼내 해당 매개변수에 저장하도록 하는 것
(오른쪽) 이번 글과 같이 @RequestParam 애너테이션에 name 속성에 문자열을 지정하면 이름이 "param1" 파라미터의 값을 꺼내 해당 매개변수에 저장하도록 할 수 있음
required 속성을 사용하면 클라이언트가 해당 파라미터는 반드시 전달해야하는지 아니면 보내고 싶을 때만 보내는 선택사항인지를 지정할 수 있음
requried 속성이 true면 클라이언트가 해당 파라미터를 반드시 전달해야하고 required 속성이 false면 해당 파라미터는 보내고 싶을 때 보내는 선택사항이 되도록 할 수 있음
이제 프로젝트를 재시작한 후 이 컨트롤러에 접근할 때 파라미터를 넣지 않고 접근해보자
반드시 보내야하는 파라미터로 설정했는데 보내지 않았으므로 MissingServletRequestParameterException 이 발생함
이때는 적절한 방법을 사용해 예외처리를 하면 됨
클라이언트가 파라미터를 보내고 싶을 때 보내는 선택사항으로 만들어보자
@RequestParam 애너테이션을 붙이지 않으면 해당 파라미터는 선택사항으로 됨
이 애너테이션을 붙여야한다면 다음과 같이 required 속성을 false 로 설정하면 됨
package com.example.demo.chapter02;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class TestController04 {
@GetMapping("/chapter02/controller02")
public void controller02(@RequestParam(name="param1", required=false) int param1,
@RequestParam(name="param2", required=false) double param2,
@RequestParam(name="param3", required=false) char param3,
@RequestParam(name="param4", required=false) boolean param4,
@RequestParam(name="param5", required=false) String param5) {
System.out.println("<< controller02 메서드 호출 >>");
System.out.println("-- 클라이언트가 파라미터를 보내지 않았을 때 --");
System.out.println("param1 => " + param1);
System.out.println("param2 => " + param2);
System.out.println("param3 => " + param3);
System.out.println("param4 => " + param4);
System.out.println("param5 => " + param5);
}
@GetMapping("/chapter02/controller01")
public void controller01(@RequestParam(name="param1", required=true) int param1,
@RequestParam(name="param2", required=true) double param2,
@RequestParam(name="param3", required=true) char param3,
@RequestParam(name="param4", required=true) boolean param4,
@RequestParam(name="param5", required=true) String param5) {
System.out.println("<< controller01 메서드 호출 >>");
System.out.println("-- 클라이언트가 파라미터를 보내지 않았을 때 --");
System.out.println("param1 => " + param1);
System.out.println("param2 => " + param2);
System.out.println("param3 => " + param3);
System.out.println("param4 => " + param4);
System.out.println("param5 => " + param5);
}
}
위와 같이 controller02 컨트롤러를 추가한 후 프로젝트를 재시작하고 해당 컨트롤러에 접근할 때 파라미터를 보내지 말아보자
예외 명은 다르지만 또 다시 예외가 발생함
왜이럴까? 왜 그런지는 위에서 이미 언급했음
클라이언트가 매개변수가 있는 컨트롤러에 접근할 때 파라미터를 전달하지 않으면 Spring Framework는 컨트롤러의 매개변수 데이터 타입에 상관없이 매개변수에 null 을 저장함
매개변수 param1의 데이터 타입은 int 인데 int는 null 을 저장할 수 없으므로 InllegalStateException 이 발생하는 것
결국은 required=true 일 때도 required=false 일 때도 클라이언트가 파라미터를 보내지 않으면 예외가 발생함
required=false 일 때 예외가 발생하지 않으려면 해당 매개변수에 기본값을 지정하면 됨
기본값은 defaultValue 속성으로 지정할 수 있음
다음과 같이 defaultValue 속성을 사용해 controller02 컨트롤러에 매개변수의 기본값을 설정하자
이제 클라이언트가 파라미터를 전달하지 않으면 해당 매개변수에는 설정된 기본값이 저장됨
이렇게 파라미터를 선택사항으로 지정하고 싶다면 required 속성은 false로 defaultValue 속성은 파라미터를 전달하지 않았을 때 저장될 기본값으로 지정해주면 됨
'Spring + Boot > Boot-Chapter02' 카테고리의 다른 글
Chapter02. Spring Boot - 롬복(Lombok) 사용하기 (0) | 2023.04.11 |
---|---|
Chapter02. Spring Boot - 클라이언트가 보낸 파일 꺼내기 (0) | 2023.04.11 |
Chapter02. Spring Boot - 클라이언트가 보낸 값 꺼내기 (0) | 2023.04.09 |
Chapter02. Spring Boot - 컨트롤러 만들기 (0) | 2023.04.09 |
Chapter02. Spring Boot - MVC 디자인 패턴 (0) | 2023.04.08 |