๐Ÿ๏ธ Spring/Web MVC

๐Ÿง ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ ์‹œ์Šคํ…œ์˜ ์ธ์ˆ˜๋ฅผ ์œ„ํ•ด ๊ธฐ๋Šฅ์ /๋น„๊ธฐ๋Šฅ์  ์š”๊ตฌ์‚ฌํ•ญ์„ ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ํ…Œ์ŠคํŠธํ•˜์—ฌ ๊ฐœ๋ฐœ์ด ์™„๋ฃŒ๋˜์—ˆ์Œ์„ ์ฆ๋ช…ํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ๋Š” ์œ„์™€ ๊ฐ™์ด ์‹œ์Šคํ…œ์˜ ์ธ์ˆ˜๋ฅผ ์œ„ํ•ด ์ž‘์„ฑํ•˜๋Š” ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. ์ฆ‰ ์ธ์ˆ˜ํ…Œ์Šค์˜ ๋ชฉ์ ์€ ์‚ฌ์šฉ์ž๋“ค์ด ์›ํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋Œ€๋กœ ๊ธฐ๋Šฅ์ด ์ž˜ ๋™์ž‘ํ•˜๋Š”์ง€๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ์ด๋ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์ธ์ˆ˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ, ๊ฐ€๋…์„ฑ์„ ๋†’์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿง RestAssured ์ฝ”๋“œ ์ˆจ๊ธฐ๊ธฐ ์ธ์ˆ˜ํ…Œ์ŠคํŠธ๋Š” ๊ทธ ๋ชฉ์ ์— ๋”ฐ๋ผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹Œ ์‚ฌ๋žŒ๋“ค์ด ๋ณด๋”๋ผ๋„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ €๋Š” ๊ฐœ๋ฐœ๊ณผ ๊ด€๋ จ๋œ ์ฝ”๋“œ๋ฅผ ์ตœ๋Œ€ํ•œ ๊ฐ์ถ”์–ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ์ดˆ์ ์„ ๋‘์–ด ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์‚ดํŽด๋ณด..
๐Ÿง ์„œ๋ก  ์Šคํ”„๋ง์—์„œ๋Š” ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ํ†ตํ•ด, ์ปจํŠธ๋กค๋Ÿฌ(ํ•ธ๋“ค๋Ÿฌ)๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „๊ณผ ํ›„์— ์ถ”๊ฐ€์ ์ธ ์ž‘์—…๋“ค์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ธ์ฆ ์ •๋ณด๋ฅผ ํ™•์ธํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์ด ์žˆ์„ ์ˆ˜ ์žˆ๊ฒ ๋„ค์š”. ์ธํ„ฐ์…‰ํ„ฐ์— ๋Œ€ํ•ด์„œ๋Š” ๋‹ค์Œ ๊ธ€์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”. ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์ธํ„ฐ์…‰ํ„ฐ๊ฐ€ ์‹ค์ œ๋กœ ์–ด๋–ค ์‹์œผ๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์šฐ์„  ์„ค๋ช…์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด HandlerExecutionChain๋ถ€ํ„ฐ ์‚ดํŽด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿง HandlerExecutionChain HandlerExecutionChain์€ ์œ„์™€ ๊ฐ™์ด ํ•ธ๋“ค๋Ÿฌ์™€, ํ•ด๋‹น ํ•ธ๋“ค๋Ÿฌ์— ์ ์šฉ๋  ์ธํ„ฐ์…‰ํ„ฐ๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. (@Controller์— @RequestMapping์œผ๋กœ ์ •์˜ํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ํ•˜๋‚˜์˜ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.) ์ฆ‰ HandlerExecution..
๐Ÿง ์„œ๋ก  ์Šคํ”„๋ง์—์„œ๋Š” ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก @ExceptionHandler ์™€ @ControllerAdvice๋ฅผ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค. ์ด ๋‘˜์˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋ผ ์–ด๋–ค ์‹์œผ๋กœ ๋™์ž‘ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ ๋‚ด๋ถ€ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๊ฐ€๋ฉฐ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿง ์Šคํ”„๋ง์˜ ์ดˆ๊ธฐํ™” ๊ณผ์ • ์šฐ์„  ์Šคํ”„๋ง์˜ ์ดˆ๊ธฐํ™” ๊ณผ์ •๋ถ€ํ„ฐ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. SpringAppliction์˜ run ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ, refreshContext()๋ฅผ ํ†ตํ•ด ๋นˆ๋“ค์„ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ์˜์กด๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์นฉ๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ์˜ ํ˜ธ์ถœ์„ ๋”ฐ๋ผ๊ฐ€๋‹ค๋ณด๋ฉด AbstractApplicationContext์˜ refresh()๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๊ณณ์—์„œ๋Š” finishBeanFactoryInitialization() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ด์ „ ๊ณผ์ •๋“ค์—์„œ ๋“ฑ๋ก๋˜์ง€..
๐Ÿง ์ƒํ™ฉ ์ธ์ฆ ์‹œ JWT๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ธ์ฆ์„ ์ง„ํ–‰ํ•˜๋ฉฐ, ํšŒ์›๊ฐ€์ž…๊ณผ ๋กœ๊ทธ์ธ์„ ์ œ์™ธํ•œ ๋ชจ๋“  URL์— ๋Œ€ํ•ด์„œ ์ธ์ฆ ๊ด€๋ จ Interceptor๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ๋“ฑ๋กํ•ด ๋‘” ์ƒํƒœ์˜€์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ์ธํ„ฐ์…‰ํ„ฐ์—์„œ๋Š” AccessToken์ด ์—†๋Š” ๊ฒฝ์šฐ ์˜ˆ์™ธ๋ฅผ throw ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€๋Š”๋ฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ์˜€์Šต๋‹ˆ๋‹ค. @Component public class LogInInterceptor implements HandlerInterceptor { // ์ƒ๋žต @Override public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) { AccessToken token = extractA..
๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋ง์”€๋“œ๋ฆฌ๋ฉด JSON ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋ฅผ ์œ„ํ•ด ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. @Controller public class MemberController { @GetMapping("/") public MemberDto getInfo(){ return new MemberDto("์‹ ๋™ํ›ˆ",12)); } } ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋‹น์—ฐํ•˜๊ฒŒ๋„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” @Controller๋ฅผ @RestController๋กœ ๋ฐ”๊พธ์–ด์ฃผ๊ฑฐ๋‚˜, @ResponseBody๋ฅผ ๋ถ™์—ฌ์ฃผ์–ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜๋Š” ResponseEntity๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ResponseEntity๋ฅผ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. @Controller public class MemberContr..
@RequestBody๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด MappingJackson2HttpMessageConverter๊ฐ€ ObjectMapper๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ๋ฐ”์ธ๋”ฉํ•ด์ค๋‹ˆ๋‹ค. ์ฆ‰ @RequestBody์˜ ๋ฐ”์ธ๋”ฉ ์กฐ๊ฑด์€ ObjectMapper์˜ ๋ฐ”์ธ๋”ฉ ์กฐ๊ฑด๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ณผ์ •์€ ๋งจ ๋งˆ์ง€๋ง‰์— ์ž์„ธํžˆ ์‚ดํŽด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์šฐ์„  ๊ธฐ๋ณธ์ ์ธ ์ƒํ™ฉ์—์„œ ๋ฐ”์ธ๋”ฉ์ด ๋˜๋Š” ์กฐ๊ฑด์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ์กฐ๊ฑด (๋ชจ๋“  ์ ‘๊ทผ์ œ์–ด์ž) ๊ธฐ๋ณธ์ƒ์„ฑ์ž + (public) Getter ๊ฐ€๋Šฅ (๋ชจ๋“  ์ ‘๊ทผ์ œ์–ด์ž) ๊ธฐ๋ณธ์ƒ์„ฑ์ž + (๋ชจ๋“  ์ ‘๊ทผ์ œ์–ด์ž) Setter ๊ฐ€๋Šฅ ๋ถˆ๊ฐ€๋Šฅํ•œ ์กฐ๊ฑด ๊ธฐ๋ณธ์ƒ์„ฑ์ž๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ ๊ธฐ๋ณธ์ƒ์„ฑ์ž๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ (๋ชจ๋“  ์ ‘๊ทผ์ œ์–ด์ž) ๊ธฐ๋ณธ์ƒ์„ฑ์ž + (public์ด ์•„๋‹Œ ๋‹ค๋ฅธ ์ ‘๊ทผ์ œ์–ด์ž) Getter ObjectMapper ์กฐ๊ฑด ๋ณ€๊ฒฝํ•˜๊ธฐ object..
์ƒํ™ฉ 1 - String ํƒ€์ž…์˜ List์ธ ๊ฒฝ์šฐ "๋ฆฌ์ŠคํŠธ๋ช…" : [ "์š”์†Œ1", "์š”์†Œ2", "์š”์†Œ3", "์š”์†Œ4" ] ์š”์†Œ์˜ " "๋Š” ์ƒ๋žต๊ฐ€๋Šฅ ์˜ˆ์‹œ public class Blog { private String address; private List visitor = new ArrayList(); public List getVisitor() { return visitor; } public String getAddress() { return address; } public Blog() { } } ํ…Œ์ŠคํŠธ์ฝ”๋“œ @SpringBootTest class ObjectMapperTest { private ObjectMapper objectMapper = new ObjectMapper(); private static ..
์ด์ „๊นŒ์ง€์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํฌ์ŠคํŒ…์—์„œ๋Š” API ๋ฐฉ์‹์ด ์•„๋‹Œ ๊ธฐ๋ณธ์ ์ธ ํ™”๋ฉด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ์‹์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ค๋ฃจ์—ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ API ํ†ต์‹ ์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ, ํ™”๋ฉด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์€ ์•„๋ฌด๋Ÿฐ ์“ธ๋ชจ๊ฐ€ ์—†๋‹ค. ๋”ฐ๋ผ์„œ API ํ†ต์‹ ์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ์—๋Š” ์–ด๋–ค ์‹์œผ๋กœ ์˜ˆ์™ธ ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ •ํ•˜๊ณ , ๊ทธ์— ๋งž๊ฒŒ json์œผ๋กœ ์˜ˆ์™ธ ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค. ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” BasicErrorController๋ฅผ ํ†ตํ•ด ๊ธฐ๋ณธ์ ์ธ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค๊ณ  ํ–ˆ์—ˆ๋‹ค. API ์˜ˆ์™ธ ๋˜ํ•œ ์ด๊ณณ์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•ด ์ฃผ๋Š”๋ฐ, ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” json์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•์‹์ด๋‹ค. Accept ํ—ค๋”๊ฐ€ application/json์ธ ๊ฒฝ์šฐ { "timestamp": "2022-01-07T13:17:21..
๋ง ๋ž‘
'๐Ÿ๏ธ Spring/Web MVC' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๊ธ€ ๋ชฉ๋ก