@PathVariable, @RequestParam, @ModelAttribute, @RequestBody, @Vaild, @JsonInclude
Spring์์ ์ธ๋ถ ์์ฒญ์ผ๋ก ์ธ์ ๋๋ ๊ฐ๋ค
Spring์์๋ ํด๋ผ์ด์ธํธ๊ฐ HTTP ์์ฒญ์ ํตํด ์ ๋ฌํ ๋ฐ์ดํฐ๋ฅผ ๋ค์ํ ๋ฐฉ์์ผ๋ก ์ปจํธ๋กค๋ฌ์ ์ ๋ฌํ ์ ์๋ค.
๊ฐ ์์ฒญ๋ง๋ค ๋ฐ์ดํฐ์ ์ฒ๋ฆฌ ๋ฐฉ์์ด ๋ฌ๋ผ์ง๊ณ , ๊ทธ์ ๋ฐ๋ผ Model์ด๋ View๋ ๋ค์ํด์ง ์ ์๋ค. Spring์์ ์์ฒญ๊ฐ์ ์ฒ๋ฆฌํ๋ ์ฃผ์ ์ด๋ ธํ ์ด์ ์ ๋ํด ์์๋ณด๋๋ก ํ์.
@PathVaribale: /api/users/{id}
@PathVariable์ URL ๊ฒฝ๋ก์์ ๋์ ์ผ๋ก ๊ฐ์ ์ถ์ถํ ๋ ์ฌ์ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์์ ID๋ ํน์ ๋ฆฌ์๋์ ๋ํ ๊ณ ์ ๊ฐ์ URL ๊ฒฝ๋ก์์ ์ง์ ์ถ์ถํ ์ ์๋ค.
package com.example.demo.controller;
import com.example.demo.service.User;
import com.example.demo.service.UserServiceInterface;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
@RequestMapping("/users")
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class UserController {
UserServiceInterface userService;
@Autowired
private ApplicationContext applicationContext;
@GetMapping("/bean")
@ResponseBody
public String bean() {
return applicationContext.getBean(UserServiceInterface.class).toString();
}
@GetMapping("")
public String userPage(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "/users/list";
}
@GetMapping("/{id}/detail")
public String detailPage(@PathVariable Integer id, Model model) {
User user = userService.findById(id);
model.addAttribute("id", user.getId());
model.addAttribute("name", user.getName());
model.addAttribute("age", user.getAge());
model.addAttribute("job", user.getJob());
model.addAttribute("specialty", user.getSpecialty());
return "/users/detail";
}
@GetMapping("/{id}/data")
@ResponseBody
public User detailData(@PathVariable Integer id) {
User user = userService.findById(id);
return user;
}
}
- ์ ์ฝ๋์์ @PathVariable์ ์ฌ์ฉํ์ฌ ๋์ ์ผ๋ก URl์์ ์ฌ์ฉ์ ID๋ฅผ ๋ฐ์ ์ฌ์ฉํ๊ณ ์๋ค. ์๋ฅผ ๋ค์ด /users/1/detail ๊ฐ์ ์์ฒญ์ด ๋ค์ด์ค๋ฉด, @PathVariable์ ํตํด ID ๊ฐ์ ๋ฐ์ ํด๋น ์ฌ์ฉ์์ ์์ธ ์ ๋ณด๋ฅผ ์กฐํํ์ฌ ๋ฐํํ๋ค.
- ํด๋น ID๋ฅผ ๊ธฐ๋ฐ์ผ๋ก userService.findById(id) ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค.
- ๋ง์ฝ @PathVariable์ ์ฌ์ฉํ ๋ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๋ฉด, value์ต์
์ ์ถ๊ฐํ์ฌ ๋ณ์๋ช
์ ๋ช
ํํ ์ง์ ํด์ผํ๋ค.
- `@PathVariable Integer id` → `@PathVariable("id") Integer id`
@RequestParam: ?key=value
@RequestParam์ URL์ ๋ถ๋ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฒ๋ฆฌํ๋๋ฐ ์ฌ์ฉ๋๋ค. ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ ์ผ๋ฐ์ ์ผ๋ก ํน์ ๊ฒ์ ์กฐ๊ฑด์ด๋ ํํฐ๋ง ์กฐ๊ฑด์ ์ ๋ฌํ ๋ ์ฌ์ฉ๋๋ค.
package com.example.demo.controller;
import com.example.demo.service.User;
import com.example.demo.service.UserServiceInterface;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
@RequestMapping("/users")
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class UserController {
UserServiceInterface userService;
@Autowired
private ApplicationContext applicationContext;
// ApplicationContext์์ UserService Bean ํ์ธ
@GetMapping("/bean")
@ResponseBody
public String bean() {
return applicationContext.getBean(UserServiceInterface.class).toString();
}
// ์ ์ฒด ์ฌ์ฉ์ ๋ชฉ๋ก์ ์กฐํํ์ฌ ๋ฆฌ์คํธ ํ์ด์ง ๋ฐํ
@GetMapping("")
public String userPage(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "/users/list";
}
// ํน์ ์ฌ์ฉ์ ์์ธ ์ ๋ณด๋ฅผ ์กฐํํ์ฌ ๋ทฐ์ ์ ๋ฌ
@GetMapping("/detail")
public String detailPage(@RequestParam Integer id, Model model) {
User user = userService.findById(id);
model.addAttribute("id", user.getId());
model.addAttribute("name", user.getName());
model.addAttribute("age", user.getAge());
model.addAttribute("job", user.getJob());
model.addAttribute("specialty", user.getSpecialty());
return "/users/detail";
}
// ํน์ ์ฌ์ฉ์ ์์ธ ์ ๋ณด๋ฅผ JSON ํ์์ผ๋ก ๋ฐํ
@GetMapping("/data")
@ResponseBody
public User detailData(@RequestParam Integer id) {
User user = userService.findById(id);
return user;
}
}
- @RequestParam์ URL์์ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ๋ ๊ฐ์ ๊ฐ์ ธ์ค๋ ๋ฐ ์ฌ์ฉ๋๋ค. ์๋ฅผ๋ค์ดhttp://localhost:8080/users/detail?id=1 ๊ฐ์ ์์ฒญ์ด ๋ค์ด์ค๋ฉด id ๊ฐ์ด ์ถ์ถ๋์ด ์๋น์ค ๋ฉ์๋๋ก ์ ๋ฌ๋๋ค
- @RequestParam Integer id: ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ๋ id ๊ฐ์ ์ถ์ถํ๋ค.
- ์์ ์์ฒญ: http://localhost:8080/users/detail?id=3
@ReqeustParam ์ฌ์ฉ ์ ํ์ฅ ์ฌ์ฉ ๊ฐ๋ฅํ ์ต์ ๋ค
- ํ์ / ๋นํ์ ์ฌ๋ถ: `@RequestParam(required = false)
- ๊ธฐ๋ณธ๊ฐ ์ค์ : `@RequestParam(defaultValue = "์ํ๋ ๊ฐ์ String์ผ๋ก ๋ช ์")`
@ModelAttribue: ?key1=value&key2=value2
@ModelAttribute๋ ์ฌ๋ฌ ๊ฐ์ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ฒด๋ก ๋งคํํ ๋ ์ฌ์ฉํ๋ค. ์ฃผ๋ก ํผ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ฑฐ๋ ๋ค์์ ํ๋ผ๋ฏธํฐ๋ฅผ ํ ๋ฒ์ ๊ฐ์ฒด๋ก ๋ฐ์์ผ ํ ๋ ์ฌ์ฉ๋๋ค.
package com.example.demo.controller;
import com.example.demo.controller.dto.UserCreateRequestDto;
import com.example.demo.service.User;
import com.example.demo.service.UserServiceInterface;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
@RequestMapping("/users")
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class UserController {
UserServiceInterface userService;
@Autowired
private ApplicationContext applicationContext;
// ApplicationContext์์ UserService Bean ํ์ธ
@GetMapping("/bean")
@ResponseBody
public String bean() {
return applicationContext.getBean(UserServiceInterface.class).toString();
}
// ์ ์ฒด ์ฌ์ฉ์ ๋ชฉ๋ก์ ์กฐํํ์ฌ ๋ฆฌ์คํธ ํ์ด์ง ๋ฐํ
@GetMapping("")
public String userPage(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "/users/list";
}
// ํน์ ์ฌ์ฉ์ ์์ธ ์ ๋ณด๋ฅผ ์กฐํํ์ฌ ๋ทฐ์ ์ ๋ฌ
@GetMapping("/detail")
public String detailPage(@RequestParam Integer id, Model model) {
User user = userService.findById(id);
model.addAttribute("id", user.getId());
model.addAttribute("name", user.getName());
model.addAttribute("age", user.getAge());
model.addAttribute("job", user.getJob());
model.addAttribute("specialty", user.getSpecialty());
return "/users/detail";
}
// ํน์ ์ฌ์ฉ์ ์์ธ ์ ๋ณด๋ฅผ JSON ํ์์ผ๋ก ๋ฐํ
@GetMapping("/data")
@ResponseBody
public User detailData(@RequestParam Integer id) {
User user = userService.findById(id);
return user;
}
// ์๋ก์ด ์ฌ์ฉ์ ์ ์ฅ
@RequestMapping(value = "", method = RequestMethod.POST)
@ResponseBody
public User save(@ModelAttribute UserCreateRequestDto request) {
User user = userService.save(request.getName(), request.getAge(), request.getJob(), request.getSpecialty());
return user;
}
}
- @ModelAttribute UserCreateRequestDto request: ์ฌ๋ฌ ๊ฐ์ ์์ฒญ ํ๋ผ๋ฏธํฐ๊ฐ UserCreateRequestDto ๊ฐ์ฒด๋ก ์๋ ๋งคํ๋๋ค. ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ๋ค์ด DTO ๊ฐ์ฒด์ ํ๋๋ก ์๋์ผ๋ก ๋งคํ๋๋ค.
UserCreateReqeustDto ํด๋์ค:
package com.example.demo.controller.dto;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class UserCreateRequestDto {
private String name;
private Integer age;
private String job;
private String specialty;
}
- ์ฃผ์: ์์ฒญ ๊ฐ์ฒด ํด๋์ค์ ์๋ Lombok์ด ์๋ค๋ฉด ์ญ์ง๋ ฌํ๊ฐ ๋์ง ์์ ๊ฐ์ด ์ ๋๋ก ๋ค์ด์ค์ง ์๋๋ค.
- @AllArgsConstructor
- @NoArgsConstructor + @Setter ← ๊ธฐ๋ณธ๊ฐ์ด ์ค์ ๊ฐ๋ฅํ ์ด ๋ฐฉ๋ฒ์ ๋ ์ ํธํ๋ค.
ํ ์คํธ ์์:
- ์ ์ฒด ์ฌ์ฉ์ ์กฐํ:
- URL: http://localhost:8080/users
- ํน์ ์ฌ์ฉ์ ์กฐํ (๋ทฐ ๋ฐํ):
- URL: http://localhost:8080/users/detail?id=1
- ํน์ ์ฌ์ฉ์ ์กฐํ(JSON ๋ฐํ):
- URL: http://localhost:8080/users/data?id=1
- ์ ์ฌ์ฉ์ ์์ฑ:
- URL: http://localhost:8080/users
- HTTP ๋ฉ์๋: POST
- ํ๋ผ๋ฏธํฐ: name, age, job, specialty
- ์์: http://lcoalhost:8080/users?name=cheonsang&age=20&job=developer&specialty=backend
@ReqeustBody: JSON { property: 'value' }
@ReqeustBody๋ ์์ฒญ ๋ณธ๋ฌธ(body)์์ ๋ฐ์ดํฐ๋ฅฟ ใ ใท์ ์ฒ๋ฆฌํ๋ค. ์ฃผ๋ก ํด๋ผ์ด์ธํธ์์ JSON ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์กํ ๋ ์ฌ์ฉ๋๋ฉฐ, POST ์์ฒญ๊ณผ ํจ๊ป ๋ง์ด ์ฌ์ฉ๋๋ค.
package com.example.demo.controller;
import com.example.demo.controller.dto.UserCreateRequestDto;
import com.example.demo.service.User;
import com.example.demo.service.UserServiceInterface;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
@RequestMapping("/users")
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class UserController {
UserServiceInterface userService;
@Autowired
private ApplicationContext applicationContext;
// ApplicationContext์์ UserService Bean ํ์ธ
@GetMapping("/bean")
@ResponseBody
public String bean() {
return applicationContext.getBean(UserServiceInterface.class).toString();
}
// ์ ์ฒด ์ฌ์ฉ์ ๋ชฉ๋ก์ ์กฐํํ์ฌ ๋ฆฌ์คํธ ํ์ด์ง ๋ฐํ
@GetMapping("")
public String userPage(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "/users/list";
}
// ํน์ ์ฌ์ฉ์ ์์ธ ์ ๋ณด๋ฅผ ์กฐํํ์ฌ ๋ทฐ์ ์ ๋ฌ
@GetMapping("/detail")
public String detailPage(@RequestParam Integer id, Model model) {
User user = userService.findById(id);
model.addAttribute("id", user.getId());
model.addAttribute("name", user.getName());
model.addAttribute("age", user.getAge());
model.addAttribute("job", user.getJob());
model.addAttribute("specialty", user.getSpecialty());
return "/users/detail";
}
// ํน์ ์ฌ์ฉ์ ์์ธ ์ ๋ณด๋ฅผ JSON ํ์์ผ๋ก ๋ฐํ
@GetMapping("/data")
@ResponseBody
public User detailData(@RequestParam Integer id) {
User user = userService.findById(id);
return user;
}
// ์๋ก์ด ์ฌ์ฉ์ ์ ์ฅ
@RequestMapping(value = "", method = RequestMethod.POST)
@ResponseBody
public User save(@RequestBody UserCreateRequestDto request) {
User user = userService.save(request.getName(), request.getAge(), request.getJob(), request.getSpecialty());
return user;
}
}
- @RequestBody UserCreateRequestDto request: ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ์ ๋ฌ๋ JSON ํ์์ ๋ฐ์ดํฐ๋ฅผ UserCreateRequestDto ๊ฐ์ฒด๋ก ๋ณํํ์ฌ ์ปจํธ๋กค๋ฌ ๋ฉ์๋๋ก ์ ๋ฌํ๋ค.
ํ ์คํธ ์์
- ์ ์ฌ์ฉ์ ์์ฑ:
- URL: http://localhost:8080/users
- HTTP ๋ฉ์๋: POST
- Contenty-Type: application/json
- ์์ฒญ ๋ณธ๋ฌธ ์์ (JSON):
{
"name": "cheosange",
"age": 20,
"job": "Developer",
"specialty": "Backend"
}
Spring์์์ ์์ฒญ๊ฐ ์ ํจ์ฑ ๊ฒ์ฆ: @Valid, @Validated
Spring์์๋ ํด๋ผ์ด์ธํธ๊ฐ ์ ์กํ ์์ฒญ๊ฐ์ ์ ํจ์ฑ์ ๊ฒ์ฆํ ์ ์๋ค. ์ฃผ์ ์ด๋ ธํ ์ด์ ์ผ๋ก @Valid์ @Validated๊ฐ ์๋ค.
- @Valid: Java ํ์ค ์ ํจ์ฑ ๊ฒ์ฆ ์ด๋ ธํ ์ด์ ์ผ๋ก, ์์ฒญ ํ๋ผ๋ฏธํฐ์ ๋ํ ๊ธฐ๋ณธ์ ์ธ ๊ฒ์ฆ์ ์ ๊ณตํ๋ค.
- @Validated: Spring์์ ์ ๊ณตํ๋ ์ ํจ์ฑ ๊ฒ์ฆ ์ด๋ ธํ ์ด์ ์ผ๋ก, ์ข ๋ ๋ณต์กํ ๊ฒ์ฆ์ ์ํํ ์ ์๋ค.
ํ์์กฐ๊ฑด: `build.gradle`์ ๋ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํด์ผํ๋ค.
implementation 'org.springframework.boot:spring-boot-starter-validation'
UserController.java
package com.example.demo.controller;
import com.example.demo.controller.dto.UserCreateRequestDto;
import com.example.demo.service.User;
import com.example.demo.service.UserServiceInterface;
import jakarta.validation.Valid;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
@RequestMapping("/users")
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class UserController {
UserServiceInterface userService;
@Autowired
private ApplicationContext applicationContext;
@GetMapping("/bean")
@ResponseBody
public String bean() {
return applicationContext.getBean(UserServiceInterface.class).toString();
}
@GetMapping("")
public String userPage(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "/users/list";
}
@GetMapping("/detail")
public String detailPage(@RequestParam Integer id, Model model) {
User user = userService.findById(id);
model.addAttribute("id", user.getId());
model.addAttribute("name", user.getName());
model.addAttribute("age", user.getAge());
model.addAttribute("job", user.getJob());
model.addAttribute("specialty", user.getSpecialty());
return "/users/detail";
}
@GetMapping("/data")
@ResponseBody
public User detailData(@RequestParam Integer id) {
User user = userService.findById(id);
return user;
}
// @Valid๋ฅผ ์ฌ์ฉํ์ฌ ์์ฒญ ๋ฐ์ดํฐ์ ์ ํจ์ฑ ๊ฒ์ฆ
@PostMapping("")
@ResponseBody
public User save(@RequestBody @Valid UserCreateRequestDto request) {
User user = userService.save(request.getName(), request.getAge(), request.getJob(), request.getSpecialty());
return user;
}
}
- save() ๋ฉ์๋์์ @Valid๋ฅผ ์ฌ์ฉํ์ฌ UserCreateRequestDto ํ๋ ๊ฒ์ฆ์ ์ํํ๋ค.
- ์์ฒญ์ ํฌํจ๋ ๋ฐ์ดํฐ๊ฐ ๊ฒ์ฆ ์กฐ๊ฑด์ ๋ง์กฑํ์ง ์์ผ๋ฉด, Spring์์ ์๋์ผ๋ก 400 Bad Reqeust ์๋ต์ ๋ฐํํ๋ค.
UserCreateRequestDto.java
package com.example.demo.controller.dto;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class UserCreateRequestDto {
// ์ด๋ฆ์ ๋น ๊ฐ์ผ ์ ์๋ค
@NotBlank
private String name;
// ๋์ด๋ ์ต์ 10์ด์ด์ผ ํ๋ค
@Min(10)
private Integer age;
// ์ง์
์ ๋ฐ๋์ ์์ด์ผ ํ๋ค
@NotNull
private String job;
// ํน๊ธฐ๋ ์ ํ์ฌํญ, ๊ธฐ๋ณธ๊ฐ์ "(empty)"
private String specialty = "(empty)";
}
- ํ๋์ ๊ฒ์ฆ ์ด๋ ธํ ์ด์ ์ ์ ์ฉํ์ฌ ๊ฐ ํ๋์ ์ ํจ์ฑ ์กฐ๊ฑด์ ์ค์ ํ๋ค.
- ์ด๋ฆ์ด ๋น์ด ์์ผ๋ฉด ์๋๊ณ , ๋์ด๋ ์ต์ 10์ด์ ์ด์ด์ผํ๋ฉฐ, ์ง์ ์ null์ผ ์ ์๋ค.
์ฃผ์ ๊ฒ์ฆ ์ด๋ ธํ ์ด์ :
- @NotBlank: ํ๋๊ฐ null, ๋น ๋ฌธ์์ด, ๊ณต๋ฐฑ ๋ฌธ์ ๋ ์๋ ๊ฒฝ์ฐ ํ์ฉํ์ง ์์.
- @Min(value): ํ๋์ ์ต์๊ฐ์ ์ง์
- @NotNull: ํ๋๊ฐ ๋ฐ๋์ null์ด ์๋์ฌ์ผํจ.
ํ ์คํธ ์์:
1. ์ ํจํ ๋ฐ์ดํฐ๋ก ์์ฒญ:
- URL: http://localhost:8000/users
- HTTP ๋ฉ์๋: POST
- Content-Type: application/json
- ์์ฒญ ๋ณธ๋ฌธ:
{
"name": "CheonSang",
"age": 20,
"job": "Developer"
}
- ์๋ต ๋ณธ๋ฌธ:
{
"id": 1,
"name": "CheonSang",
"age": 20,
"job": "Developer",
"specialty": "(empty)"
}
2. ์ ํจํ์ง ์์ ๋ฐ์ดํฐ๋ก ์์ฒญ(์ด๋ฆ X):
- ์์ฒญ ๋ณธ๋ฌธ:
{
"name": "",
"age": 20,
"job": "Developer"
}
- ์๋ต: 400 Bad Request
{
"status": 400,
"error": "Bad Request",
"message": "Validation failed for object='userCreateRequestDto'. Error count: 1"
}
3. ์ ํจํ์ง ์์ ๋ฐ์ดํฐ๋ก ์์ฒญ (๋์ด๊ฐ 10 ๋ฏธ๋ง):
- ์์ฒญ ๋ณธ๋ฌธ:
{
"name": "CheonSang",
"age": 5,
"job": "Developer"
}
- ์๋ต: 400 Bad Request
{
"status": 400,
"error": "Bad Request",
"message": "Validation failed for object='userCreateRequestDto'. Error count: 1"
}
4. ์ ํจํ์ง ์์ ๋ฐ์ดํฐ๋ก ์์ฒญ (์ง์ ์ด null):
- ์์ฒญ ๋ณธ๋ฌธ:
{
"name": "CheonSang",
"age": 30,
"job": null
}
- ์๋ต: 400 Bad Requeest
{
"status": 400,
"error": "Bad Request",
"message": "Validation failed for object='userCreateRequestDto'. Error count: 1"
}
Spring ์๋ต ์ธ๋ถ ์กฐ์จ: @JsonInclude
@JsonInclude๋ ์๋ต์ผ๋ก ๋ฐํ๋ JSON ๋ฐ์ดํฐ์์ null ๊ฐ์ ํฌํจํ ์ง ์ ์ธํ ์ง๋ฅผ ์ค์ ํ ์ ์๋ ์ด๋ ธํ ์ด์ ์ด๋ค. ์๋ฅผ ๋ค์ด, ๊ฐ์ด null์ธ ํ๋๋ JSON ์๋ต์ ํฌํจ๋์ง ์๋๋ก ์ค์ ํ ์ ์๋ค.
package com.example.demo.controller.dto;
import com.example.demo.service.User;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor(access = AccessLevel.PACKAGE)
public class UserResponseDto {
private Integer id;
private String name;
private Integer age;
private String job;
private String specialty;
// null์ธ ๊ฒฝ์ฐ JSON ์๋ต์์ ์ ์ธ
@JsonInclude(JsonInclude.Include.NON_NULL)
private String address;
// null์ธ ๊ฒฝ์ฐ JSON ์๋ต์์ ์ ์ธ
@JsonInclude(JsonInclude.Include.NON_NULL)
private String postcode;
// User ์ํฐํฐ๋ก๋ถํฐ UserResponseDto๋ก ๋ณํ
public static UserResponseDto from(User entity) {
return new UserResponseDto(
entity.getId(),
entity.getName(),
entity.getAge(),
entity.getJob(),
entity.getSpecialty(),
null, // Address๋ null๋ก ์ค์
null // Postcode๋ null๋ก ์ค์
);
}
}
- User ์ํฐํฐ๋ก๋ถํฐ ๋ฐ์ดํธ๋ฅผ ๋ฐ์ ์๋ต์ ์ํ DTO๋ก ๋ณํํ๋ค.
- address์ postcode๋ null์ผ ์ ์์ผ๋ฉฐ, null์ธ ๊ฒฝ์ฐ ์๋ต์ ํฌํจ๋์ง ์๋๋ค.
ํ ์คํธ ์์:
1. ์ฃผ์์ ์ฐํธ๋ฒํธ๊ฐ ์๋ ๊ฒฝ์ฐ:
- URL: http://localhost:8080/users/data?id=1
- ์์ฒญ์ด ๋ค์ด์ค๋ฉด, ์๋ต์ address์ postcode๋ ํ๋์ ํฌํจ๋์ง ์๋๋ค.
{
"id": 1,
"name": "CheonSang",
"age": 20,
"job": "Developer",
"specialty": "(empty)"
}
2. ์ฃผ์์ ์ฐํธ๋ฒํธ๊ฐ ์๋ ๊ฒฝ์ฐ(๊ฐ์ด ์๋ ๊ฒฝ์ฐ):
{
"id": 1,
"name": "cheonsang",
"age": 20,
"job": "Developer",
"specialty": "(empty)",
"address": "seoul",
"postcode": "56789"
}
ํ๋๊ฐ ์๋ ํด๋์ค(Dto) ๋จ์๋ก๋ ์ ์ฝ ์ ์ฉ์ด ๊ฐ๋ฅํ๋ค
package com.example.demo.controller.dto;
import com.example.demo.service.User;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserResponseDto {
private Integer id;
private String name;
private Integer age;
private String job;
private String specialty;
private String address;
private String postcode;
// User ์ํฐํฐ๋ฅผ UserResponseDto๋ก ๋ณํํ๋ ์ ์ ๋ฉ์๋
public static UserResponseDto from(User entity) {
return new UserResponseDto(
entity.getId(),
entity.getName(),
entity.getAge(),
entity.getJob(),
entity.getSpecialty(),
null, // address๋ null๋ก ์ค์
null // postcode๋ null๋ก ์ค์
);
}
}
โน๏ธ ์ฐธ๊ณ
[ASAC 6๊ธฐ ๊ฐ์์๋ฃ]
'๐ปDEV-STUDY > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] ์ค๋ฌด์์์ Best Practices #1 (0) | 2024.10.07 |
---|---|
[Spring] Spring Boot ์ฅ์ ๋ฐ ๋์ (0) | 2024.10.06 |
Spring Bean ์๋ฆฌ๊ณผ ์์กด์ฑ ์ฃผ์ (1) | 2024.10.06 |
[Spring]HttpMessageConverter (0) | 2024.10.06 |
[Spring] Controller ์ฒ๋ฆฌ ๋ฐํ (1) | 2024.10.05 |