[Spring Boot - ๐ŸฑPetClinic๐Ÿถ] 8. Controller ๋ถ„์„(1)๐Ÿ”

์‘ค๋ฐยท2023๋…„ 4์›” 18์ผ

[Spring Boot - ๐ŸฑPetClinic๐Ÿถ]

๋ชฉ๋ก ๋ณด๊ธฐ
8/11

โœ”๏ธ Controller ๊ณตํ†ต์‚ฌํ•ญ

  • ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ๋กœ์˜ ์ˆ˜๊ฐ€ ๋งŽ์€ ์ปจํŠธ๋กค๋Ÿฌ์—” ๊ณตํ†ต์œผ๋กœ ๋ฆฌํ„ดํ•˜๋Š” ํŽ˜์ด์ง€์˜ ์ด๋ฆ„์„ private static final String์œผ๋กœ ์„ ์–ธํ•ด ๋‘”๋‹ค. (OwnerController, PetContoller)
private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
  • ๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ จ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•  Repository ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ์ž์—์„œ ์ฃผ์ž…๋ฐ›๋Š”๋‹ค.
  • @InitBinder ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค.
  • @ModelAttribute ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค.

๐Ÿ’‰ Controller์˜ Repository ๊ฐ์ฒด ์˜์กด์„ฑ ์ฃผ์ž…

์ง€๊ธˆ๊นŒ์ง€ ๋‚ด๊ฐ€ ์‚ฌ์šฉํ–ˆ๋˜ ์˜์กด์„ฑ ์ฃผ์ž…์€ Repository ๊ฐ์ฒด๊ฑด Service ๊ฐ์ฒด๊ฑด ๋ชจ๋‘ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ  @Autowired ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•ด Controller์—์„œ ์ฃผ์ž…๋ฐ›๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ–ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ Pet Clinic์—์„œ๋Š” ๊ทธ ๋Œ€์‹  ๋ณ€์ˆ˜๋ฅผ private final๋กœ ์„ ์–ธํ•˜๊ณ  ์ƒ์„ฑ์ž์—์„œ ๊ฐ์ฒด๋ฅผ ํ• ๋‹น๋ฐ›๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

private final OwnerRepository owners;

public OwnerController(OwnerRepository clinicService) {
	this.owners = clinicService;
}

๊ทธ๋ƒฅ ํ–ˆ์„ ๊ฒƒ ๊ฐ™์ง„ ์•Š๊ณ  ๋ญ”๊ฐ€ ์ด์œ ๊ฐ€ ์žˆ์œผ๋ฆฌ๋ผ ์ƒ๊ฐํ•ด์„œ ์ฐพ์•„๋ดค๋‹ค. ์˜์กด์„ฑ ์ฃผ์ž… ๋ฐฉ๋ฒ•์—๋Š” ํฌ๊ฒŒ ์„ธ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค. ์ฒซ ๋ฒˆ์งธ๋กœ๋Š” ํ•„๋“œ ์ฃผ์ž… ๋ฐฉ์‹, ๋‘ ๋ฒˆ์งธ๋กœ ์ˆ˜์ •์ž ์ฃผ์ž… ๋ฐฉ์‹, ๋งˆ์ง€๋ง‰์œผ๋กœ ์ƒ์„ฑ์ž ์ฃผ์ž… ๋ฐฉ์‹์ด ์žˆ๋‹ค.

1. ํ•„๋“œ ์ฃผ์ž… ๋ฐฉ์‹

์ด ๋ฐฉ์‹์€ ๋‚ด๊ฐ€ ์ฃผ๋กœ ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐฉ์‹์ด๋‹ค. ์œ„์˜ ์ฝ”๋“œ๋ฅผ ํ•„๋“œ ์ฃผ์ž… ๋ฐฉ์‹์œผ๋กœ ๋ฐ”๊พธ์ž๋ฉด

@Autowired
private OwnerRepository owners;

์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค. Controller์— ์ฃผ์ž…ํ•  ๋นˆ ๊ฐ์ฒด๋Š” ๋”ฐ๋กœ ๋นˆ ๊ฐ์ฒด๋ผ๊ณ  ๋“ฑ๋กํ•ด์•ผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์œผ๋‚˜ ์ถ”์ฒœํ•˜๋Š” ๋ฐฉ์‹์€ ์•„๋‹ˆ๋ผ๊ณ  ํ•œ๋‹ค. ํ•„๋“œ ์ฃผ์ž…์„ ํ†ตํ•ด ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๊ฒŒ ๋˜๋ฉด ์™ธ๋ถ€์—์„œ ์ˆ˜์ •์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ , ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ์ž‘์„ฑํ•  ๋•Œ ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ•„๋“œ ์ฃผ์ž…์„ ํ†ตํ•ด ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•œ๋‹ค๋ฉด final ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•œ ์„ ์–ธ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์ฒด๊ฐ€ mutable ํ•ด์ง„๋‹ค. ๋˜ํ•œ, ์˜์กด์„ฑ ์ฃผ์ž…์„ ๋‚จ๋ฐœํ•˜๊ฒŒ ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ์ผ ์ฑ…์ž„์˜ ์›์น™์„ ์œ„๋ฐฐํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์„ ์ง€์–‘ํ•ด์•ผ ํ•œ๋‹ค.

2. ์ˆ˜์ •์ž ์ฃผ์ž… ๋ฐฉ์‹

์ด ๋ฐฉ์‹์€ Setter ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…๋ฐ›๋Š” ๋ฐฉ์‹์ด๋‹ค. ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •์ž ์ฃผ์ž… ๋ฐฉ์‹์œผ๋กœ ๋ฐ”๊พธ์ž๋ฉด

private OwnerRepository owners;

public setOwnerController(OwnerRepository clinicService) {
	this.owners = clinicService;
}

์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค. Setter ๋ฉ”์„œ๋“œ๋Š” ๊ด€๊ณ„๋ฅผ ์ฃผ์ž…๋ฐ›๋Š” ๊ฐ์ฒด์˜ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๋ณดํ†ต์˜ ๊ฒฝ์šฐ ๊ฐ์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋  ์ผ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•  ์ผ์ด ๋“œ๋ฌผ๋‹ค. ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์„ ์—ด์–ด๋‘๊ฒŒ ๋˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์œ„ํ—˜์ด ๋†’๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์„ ์ง€์–‘ํ•ด์•ผ ํ•œ๋‹ค.

3. ์ƒ์„ฑ์ž ์ฃผ์ž… ๋ฐฉ์‹

์ด ๋ฐฉ์‹์€ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…๋ฐ›๋Š” ๋ฐฉ์‹์ด๋‹ค. ๋งจ ์ฒ˜์Œ์— ์†Œ๊ฐœํ•œ ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ์ด๋‹ค. ์ƒ์„ฑ์ž๋Š” ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๋Š” ํŠน์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— immutable ํ•˜๋‹ค. final ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฐฉ์‹์€ ์ฃผ์ž…๋ฐ›์€ ๊ฐ์ฒด๊ฐ€ ๋ถˆ๋ณ€์ด์–ด์•ผ ํ•˜๊ฑฐ๋‚˜, ๋ฐ˜๋“œ์‹œ ๊ฐ์ฒด์˜ ์ฃผ์ž…์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค. ๋‹ค๋ฅธ ๋ฐฉ์‹๋“ค์€ Spring๊ณผ ๊ฐ™์€ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ๊นŒ๋‹ค๋กญ๋‹ค. (์˜์กด์„ฑ ์ฃผ์ž…์„ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋‹ด๋‹นํ•˜๋Š”๋ฐ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ) ํ•˜์ง€๋งŒ ์ƒ์„ฑ์ž ์ฃผ์ž… ๋ฐฉ์‹์„ ์ด์šฉํ•œ๋‹ค๋ฉด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์ด ์‰ฝ๋‹ค. ๋˜ํ•œ ๊ฐœ๋ฐœ์ž์˜ ์‹ค์ˆ˜๋กœ ์ˆœํ™˜ ์ฐธ์กฐ๋ฅผ ํ•˜๊ฒŒ ๋  ๊ฒฝ์šฐ ๋‹ค๋ฅธ ๋ฐฉ์‹๋“ค์€ ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๊ฐ€ ๋‚˜๋Š” ๋ฐ˜๋ฉด ์ƒ์„ฑ์ž ์ฃผ์ž… ๋ฐฉ์‹์€ ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ ๋” ์ข‹๋‹ค.

๊ฐ์ž์˜ ์žฅ๋‹จ์ ์ด ์žˆ์ง€๋งŒ ์ƒ์„ฑ์ž ์ฃผ์ž… ๋ฐฉ์‹์ด ์žฅ์ ์ด ์กฐ๊ธˆ ๋” ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์„ฑ์ž ์ฃผ์ž… ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค. ์ถ”๊ฐ€๋กœ ๋กฌ๋ณต(Lombok)์˜ @RequiredArgsConstructor ์–ด๋…ธํ…Œ์ด์…˜์€ ์ƒ์„ฑ์ž๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ์•Œ์•„์„œ ๋งŒ๋“ค์–ด ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•˜๊ธฐ ํŽธ๋ฆฌํ•˜๋‹ค. ๋กฌ๋ณต์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•  ๋ณ€์ˆ˜๋ฅผ final๋กœ ์„ ์–ธํ•˜๊ณ  ๊ทธ ์œ„์— ์œ„์˜ ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์—ฌ์ฃผ๋ฉด ๋œ๋‹ค.

๐Ÿ“š @InitBinder

@InitBinder๋Š” ์ƒ์†Œํ•œ ์–ด๋…ธํ…Œ์ด์…˜์ด์—ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ (๋งŽ์ด ํ•ด๋ณธ ๊ฑด ์•„๋‹ˆ์ง€๋งŒ) ์ง„ํ–‰ํ–ˆ๋˜ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ปจํŠธ๋กค๋Ÿฌ์˜ ๊ตฌ์„ฑ์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ จ ์„œ๋น„์Šค ๊ฐ์ฒด๊ฐ€ ์žˆ๊ณ  @GetMapping์ด๋‚˜ @PostMapping์˜ ์–ด๋…ธํ…Œ์ด์…˜๋“ค์„ ์‚ฌ์šฉํ•ด์„œ ๊ฒฝ๋กœ ์„ค์ •์„ ํ•ด์ฃผ๊ณ  ๊ฒฝ๋กœ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ ํ• ์ง€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒŒ ๋‹ค์˜€๋‹ค. ์ด ์–ด๋…ธํ…Œ์ด์…˜์ด ์–ด๋–ค ์—ญํ• ์„ ํ•˜๊ณ  ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•ด์„œ ์ฐพ์•„๋ดค๋‹ค.

@InitBinder ์–ด๋…ธํ…Œ์ด์…˜์€ @Controller๋‚˜ @ControllerAdvice ํด๋ž˜์Šค๊ฐ€ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ , WebDataBinder๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค. ์‰ฝ๊ฒŒ ๋งํ•ด ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋“ค์–ด์˜ค๋Š” ๋ฆฌํ€˜์ŠคํŠธ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ชจ๋ธ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ๋ชจ๋“  ์š”์ฒญ ์ „์— @InitBinder๊ฐ€ ๋ถ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

setAllowedField์™€ setDisallowedField๋ฅผ ํ†ตํ•ด ํ—ˆ์šฉํ•  ํ•„๋“œ, ํ—ˆ์šฉํ•˜์ง€ ์•Š์„ ํ•„๋“œ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. addCustomFormatter๋ฅผ ํ†ตํ•ด ํ•„๋“œ์˜ ํ˜•์‹์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๋˜ํ•œ, addValidators๋ฅผ ํ†ตํ•ด ์œ ํšจ์„ฑ ๊ฒ€์ฆ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฐ–์—๋„ ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์–ด ์—ฌ๋Ÿฌ ์„ค์ • ์‚ฌํ•ญ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

Pet Clinic์—์„œ๋Š” setDisallowedField์™€ addValidators๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. addValidators๋Š” ์™œ ์“ฐ๋Š”์ง€ ์ดํ•ด๊ฐ€ ๊ฐ€๋Š”๋ฐ setDisallowedField๋Š” ์™œ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์ดํ•ด๊ฐ€ ์•ˆ ๊ฐ€์„œ ์ฐพ์•„๋ดค๋Š”๋ฐ ๋‹ค๋“ค ์‚ฌ์šฉ๋ฒ•๋งŒ ์•Œ๋ ค์ฃผ๊ณ  ์™œ ์“ฐ๋Š”์ง€๋Š” ์•Œ๋ ค์ฃผ์ง€ ์•Š๋Š”๋‹ค. ์™ค๊นŒ...? ์•„์ด๋”” ํ•„๋“œ๋Š” ์š”์ฒญ์ด ๋“ค์–ด์™€๋„ ์„œ๋ฒ„์—์„œ ๊ฒฐ์ •ํ•˜๋Š” ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋Ÿฐ๊ฐ€..? ์•„๋ฌดํŠผ @InitBinder๋Š” ๋” ์ฐพ์•„๋ด์•ผ ํ•  ๊ฒƒ ๊ฐ™๋‹ค.

๐Ÿ“š @ModelAttribute

์ง€๊ธˆ๊นŒ์ง€ ๋ดค์—ˆ๋˜ @ModelAttribute ์–ด๋…ธํ…Œ์ด์…˜์€ ๋ฉ”์„œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ฃผ์–ด์ง€๋Š” ๊ฐ’์— ๋ถ™์–ด์žˆ๋Š” ๊ฒฝ์šฐ๋งŒ ๋ดค์—ˆ๋‹ค. ํ•˜์ง€๋งŒ Pet Clinic์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ฉ”์„œ๋“œ ์•ž์— ๋ถ™์–ด์žˆ์—ˆ๋‹ค. ์ด๋Š” @InitBinder๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์š”์ฒญ์ด ๋“ค์–ด์™”์„ ๋•Œ @ModelAttribute๊ฐ€ ์š”์ฒญ ์ฒ˜๋ฆฌ ์ „ ๋จผ์ € ์‹คํ–‰๋œ๋‹ค. @InitBinder๊ฐ€ ๋“ค์–ด์˜ค๋Š” ๊ฐ์ฒด๋ฅผ ๋‹ด์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด @ModelAttribute๋Š” ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์„ ํด๋ผ์ด์–ธํŠธ์— ๋ณด๋‚ผ model ๊ฐ์ฒด์— ๋‹ด๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

๐Ÿงฉ ๋งˆ๋ฌด๋ฆฌ

Controller๋“ค์„ ๋ณด๋ฉฐ ์ƒ์†Œํ•œ ๊ฐœ๋…๋“ค์„ ์ •๋ฆฌํ•˜๋‹ค ๋ณด๋‹ˆ ๊ธ€์ด ๊ธธ์–ด์กŒ๋‹ค. Pet Clinic์˜ Controller ๋ถ„์„์€ ๋‹ค์Œ ๊ธ€์—์„œ ํ•  ์˜ˆ์ •์ด๋‹ค. ๊ฐ์ฒด์— ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•  ๋•Œ ์ƒ์„ฑ์ž ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์žฅ์ ์ด ๋งŽ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋˜์–ด ์ข‹์•˜๋‹ค. ๊ทธ๋Ÿฐ๋ฐ @InitBinder๋Š” ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์™ธ์—” ์–ด๋–ค ์ด์œ ๋กœ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•„์ง ๊ฐ์ด ์•ˆ ์™€์„œ ๋” ์•Œ์•„๋ด์•ผ ํ•  ๊ฒƒ ๊ฐ™๋‹ค.

[์ฐธ๊ณ ]

๊ฐ์ฒด ์ƒ์„ฑ์ž ์ฃผ์ž… -
https://programforlife.tistory.com/111
@InitBinder -
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-initbinder
https://goodgid.github.io/Spring-MVC-InitBinder/
https://stackoverflow.com/questions/3801477/why-setdisallowedfields-for-id-spring-petclinic-example
@ModelAttribute -
https://memo-the-day.tistory.com/200

profile
๊ฐœ๋ฐœ์ž์ง€๋ง์ƒ

0๊ฐœ์˜ ๋Œ“๊ธ€