๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ์ @Controller๋ฅผ ์ ๊ฐ๋ฐํ๋ ๋ฐฉ๋ฒ
๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ
Spring ์ ํ๋ฆฌ์ผ์ด์ ฉ๋ ๊ฐ๋ฐํ ๋, ํด๋์ค๋ช ์ ๋๋ฉ์ธ ๊ธฐ๋ฐ ๋ช ์นญ๊ณผ 3๊ณ์ธต ์ํคํ ์ฒ ๋ช ์นญ์ ์กฐํฉํ์ฌ ์์ฑ๋๋ค. ์๋ฅผ ๋ค์ด, PaymentService๋ ๋๋ฉ์ธ์ธ Payment์ ์ญํ ์ธ Service๋ฅผ ์กฐํฉํ ํด๋์ค๋ช ์ด๋ค. ์ด์ ๊ฐ์ด ๊ฐ ํด๋์ค๋ ์ผ๋ฐ์ ์ผ๋ก ๋๋ฉ์ธ๊ณผ ๊ณ์ธต ๊ตฌ์กฐ์๋ฐ๋ผ ๋ช ๋ช ๋๋ค.
- ๋๋ฉ์ธ ๊ธฐ๋ฐ ๋ช
์นญ + 3๊ณ์ธต ์ํคํ
์ฒ ๊ธฐ๋ฐ ๋ช
์นญ
- PaymentService = Payment(๋๋ฉ์ธ) + Service(3๊ณ์ธต ์ํคํ ์ฒ ์ค ์๋น์ค ๊ณ์ธต)
- UserRepository = User + Repositorry
- JobpostController = Jobpost + Controller
ํด๋์ค๋ฅผ ๋ฐฐ์นํ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ์ ๋ํด์๋ ๋ ๊ฐ์ง ๋ฐฉ์์ด ์๋ค.
1. ๋๋ฉ์ธ ๊ธฐ๋ฐ ๋๋ ํ ๋ฆฌ → 3๊ณ์ธต ์ํค์ฒต์ฒ ๊ธฐ๋ฐ ๋๋ ํ ๋ฆฌ
ํด๋์ค๋ฅผ ๋๋ฉ์ธ๋ณ๋ก ๋๋๊ณ , ๊ทธ ์์์ 3๊ณ์ธต ์ํคํ ์ฒ(Controller, Service, Repository)๋ก ๊ตฌ๋ถํ๋ ๋ฐฉ์์ด๋ค.
2. 3๊ณ์ธต ์ํคํ ์ฒ ๊ธฐ๋ฐ ๋๋ ํ ๋ฆฌ → ๋๋ฉ์ธ ๊ธฐ๋ฐ ๋๋ ํ ๋ฆฌ
3๊ณ์ธต ์ํคํ ์ฒ ๊ธฐ์ค์ผ๋ก ๋๋ ํ ๋ฆฌ๋ฅผ ๋๋ ํ, ๊ฐ ๊ณ์ธต์์ ๋๋ฉ์ธ๋ณ๋ก ํด๋์ค๋ฅผ ๋ฐฐ์นํ๋ ๋ฐฉ์์ด๋ค.
- ๋๋ฉ์ธ ๊ธฐ๋ฐ ๋๋ ํ ๋ฆฌ๋ ๋๋ฉ์ธ ๊ฐ์ ์์ง๋๊ฐ ๋๊ณ ํด๋์ค๊ฐ ๊ฐ๋จํ ํ์ ํ๋ก์ ํธ๋ ์์ ๊ท๋ชจ์ ํ๋ก์ ํธ์์ ์์ฃผ ์ฌ์ฉ๋๋ค.
- 3๊ณ์ธต ์ํคํ ์ฒ ๊ธฐ๋ฐ ๋๋ ํ ๋ฆฌ๋ ์๋ง์ ๋๋ฉ์ธ์ ๋ค๋ฃจ๋ ๋๊ท๋ชจ ์์คํ ์์ ์ ์ง๋ณด์์ ๊ณ์ธต๊ฐ ์ญํ ์ ๋ช ํํ ํ๊ธฐ ์ํด ํ์ ์์ ๋ง์ด ์ฌ์ฉ๋๋ค.
3-Layered Architecture ๊ธฐ๋ฐ ๋๋ ํ ๋ฆฌ
- /exception/
- /advisor/
- /controller/ ← ์์ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ
- /user/
- /payment/
- /cart/
- /jobpost/
- /delivery/
- /service/
- /repository/
- /configuration/
Domain ๊ธฐ๋ฐ ๋๋ ํ ๋ฆฌ
- /user/
- /payment/ ← ์์ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ
- /controller/
- /service/
- /repository/
- /cart/
- /jobpost/
- /delivery
@Controller๋ฅผ ์ ๊ฐ๋ฐํ๋ ๋ฐฉ๋ฒ
@Controller์์ ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ๋ ๋ฐฉ๋ฒ 4๊ฐ์ง
โน๏ธ https://1000sang-dev.tistory.com/60 ํด๋น ํฌ์คํ ์ ์ฐธ๊ณ ํ์ !
1. @PathVariable: URI ๊ฒฝ๋ก์์ ๊ฐ๋ณ ์ธ์๋ฅผ ๋ฐ๋ ๋ฐฉ์. ์: `/api/users/{id}`
2. @RequestParam: ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ๋จ์ผ ๊ฐ์ ๋ฐ๋ ๋ฐฉ์. ์: `?key=value`
3. @ModelAttribute: ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ์์ ์ฌ๋ฌ ๊ฐ์ DTO ๊ฐ์ฒด๋ก ๋ฐ์ ๋ ์ฌ์ฉ.์: `?key1=value&key2=value2`
4. @RequestBody: JSON ๋๋ XML๋ก ์์ฒญ ๋ฐ๋์ ๋ด๊ธด ๋ฐ์ดํฐ๋ฅผ DTO ๊ฐ์ฒด๋ก ๋ฐ๋ ๋ฐฉ์. ์: `{ "property : "value" }`
@RestCotroller = @Controller + @ResponseBody
โน๏ธ https://1000sang-dev.tistory.com/57 ํด๋น ํฌ์คํ ์ ์ฐธ๊ณ ํ์ !
- @RestController๋ @Controller์ @ResponseBody๋ฅผ ๊ฒฐํฉํ ๊ฒ์ผ๋ก, ๋ฉ์๋๋ง๋ค @ResponseBody๋ฅผ ๋ถ์ด์ง ์๊ณ ๋ JSON ์๋ต์ ์ฒ๋ฆฌํ ์ ์๋ค.
ํ์ค HTTP Status Code๋ฅผ ํ์ฉํ์ฌ ๊ฒฐ๊ณผ ๋ฐํ์ ์ํ Wrapper Class
- Spring์์ ๋จ์ํ API๋ฅผ ๊ฐ๋ฐํ ๋, ์ ์ ์๋ต์ 200OK๋ฅผ ๋ฐํธ๋ํ๊ณ , ์ค๋ฅ ๋ฐ์ ์ 500 Internal Server Error ๊ฐ์ ๊ธฐ๋ณธ ์๋ฌ ํ์ด์ง๊ฐ ๋ฐํ๋๋ค.
- ๊ทธ๋ฌ๋ ์ค๋ฌด์์๋ ์ํฉ๋ณ๋ก ๋ค์ํ ์ํ์ฝ๋๋ฅผ ์ธ๋ฐํ๊ฒ ์ค๊ณํ์ฌ API์ ์ฑ๊ณต/์คํจ๋ฅผ ๊ด๋ฆฌํ๋๊ฒ์ด ์ค์ํ๋ค.
- ์๋ฅผ ๋ค์ด, ์ธ๋ถ API์์ ํต์ ์ ๋ฐ์ํ๋ ์๋ฌ๋ ํ๋ก ํธ์๋์์ ์์ฒญํ ๋ฐ์ดํฐ๋ฅผ ์๋ชป ์ฒ๋ฆฌํ ๊ฒฝ์ฐ๋ฅผ ์ํ์ฝ๋๋ก ๋ช ํํ๊ฒ ๊ตฌ๋ถํด์ผํ๋ค.
HTTP Response ์ํ์ฝ๋ ์ข ๋ฅ
- HTTP ์ํ์ฝ๋ : 200 OK, 404 Not Found, 500 Internal Server Error ๋ฑ
- HTTP Response Status
- 10X : ์ ๋ณด์ฑ ์๋ต ← Informational Response
- 20X : ์ฑ๊ณต (์๋ต ์๋ฃ) ← Successful Response
- 30X : ๋ฆฌ๋ค์ด๋ ์ ← Redirection
- 40X : ๊ถํ ํน์ ์๋ชป๋ ์ ๊ทผ (์ ์ ์ ์๋ชป) ← Client Error
- 50X : ์๋ฒ ๋ด๋ถ ๋ฌธ์ ← Server Error
- 200 OK : ์์ฒญ ์ฑ๊ณต
- 201 Created : ์๋ก์ด ์์์ด ์ฑ๊ณต์ ์ผ๋ก ์์ฑ
- 400 Bad Request : ์๋ชป๋ ์์ฒญ
- 401 Unauthorized : ์ธ์ฆ ์คํจ
- 404 Not Found : ์์ฒญํ ์์์ ์ฐพ์ ์ ์์
- 500 Internal Server Error : ์๋ฒ ๋ด๋ถ ์ค๋ฅ
- HTTP Response Status
- ์ปค์คํ
์ํ์ฝ๋ : A01 ํ์
์๋ฌ, A02 ์
๋ ฅ ์๋ฌ, B01 ์ธ๋ถ ์๋ฒ ํต์ ์๋ฌ ๋ฑ
- ๊ธฐํ์๋ณด๋ค๋ ๊ธฐ์ ๋ฆฌ๋๋ ๊ฐ๋ฐ์๋ค์ด ๋ชจ์ธ ๊ธฐ์ ํ์์ ๊ฒฐ์ ํ๋ ์๋ฌ ์ฝ๋
- ResponseEntity<T>: POST ์์ฑ ์๋ฃ ์ HTTP ์ํ์ฝ๋(201, CREATED) ํฌํจ ๊ฒฐ๊ณผ ๋ฐํ
@PostMapping("")
@ResponseBody
public ResponseEntity<UserResponseDto> save(@RequestBody @Valid UserCreateRequestDto request) {
UserResponseDto user = userService.save(request.getName(), request.getAge(), request.getJob(), request.getSpecialty());
return ResponseEntity
// .status(HttpStatusCode.valueOf(201)) // 1. HttpStatusCode.valueOf(201) ์ฌ์ฉ ๊ฐ๋ฅํ์ง๋ง ์๋์ ๋์ผํ ๊ฒฐ๊ณผ
.status(HttpStatus.CREATED) // 1. HTTP 201 ์ํ ์ฝ๋ ๋ฐํ: ์๋ก์ด ์์(User)์ด ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋จ์ ๋ํ๋
.body(user); // 2. ๊ฒฐ๊ณผ ๊ฐ์ฒด(User) ๋ฐํ
}
HttpStatus.CREATED: HTTP ์ํ ์ฝ๋ 201์ ์๋ก์ด ๋ฆฌ์์ค๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋์์์ ๋ํ๋ธ๋ค. ์ฌ๊ธฐ์ user๋ผ๋ ์๋ก์ด ์ ์ ๊ฐ ์์ฑ๋์๊ธฐ ๋๋ฌธ์, 201 Created ์ํ ์ฝ๋๊ฐ ๋ฐํ๋๋ค.
- ResponseEntity<T>: GET ์กฐํ ์๋ฃ ์ HTTP ์ํ์ฝ๋(200, OK) ํฌํจ ๊ฒฐ๊ณผ(JSON) ๋ฐํ
@GetMapping("/data")
@ResponseBody
public ResponseEntity<UserResponseDto> detailData(@RequestParam Integer id) {
UserResponseDto user = userService.findById(id);
return ResponseEntity
.status(HttpStatus.OK) // 1. HTTP 200 ์ํ ์ฝ๋ ๋ฐํ
.body(user); // 2. ์กฐํ๋ UserResponseDto ๊ฐ์ฒด ๋ฐํ
}
HttpStatus.OK: HTTP ์ํ ์ฝ๋ 200์ ์์ฒญ์ด ์ฑ๊ณต์ ์ผ๋ก ์ฒ๋ฆฌ๋์์์ ์๋ฏธํ๋ค. ์ฌ๊ธฐ์ ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ ์์ ์ผ๋ก ์กฐํํ ํ์, 200OK ์ํ์ฝ๋๊ฐ ๋ฐํ๋๋ค.
- ResponseEntity<T>: ๋ด๋ถ RuntimeException ๋ฐ์ ์ HTTP ์ํ์ฝ๋(404, Not Found)
@GetMapping("/data")
@ResponseBody
public ResponseEntity<UserResponseDto> detailData(@RequestParam Integer id) {
try {
UserResponseDto user = userService.findById(id);
return ResponseEntity
.status(HttpStatus.OK) // 1. ์ฑ๊ณต ์, HTTP 200 ์ํ ์ฝ๋ ๋ฐํ
.body(user); // 2. ์กฐํ๋ ์ ์ ๊ฐ์ฒด(UserResponseDto) ๋ฐํ
} catch (RuntimeException e) {
return ResponseEntity
.status(HttpStatus.NOT_FOUND) // 3. ์ ์ ๋ฅผ ์ฐพ์ง ๋ชปํ ๊ฒฝ์ฐ, HTTP 404 ์ํ ์ฝ๋ ๋ฐํ
.body(null); // 4. ์๋ฌ ์ํฉ์์๋ body์ null ๋ฐํ
}
}
์กฐํ์ ์คํจํ๊ฑฐ๋ ํด๋น ์ ์ ๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด HTTP 404(NOT FOUND) ์ํ ์ฝ๋์ ํจ๊ป null์ ์๋ต์ ๋ด์ ๋ฐํํ๋ค.
- Optional: Optional.ofNullable(user).orElseThrow(...) = Null์ ๋ํ ์์ธ ์ฒ๋ฆฌ
โน๏ธ https://1000sang-dev.tistory.com/52 ํด๋น ํฌ์คํ ์ ์ฐธ๊ณ ํ์ !
public User findById(Integer id) {
Optional<User> retrieved = Optional.ofNullable(users.get(id));
// users.get(id)๋ก ์ ์ ๋ฅผ ๊ฒ์ํ๊ณ , ๊ฒฐ๊ณผ๊ฐ null์ผ ์ ์์ผ๋ฏ๋ก Optional๋ก ๊ฐ์ธ์ค๋ค.
// Optional.ofNullable()์ null์ผ ์ ์๋ ๊ฐ์ฒด๋ฅผ ์์ ํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋๋ก ํด์ค๋ค.
return retrieved.orElseThrow(() -> new RuntimeException("์ ์ ๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค. id : " + id));
// Optional์ ๊ฐ์ด ์กด์ฌํ๋ฉด ํด๋น ๊ฐ์ ๋ฐํํ๊ณ , ๊ฐ์ด ์์ผ๋ฉด ์์ธ๋ฅผ ๋์ง๋ค.
// orElseThrow()๋ ๊ฐ์ด ์์ ๋ RuntimeException์ ๋ฐ์์์ผ ์ ์ ๊ฐ ์๋ค๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ๋ฌ๋ค.
}
JSON ๋ฐํ ์ ์ธ๋ถ ์ค์ : Jackson ์ง๋ ฌํ / ์ญ์ง๋ ฌํ
@JsonInclude: JSON ๋ ธ์ถ ์ฌ๋ถ์ ๋ํ ์กฐ๊ฑด
โน๏ธ https://1000sang-dev.tistory.com/60 ํด๋น ํฌ์คํ ์ ์ฐธ๊ณ ํ์ !
- @JsonInclude: JSON์์ ํน์ ํ๋๋ฅผ ๋ ธ์ถํ ์กฐ๊ฑด์ ์ค์ . ์๋ฅผ ๋ค์ด, NULL ๊ฐ์ธ ํ๋๋ฅผ ์ ์ธํ๊ณ ๋ ธ์ถ ๊ฐ๋ฅ.
@JsonProperty: ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๊ฐ ๊ณ์ Key๋ฅผ ๋ฐ๊ฟ๋ฌ๋ผ๊ณ ํ๋ ๊ฒฝ์ฐ
@JsonProperty("userId")
private Integer id;
// JSON ์๋ต ์ "id" ํ๋๋ฅผ "userId"๋ก ๋ณ๊ฒฝํ์ฌ ๋ฐํํ๋ค.
// ์ฆ, ํด๋ผ์ด์ธํธ์๊ฒ "id" ๋์ "userId"๋ผ๋ ์ด๋ฆ์ผ๋ก ์ด ํ๋๋ฅผ ๋
ธ์ถ์ํจ๋ค.
@JsonProperty("username")
private String name;
// JSON ์๋ต ์ "name" ํ๋๋ฅผ "username"์ผ๋ก ๋ณ๊ฒฝํ์ฌ ๋ฐํํ๋ค.
// ํด๋ผ์ด์ธํธ๋ "name" ๋์ "username"์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ์ด ํ๋๋ฅผ ๋ฐ๋๋ค.
- @JsonProperty๋ ํ๋๊ฐ JSON์ผ๋ก ์ง๋ ฌํ๋ ๋, JSON์์ ์ฌ์ฉํ ํค ๊ฐ์ ์ง์ ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
- ์ ์์๋ id๋ userId๋ก, name์ username์ผ๋ก JSON์ ๋ฐํ๋ ๋ ๋ ธ์ถ๋๋ค.
- ์ฆ, ํด๋์ค์ ํ๋๋ช ๊ณผ JSON์์ ์ฌ์ฉ๋๋ ์ด๋ฆ์ด ๋ค๋ฅผ ๋ @JsonProperty๋ฅผ ํตํด ์ํ๋ ์ด๋ฆ์ ์ง์ ํ ์ ์๋ค.
@JsonNaming: ์ค๋ค์ดํฌ ์ผ์ด์ค ๋ฑ ๋ฐํํ ๋ JSON ๋ด Key ๋ค์ด๋ฐ ์ปจ๋ฒค์ ์ ํ๋ฒ์ ๋ณ๊ฒฝํ ์ ์๋ค.
@Data
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
public class Student {
private String myName;
private String myAge;
private String myCountry;
}
@JsonPropertyOrder: JSON ๋ฐํ ์ ๋ณด๊ธฐ ํธํ๊ฒ ํ๋กํผํฐ ์์ ์ ๋ ฌ
@JsonPropertyOrder({"userId", "username"})
// JSON ์ง๋ ฌํ ์, ์๋ต์ผ๋ก ๋ฐํ๋๋ JSON ๊ฐ์ฒด์ ํ๋ ์์๋ฅผ ์ง์ ํ๋ค.
// ์ด ์์์์๋ "userId"์ "username" ํ๋๊ฐ ๊ฐ์ฅ ๋จผ์ ์ถ๋ ฅ๋๋๋ก ์ค์ ํ๋ค.
- @JsonPropertyOrder๋ JSON ์ง๋ ฌํ ์ ํ๋๊ฐ ์ถ๋ ฅ๋๋ ์์๋ฅผ ์ ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
- ์ง์ ๋ ํ๋ ์์๋๋ก JSON ๊ฐ์ฒด ๋ด์ ํ๋๊ฐ ๋ ธ์ถ๋๋ค.
- ์ ์ฝ๋์์๋ "userId" ํ๋๊ฐ ๋จผ์ , ๊ทธ ๋ค์์ "username" ํ๋๊ฐ JSON ์๋ต์ ๋ํ๋๋๋ก ์ค์ ๋๋ค.
@JsonIgnore: JSON ๋ฐํ ์ ๋ฏธ๋ ธ์ถ ํ๋กํผํฐ
@JsonIgnore
private Integer age;
- @JsonIgnore๋ ํด๋น ํ๋๋ฅผ JSON ์๋ต์์ ์ ์ธํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
- ์ด ๊ฒฝ์ฐ age ํ๋๋ ์ง๋ ฌํ ๋์ง ์์ผ๋ฉฐ, JSON ์๋ต์์ ๋ํ๋์ง ์๋๋ค.
- ์ฆ, UserResponseDto ๊ฐ์ฒด๊ฐ JSON์ผ๋ก ๋ณํ๋ ๋, age ๊ฐ์ ์จ๊ฒจ์ง๊ณ , ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌ๋์ง ์๋๋ค.
@JsonFormat: JSOn ๋ด ๋ ์ง ํ๊ธฐ ์ ํฌ๋งท ์ง์
- DataTimeFormat: Spring์์ ์ง์ํ๋ ๋ฐ์ดํฐ ํฌ๋งท ์ด๋ ธํ ์ด์ ์ด๊ธฐ์ JSON ์ธ์ XML ์๋ ์ ์ฉ๋๋ค.
- @JsonFormat: ์ผ๋ฐ์ ์ผ๋ก JSON์ ์ฌ์ฉํ๊ธฐ์ ๋ณธ Jackson ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
private LocalDateTime createdAt;
- LocalDataeTime ํ์ ์ Java 8์์ ๋์ ๋ ๋ ์ง ๋ฐ ์๊ฐ ๊ด๋ จ ํด๋์ค ์ค ํ๋๋ก, ๋ ์ง์ ์๊ฐ์ ๋ชจ๋ ํฌํจํ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฌ๋ค.
- createAt ํ๋๋ ์ํฐํฐ๊ฐ ์์ฑ๋ ์๊ฐ์ ๋ํ๋ด๋ฉฐ, ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ๊ฐ ์ธ์ ์์ฑ๋์๋์ง๋ฅผ ๊ธฐ๋กํ ์ ์๋ค.
- LocalDateTime ํ์ ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ , ์, ์ผ, ์, ๋ถ, ์ด ์ ๋ณด๋ฅผ ํฌํจํ๋ค.
- JSON ์ง๋ ฌํ ์ ์ด ํ๋๋ ์๋์ผ๋ก ๋ ์ง์ ์๊ฐ ํ์์ผ๋ก ๋ณํ๋์ด ํด๋ผ์ด์ธํธ์ ์ ๋ฌ๋๋ค.
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdAt;
- @JsonFormat ์ด๋ ธํ ์ด์ ์ Jackson ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ๋ ์ง์ ์๊ฐ ํ์์ ์ง์ ํ ๋ ์ฌ์ฉ๋๋ค.
- shape = JsonFormat.Shape.STRING๋ LocalDateTime ํ๋๋ฅผ ๋ฌธ์์ด ํํ๋ก ์ง๋ ฌํํ๋๋ก ์ค์ ํ๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก LocalDateTime์ ๋ณต์กํ ๊ฐ์ฒด ํํ๋ก ์ง๋ ฌํ๋์ง๋ง, ์ด ์ต์ ์ ์ฌ์ฉํ๋ฉด String ํํ๋ก ๋ ์ง๋ฅผ ํํํ๋ค
- pattern = "yyyy-MM-dd HH:mm:ss"๋ ๋ ์ง์ ์๊ฐ์ ํฌ๋งท์ ์ค์ ํ๋ค. ์ด ์์ ์์๋ ๋ค์๊ณผ ๊ฐ์ ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณํํ๋ค:
- "๋ -์-์ผ-์:๋ถ:์ด" ํ์์ผ๋ก ๋ณํ๋๋ค.
- ์์: "2024-10-07 00:29:30"
@JacksonAnnotationsInside + @interface: ์ปค์คํ JSON ๋ณํ ์ด๋ ธํ ์ด์
- @JacksonAnnotationsInside: Jackson ๊ด๋ จ ์ด๋
ธํ
์ด์
์ ์์ํ์ฌ ์ฌ์ฉํ๊ฒ ๋ค๋ ์๋ฏธ.
- ์ด๊ฒ์ ๋ถ์ด์ง ์๋๋ค๋ฉด ์ธํฐํ์ด์ค ์์ฒด์ ์ด๋ ธํ ์ด์ ์ด ์ ์ฉ๋์ด ์์น ์๋ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ํ๋ค.
@JacksonAnnotationsInside // ์ด ์ด๋
ธํ
์ด์
์ ํด๋น ์ด๋
ธํ
์ด์
์ด Jackson ๊ด๋ จ ์ด๋
ธํ
์ด์
์ ์์ํ์ฌ ์ฌ์ฉํ ์ ์๋๋ก ํจ.
// ์ฆ, ์ด ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ๋ฉด ๋ด๋ถ์ ์ผ๋ก @JsonFormat๊ณผ ๊ฐ์ Jackson ์ด๋
ธํ
์ด์
์ด ์ ์ฉ๋ ๊ฒ๊ณผ ๋์ผํ ํจ๊ณผ๋ฅผ ์ ๊ณต.
@Retention(RetentionPolicy.RUNTIME) // ์ด ์ด๋
ธํ
์ด์
์ ์ปค์คํ
์ด๋
ธํ
์ด์
์ด ๋ฐํ์ ๋์ ์ ์ง๋๋๋ก ์ค์ , ๋ฐํ์์์ ๋ฆฌํ๋ ์
๊ฐ๋ฅ.
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
// ์ด ๋ถ๋ถ์ @JsonFormat์ ํฌํจํ๋ ๊ฒ์ผ๋ก, ๋ ์ง/์๊ฐ ํ์์ ์ง์ ํจ.
public @interface DateFormat { // @interface๋ ์ปค์คํ
์ด๋
ธํ
์ด์
์ ์์ฑํ ๋ ์ฌ์ฉ๋จ.
// DateFormat์ด๋ผ๋ ์ด๋
ธํ
์ด์
์ ์๋ก ๋ง๋ค๊ณ , ์ด ์์ JsonFormat์ ํฌํจ์์ผ ์ปค์คํ
์ด๋
ธํ
์ด์
์ผ๋ก ๋ง๋ฆ.
}
Enum ์ง๋ ฌํ / ์ญ์ง๋ ฌํ: @JsonFormat, @JsonValue, @JsonCreator
1. Enum ์ง๋ ฌํ ์
- @JsonFormat(OBJECT)
- Enum์ ๋ชจ๋ ํ๋๋ฅผ ์ถ๋ ฅํ ๋ ์ฌ์ฉ๋๋ค. ์ฆ, ํน์ ํ๋๋ง์ด ์๋๋ผ Enum ๊ฐ์ฒด ์ ์ฒด๋ฅผ JSON์ผ๋ก ์ง๋ ฌํํ๋ค.
- ์์: { "id":1, "name": "CHEONSANG" } ์ฒ๋ผ ์ ์ฒด Enum ๊ฐ์ฒด๋ฅผ ํํํ๋ค
- @JsonValue ํ๋
- ํน์ ํ๋ ๊ฐ๋ง JSON์ผ๋ก ์ง๋ ฌํํ ๋ ์ฌ์ฉ๋๋ค.
- ์์: { "name": "CHEONSANG" } ์ฒ๋ผ ์ํ๋ ํ๋๋ง ์ ํํด์ ์ถ๋ ฅํ ์ ์๋ค.
- @JsonValue ๋ฉ์๋
- ํน์ ๋ฉ์๋์ ๊ฒฐ๊ณผ๊ฐ์ JSON์ผ๋ก ์ง๋ ฌํํ ๋ ์ฌ์ฉ๋๋ค. Enum ํด๋์ค์ ์ ์๋ ๋ฉ์๋์ ๋ฐํ ๊ฐ์ JSON์ผ๋ก ์ถ๋ ฅํ ์ ์๋ค.
- ์์: Enum ๋ด์์ ํน์ ๋ก์ง์ ์ ์ฉํ ํ ๊ทธ ๊ฐ์ ์ถ๋ ฅ.
- @JsonProperty
- JSON์ผ๋ก ๋ฐํ๋๋ Enum ํ๋์ ์ด๋ฆ์ ์ง์ ํ ๋ ์ฌ์ฉ๋๋ค. ํ๋๋ช ์ ์ํ๋ ๋๋ก ์ปค์คํ ํด์ ์ถ๋ ฅ ๊ฐ๋ฅํ๋ค.
- ์์: "user_id": 1๊ณผ ๊ฐ์ด ํ๋๋ช ์ ์ปค์คํ ํ ์ ์๋ค.
- ๊ธฐ๋ณธ Key ๊ฐ
- ์๋ฌด ์ค์ ๋ ํ์ง ์์ผ๋ฉด, Enum์ ๊ทธ ๊ธฐ๋ณธ ์ด๋ฆ(Key ๊ฐ) ์ผ๋ก ์ง๋ ฌํ๋๋ค.
- ์์: CHEONSANG๊ณผ ๊ฐ์ Enum ์์ฒด์ ๊ฐ์ด ์ถ๋ ฅ๋๋ค.
2. Enum ์ญ์ง๋ ฌํ ์
- @JsonCreator
- ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ๋ฐ์ ์์ฒญ์ ์ญ์ง๋ ฌํํ ๋ ์ฌ์ฉ๋๋ค. Enum์ ์ง์ ํ ๋ ํ๋ ์ด๋ฆ๊ณผ ๊ฐ์ด ์ผ์นํด์ผ๋ง ๋งคํ์ด ๊ฐ๋ฅํ๋ค.
- ์์: ์์ฒญ์ผ๋ก ๋ค์ด์จ "name": "CHEONSANG"๊ณผ ๊ฐ์ ๊ฐ์ด Enum์ ํ๋๋ช ๊ณผ ์ผ์นํด์ผ ์ ์์ ์ผ๋ก ๋งคํ๋๋ค.
- @JsonCreator(DELEGATING)
- ๋ ๊ฐ๋จํ๊ฒ ํน์ ํ๋ ๊ฐ์ผ๋ก Enum์ ๋งคํํ ์ ์๋ค. ์ด ๋ฐฉ์์ ํ๋๋ช ์ด ์๋๋ผ ํน์ ๊ฐ์ ์ง์คํ์ฌ ์์ฒญ์ ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋ ์ ์ฐํ๋ค.
- ์์: "CHEONSANG"์ด๋ผ๋ ๊ฐ๋ง์ผ๋ก๋ Enum์ ๋งคํํ ์ ์๋ค.(ํ๋๋ช ๊ณผ ์๊ด์์ด ์ฒ๋ฆฌ)
โน๏ธ ์ฐธ๊ณ
[ASAC 6๊ธฐ ๊ฐ์์๋ฃ]
'๐ปDEV-STUDY > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring Boot, DB] DB์ Spring Boot ์ฐ๋ (1) | 2024.11.29 |
---|---|
[Spring] ์ค๋ฌด์์์ Best Practices #2 (0) | 2024.10.07 |
[Spring] Spring Boot ์ฅ์ ๋ฐ ๋์ (0) | 2024.10.06 |
[Spring] Spring ์์ฒญ๊ฐ ์ฒ๋ฆฌ ๋ฐฉ์ (0) | 2024.10.06 |
Spring Bean ์๋ฆฌ๊ณผ ์์กด์ฑ ์ฃผ์ (1) | 2024.10.06 |