๐ ๋ชฉ์ฐจ
DTO๋ ๊ณ์ธต ๊ฐ ๋ฐ์ดํฐ ๊ตํ์ ํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๊ฐ์ฒด๋ก, DTO๋ ๋ก์ง์ ๊ฐ์ง์ง ์๋ ์์ํ ๋ฐ์ดํฐ ๊ฐ์ฒด(getter & setter ๋ง ๊ฐ์ง ํด๋์ค)์ ๋๋ค.
์์ฒญ ๋ฐ์ดํฐ์ ํ์์ ์ด๋ฆ, ์ด๋ฉ์ผ, ์ ํ๋ฒํธ, ์ฃผ์, ๋ก๊ทธ์ธ ํจ์ค์๋, ํจ์ค์๋ ํ์ธ ์ ๋ณด ๋ฑ๋ฑ๋ง์ ์ ๋ณด๋ค์ด ํ์ ์ ๋ณด์ ํฌํจ๋์ด ์์ ์ ์์ต๋๋ค.
์ด ์ ๋ณด๋ค์ ํ๋์ฉ postMember()์ ํ๋ผ๋ฏธํฐ๋ก ์ถ๊ฐํ๋ฉด @RequestParam์ ๊ฐ์๊ฐ ๋ง์์ง ๊ฒ ์
๋๋ค.
์ด๋ฐ ๊ฒฝ์ฐ์ DTO ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์์ฒญ ๋ฐ์ดํฐ๋ฅผ ํ๋์ ๊ฐ์ฒด๋ก ์ ๋ฌ ๋ฐ๋ ์ญํ ์ ํ์ฌ ์ฝ๋๊ฐ ๊ฐ๊ฒฐํด์ง๋๋ค.
์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๋ฐ์ดํฐ๊ฐ ์์์ ๋ง๊ฒ ์ ์ถ๋์๋์ง ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ฆํ๋ ๊ฒ์ ์ ํจ์ฑ(Validation)๊ฒ์ฆ์ด๋ผ๊ณ ํฉ๋๋ค. ์ ํจ์ฑ ๊ฒ์ฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๊ธฐ ์ ์ ๋จผ์ ๊ฒ์ฆํ๋๋ก ํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค. ์ด๋ฅผ ํตํด ์๋ชป๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐฉ์งํ๊ณ , ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ ์ ์์ต๋๋ค.
if (!email.matches("^[a-zA-Z0-9_!#$%&'\\*+/=?{|}~^.-]+@[a-zA-Z0-9.-]+$")) {
throw new InvalidParameterException();
}
์ด๋ ๊ฒ ์ง์ ์ฝ๋๋ฅผ ์จ์ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํ ์๋ ์์ง๋ง ํธ๋๋ฌ ๋ฉ์๋ ๋ด์ ์ ํจ์ฑ ๊ฒ์ฌ ์ฝ๋๊ฐ ์์ฌ์ ์ฝ๋์ ๋ณต์ก๋๊ฐ ๋์์ง๊ฒ ๋ฉ๋๋ค.
๋ฐ๋ผ์ DTO ํด๋์ค์์ ์ ํจ์ฑ ๊ฒ์ฆ ๋ก์ง์ ์ฌ์ฉํ๋ฉด ํธ๋ค๋ฌ ๋ฉ์๋๊ฐ ๊ฐ๊ฒฐํด์ง๋๋ค.
Java์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ javax.validation ํจํค์ง๋ฅผ ์ฌ์ฉํ์ฌ @NotNull, @Size, @Min, @Max ๋ฑ์ ์ด๋ ธํ ์ด์ ์ผ๋ก ๋ค์ํ ๊ฒ์ฆ ๊ท์น์ ์ค์ ํ๊ณ , ์คํ๋ง์์ ์ ๊ณตํ๋ Validator ์ธํฐํ์ด์ค๋ฅผ ์ด์ฉํด์ ์ ํจ์ฑ ๊ฒ์ฌ ๋ก์ง์ ์์ฑํ ์ ์์ต๋๋ค.
// build.gradle ํ์ผ์ validation๋ฅผ ์ถ๊ฐํ๊ณ ์ฝ๋ผ๋ฆฌ๋ฅผ ๋๋ฆ
๋๋ค.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
package com.codestates.member;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
public class MemberPostDto {
@NotBlank
@Email
private String email;
@NotBlank(message = "์ด๋ฆ์ ๊ณต๋ฐฑ์ด ์๋์ด์ผ ํฉ๋๋ค.")
private String name;
@Pattern(regexp = "^010-\\d{3,4}=\\d{4}$",
message = "ํด๋ํฐ ๋ฒํธ๋ 010์ผ๋ก ์์ํ๋ 11์๋ฆฌ ์ซ์์ '-'๋ก ๊ตฌ์ฑ๋์ด์ผ ํฉ๋๋ค.")
private String phone;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
@RestController
@RequestMapping("/v1/members")
public class MemberController {
@PostMapping
public ResponseEntity postMember(@Valid @RequestBody MemberPostDto memberPostDto) {
return new ResponseEntity<>(memberPostDto, HttpStatus.CREATED);
}
์ดํ์๋ต
package com.codestates.coffee;
import com.codestates.coffee.CoffeePostDto;
import com.codestates.coffee.CoffeePatchDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.Positive;
@RestController
@RequestMapping("/v1/coffees")
@Validated
public class CoffeeController {
@PostMapping // ์ถ๊ฐ
public ResponseEntity postCoffee(@Valid @RequestBody CoffeePostDto coffeeDto) {
return new ResponseEntity<>(coffeeDto, HttpStatus.CREATED);
}
@PatchMapping("/{coffee-id}") // ์์
public ResponseEntity patchCoffee(@PathVariable("coffee-id") @Positive long coffeeId,
@Valid @RequestBody CoffeePatchDto coffeePatchDto) {
coffeePatchDto.setCoffeeId(coffeeId);
return new ResponseEntity<>(coffeePatchDto, HttpStatus.OK);
}
@GetMapping("/{coffee-id}") // 1๊ฐ ์กฐํ
public ResponseEntity getCoffee(@PathVariable("coffee-id") long coffeeId) {
System.out.println("# coffeeId: " + coffeeId);
// not implementation
return new ResponseEntity<>(HttpStatus.OK);
}
@GetMapping // ๋ชจ๋ ์กฐํ
public ResponseEntity getCoffees() {
System.out.println("# get Coffees");
// not implementation
return new ResponseEntity<>(HttpStatus.OK);
}
@DeleteMapping("/{coffee-id}") //์ญ์
public ResponseEntity deleteCoffee(@PathVariable("coffee-id") long coffeeId) {
// No need business logic
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
}
package com.codestates.coffee;
import com.codestates.member.NotSpace;
import javax.validation.constraints.*;
public class CoffeePatchDto {
private long coffeeId;
@NotSpace(message = "์ปคํผ๋ช
์ ๊ณต๋ฐฑ์ด ์๋์ด์ผ ํฉ๋๋ค")
@Pattern(regexp = "^[ใฑ-ใ
๊ฐ-ํฃ]*$", message = "ํ๊ธ ์ปคํผ๋ช
์ ํ๊ธ๋ง ์
๋ ฅ ๊ฐ๋ฅํฉ๋๋ค")
private String korName;
@Pattern(regexp = "^[a-zA-Z]+(\\s[a-zA-Z]+)*$",
message = "์๋ฌธ ์ปคํผ๋ช
์ ์๋ฌธ(๋์๋ฌธ์)๊ณผ ์คํ์ด์ค๋ง ์
๋ ฅ ๊ฐ๋ฅํฉ๋๋ค.")
private String engName;
@Min(value = 100)
@Max(value = 50000)
private Integer price;
public void setCoffeeId(long coffeeId) {
this.coffeeId = coffeeId;
}
public long getCoffeeId() {
return coffeeId;
}
public String getKorName() {
return korName;
}
public String getEngName() {
return engName;
}
public int getPrice() {
return price;
}
}
package com.codestates.coffee;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.*;
public class CoffeePostDto {
@NotBlank
@Pattern(regexp = "^[ใฑ-ใ
๊ฐ-ํฃ]*$", message = "ํ๊ธ ์ปคํผ๋ช
์ ํ๊ธ๋ง ์
๋ ฅ ๊ฐ๋ฅํฉ๋๋ค")
private String korName;
@NotBlank
@Pattern(regexp = "^[a-zA-Z]+(\\s[a-zA-Z]+)*$",
message = "์๋ฌธ ์ปคํผ๋ช
์ ์๋ฌธ(๋์๋ฌธ์)๊ณผ ์คํ์ด์ค๋ง ์
๋ ฅ ๊ฐ๋ฅํฉ๋๋ค.")
private String engName;
@Range(min=100, max=50000)
private Integer price;
public String getKorName() {
return korName;
}
public String getEngName() {
return engName;
}
public Integer getPrice() {
return price;
}
}
DTOํด๋์ค์ int๋ก ๋ฐ์ดํฐ ํ์
์ ์ง์ ํ๋ฉด ๊ฐ์ด ์์ ๊ฒฝ์ฐ ์ด๊ธฐ๊ฐ์ด 0์ผ๋ก 0์ด๋ผ๋ ๊ฐ์ด ๋ค์ด์ค๊ฒ ๋ฉ๋๋ค. Null๋ก ๋ฐ๊ธฐ ์ํด์ Integerํ์
์ผ๋ก ์ง์ ํ์ต๋๋ค.
์ ๊ทํํ์์ ์ฒ์์ด๋ผ chatGPT ์๊ฒ ๋ฌผ์ด๋ด์ ํด๊ฒฐํ๋๋ฐ ์ ๊ทํํ์ ์ด ์ฌ์ดํธ์์ ํ
์คํธ ํด๊ฐ๋ฉด์ ์ฐพ์๋ณด๋ ์ฐ์ต๋ ๊ธฐํ๊ฐ ๋๋ฉด ํด๋ด์ผ ๊ฒ ์ต๋๋ค.
๋กฌ๋ถ์์๋ Setter๋ฅผ ์ด์ฉํ์ฌ ์ฝ๋๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ๋ง๋ค์๋ค.
package com.codestates.coffee.dto;
import lombok.Getter;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
@Getter
public class CoffeePostDto {
@NotBlank
private String korName;
@NotBlank
@Pattern(regexp = "^([A-Za-z])(\\s?[A-Za-z])*$",
message = "์ปคํผ๋ช
(์๋ฌธ)์ ์๋ฌธ์ด์ด์ผ ํฉ๋๋ค(๋จ์ด ์ฌ์ด ๊ณต๋ฐฑ ํ ์นธ ํฌํจ). ์) Cafe Latte")
private String engName;
@Range(min= 100, max= 50000)
private int price;
@NotBlank
@Pattern(regexp = "^([A-Za-z]){3}$",
message = "์ปคํผ ์ฝ๋๋ 3์๋ฆฌ ์๋ฌธ์ด์ด์ผ ํฉ๋๋ค.")
private String coffeeCode;
}