전체적으로 정리 (로그인, 상품 페이지)
📚 1. 로그인 구동 방식
ArgumentResolver 적용전을 대상으로 한다.
인터셉터 : 특정 URI로 요청시 Controller로 가는 요청을 가로채는 역할을 한다.
ArgumentResolver 적용전을 대상으로 한다.
인터셉터 : 특정 URI로 요청시 Controller로 가는 요청을 가로채는 역할을 한다.
스프링 인터셉터 호출 흐름
정상 흐름
preHandle
: 컨트롤러 호출 전에 호출된다. (더 정확히는 핸들러 어댑터 호출 전에 호출된다.)preHandle
의 응답값이true
이면 다음으로 진행하고,false
이면 더는 진행하지 않는다.false
인 경우 나머지 인터셉터는 물론이고, 핸들러 어댑터도 호출되지 않는다. 그림에서 1번에서 끝이 나버린다.
postHandle
: 컨트롤러 호출 후에 호출된다. (더 정확히는 핸들러 어댑터 호출 후에 호출된다.)afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.- 뷰가 렌더링 된 이후에 호출된다는 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다. (응답이 사용자에게 도달하는 것과는 다른 의미이다.)
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
- 질문 참고 : https://www.inflearn.com/questions/445319
스프링 인터셉터 예외 상황
예외가 발생시
preHandle
: 컨트롤러 호출 전에 호출된다.postHandle
: 컨트롤러에서 예외가 발생하면postHandle
은 호출되지 않는다.afterCompletion
:afterCompletion
은 항상 호출된다. 이 경우 예외(ex
)를 파라미터로 받아서 어떤 예외가 발생했는지 로그로 출력할 수 있다.
WebConfig - 인터셉터 등록
📖 A. 홈 화면 실행하였을 때
LogInterceptor
를 실행한다.
실행했을 때 전체적인 log 출력 내용
h.login.web.interceptor.LogInterceptor : LogInterceptor REQUEST [e725f1cc-7508-4e39-9d2a-9183f6f70096][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="home"; model={}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor RESPONSE [e725f1cc-7508-4e39-9d2a-9183f6f70096][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
LogInterceptor
클래스에서preHandle
,postHandle
,afterCompletion
실행 결과이다.preHandle
,postHandle
,afterCompletion
는HandlerInterceptor
인터페이스로부터 상속받아 구현하였다.
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor REQUEST [e725f1cc-7508-4e39-9d2a-9183f6f70096][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
부터 보면,
hello.login.web.HomeController#homeLoginV3Spring(Member, Model)
를 실행한다.
@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember, Model model
// 이미 로그인한 사용자가 있는지 찾는다.
// 이 기능은 세션을 생성하지 않는다.
여기서 SessionConst.LOGIN_MEMBER
는
이다!
✏️ preHandle 실행 정리
- 세션에 회원 데이터가 없으면 home으로 이동한다.
- 세션이 유지되면 로그인으로 이동한다.
(2) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="home"; model={}]]
부터 보면 LogInterceptor postHandle [ModelAndView [view="home"; model={}]]
를 실행한다.
(3) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor RESPONSE [e725f1cc-7508-4e39-9d2a-9183f6f70096][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
부터 보면 hello.login.web.HomeController#homeLoginV3Spring(Member, Model)
를 실행하는데 이는 요청 완료된 이후 실행되는 결과이다.
✏️ preHandle, postHandle, afterCompletion 실행 정리
컨트롤러 호출 전에preHandle
을 실행한다.
컨트롤러 호출 후에postHandle
을 실행한다. (예외 발생시 호출하지 않는다.)
뷰가 렌더링 된 이후에afterCompletion
호출된다.
📖 B. 회원 가입 화면 실행했을 때
실행했을 때 전체적인 log 출력 내용
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [d06f4567-8f98-4b7e-bb72-f40404f44117][/members/add][hello.login.web.member.MemberController#addForm(Member)]
hello.login.web.member.MemberController : input member=Member(id=null, loginId=null, name=null, password=null)
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="members/addMemberForm"; model={member=Member(id=null, loginId=null, name=null, password=null), org.springframework.validation.BindingResult.member=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [d06f4567-8f98-4b7e-bb72-f40404f44117][/members/add][hello.login.web.member.MemberController#addForm(Member)]
LogInterceptor
클래스에서preHandle
,postHandle
,afterCompletion
실행 결과이다.
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [d06f4567-8f98-4b7e-bb72-f40404f44117][/members/add][hello.login.web.member.MemberController#addForm(Member)]
hello.login.web.member.MemberController#addForm(Member)
를 실행한다.
- 여기서
input member={}
가 로그에 출력된다. templates/members/addMemberForm
회원가입html
화면을 띄워준다.
templates/members/addMemberForm
(2) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="members/addMemberForm"; model={member=Member(id=null, loginId=null, name=null, password=null), org.springframework.validation.BindingResult.member=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
addMemberForm
을 기준으로 현재 입력된 값이 없기 때문에 validation.BindingResult가 실행된다.
(3) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [d06f4567-8f98-4b7e-bb72-f40404f44117][/members/add][hello.login.web.member.MemberController#addForm(Member)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 C. 회원가입 성공했을 경우
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [0d5564f4-e550-468d-b29f-4957b4881002][/members/add][hello.login.web.member.MemberController#save(Member, BindingResult)]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="redirect:/"; model={}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [0d5564f4-e550-468d-b29f-4957b4881002][/members/add][hello.login.web.member.MemberController#save(Member, BindingResult)]
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [73844fc4-6899-4457-bd6d-f40a5fa8250d][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="home"; model={}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [73844fc4-6899-4457-bd6d-f40a5fa8250d][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [0d5564f4-e550-468d-b29f-4957b4881002][/members/add][hello.login.web.member.MemberController#save(Member, BindingResult)]
hello.login.web.member.MemberController#save(Member, BindingResult)
를 실행한다.
- 만약 범위에 해당되지 않은 값을 입력했는지 검증한다.
- 입력했다면 다시 회원가입 페이지로 이동한다.
- 범위에 해당되는 값을 입력했다면 레포지토리 저장소에 저장한다.
(2) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="redirect:/"; model={}]]
(3) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [0d5564f4-e550-468d-b29f-4957b4881002][/members/add][hello.login.web.member.MemberController#save(Member, BindingResult)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
(4) 이외
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [73844fc4-6899-4457-bd6d-f40a5fa8250d][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="home"; model={}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [73844fc4-6899-4457-bd6d-f40a5fa8250d][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
- 이는 홈 화면에서 이미 설명하였다.
📖 D. 로그인 화면
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [0b17592d-eaf7-41a3-89e0-4f6ca9913cc6][/login][hello.login.web.login.LoginController#loginForm(LoginForm)]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="login/loginForm"; model={loginForm=LoginForm(loginId=null, password=null), org.springframework.validation.BindingResult.loginForm=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [0b17592d-eaf7-41a3-89e0-4f6ca9913cc6][/login][hello.login.web.login.LoginController#loginForm(LoginForm)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [0b17592d-eaf7-41a3-89e0-4f6ca9913cc6][/login][hello.login.web.login.LoginController#loginForm(LoginForm)]
hello.login.web.login.LoginController#loginForm(LoginForm)
를 실행한다.
LoginController
LoginForm 클래스
template/login/loginForm
실행
(2) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="login/loginForm"; model={loginForm=LoginForm(loginId=null, password=null), org.springframework.validation.BindingResult.loginForm=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
(3) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [0b17592d-eaf7-41a3-89e0-4f6ca9913cc6][/login][hello.login.web.login.LoginController#loginForm(LoginForm)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 E. 로그인 실패
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [04de1c46-26db-4e61-b0a6-348193f03d57][/login][hello.login.web.login.LoginController#loginV4(LoginForm, BindingResult, String, HttpServletRequest)]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="login/loginForm"; model={loginForm=LoginForm(loginId=test, password=test), org.springframework.validation.BindingResult.loginForm=org.springframework.validation.BeanPropertyBindingResult: 1 errors
Error in object 'loginForm': codes [loginFail.loginForm,loginFail]; arguments []; default message [아이디 또는 비밀번호가 맞지 않습니다.]}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [04de1c46-26db-4e61-b0a6-348193f03d57][/login][hello.login.web.login.LoginController#loginV4(LoginForm, BindingResult, String, HttpServletRequest)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [04de1c46-26db-4e61-b0a6-348193f03d57][/login][hello.login.web.login.LoginController#loginV4(LoginForm, BindingResult, String, HttpServletRequest)]
hello.login.web.login.LoginController#loginV4(LoginForm, BindingResult, String, HttpServletRequest)
가 실행된다.
- 만약 범위에 해당되지 않은 값을 입력했는지 검증한다. (
@Valid @ModelAttribute LoginForm form
에 값이 담겨있다.- 검증되지 않았을 시 로그인 화면으로 돌아간다.
- id, password를 검증한다.
- 등록되지 않은 id, password를 입력시 다시 로그인 화면으로 돌아간다.
- 현재는 저장되어 있지 않은
id
,password
를 입력했으므로 세션이 실행되지 않고 위에서 끝난다.
HttpSession session = request.getSession();
// 세션에 로그인 회원 정보 보관
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
request.getSession();
- 이전에 생성한 세션이 있으면 세션을 반환한다.
- 세션이 없으면 신규 세션을 생성해야 한다.
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
- 세션에 로그인 회원 정보 보관한다.
return "redirect:" + redirectURL;
- 다시 요청 URL로 이동한다.
(2) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="login/loginForm"; model={loginForm=LoginForm(loginId=test, password=test), org.springframework.validation.BindingResult.loginForm=org.springframework.validation.BeanPropertyBindingResult: 1 errors
Error in object 'loginForm': codes [loginFail.loginForm,loginFail]; arguments []; default message [아이디 또는 비밀번호가 맞지 않습니다.]}]]
- 입력한
id
와password
를 확인해보니, 검증 결과 error가 발생한다.
위 preHandle
에서 설명한 loginV4
를 확인시 쉽게 알 수 있다.
if (loginMember == null) {
bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
return "login/loginForm";
}
가 실행되어 다시 로그인 화면으로 이동한다.
(3) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [04de1c46-26db-4e61-b0a6-348193f03d57][/login][hello.login.web.login.LoginController#loginV4(LoginForm, BindingResult, String, HttpServletRequest)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 F. 로그인 성공
첫 로그인시, 주소에 세션 id가 출력된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [9c6c80a6-cd9d-4ad4-ab2e-492f25a259c9][/login][hello.login.web.login.LoginController#loginV4(LoginForm, BindingResult, String, HttpServletRequest)]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="redirect:/"; model={}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [9c6c80a6-cd9d-4ad4-ab2e-492f25a259c9][/login][hello.login.web.login.LoginController#loginV4(LoginForm, BindingResult, String, HttpServletRequest)]
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [c41ecf9d-b75d-4193-8a8b-7a4c179d60c0][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="loginHome"; model={member=Member(id=1, loginId=test, name=테스트, password=test!), org.springframework.validation.BindingResult.member=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [c41ecf9d-b75d-4193-8a8b-7a4c179d60c0][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [9c6c80a6-cd9d-4ad4-ab2e-492f25a259c9][/login][hello.login.web.login.LoginController#loginV4(LoginForm, BindingResult, String, HttpServletRequest)]
hello.login.web.login.LoginController#loginV4(LoginForm, BindingResult, String, HttpServletRequest)
가 실행된다.
- 만약 범위에 해당되지 않은 값을 입력했는지 검증한다. (
@Valid @ModelAttribute LoginForm form
에 값이 담겨있다.)- 검증되지 않았을 시 로그인 화면으로 돌아간다.
- id, password를 검증한다.
- 등록되지 않은 id, password를 입력시 다시 로그인 화면으로 돌아간다.
- 현재는 저장되어 있는 id, password를 입력했으므로 세션이 실행된다.
HttpSession session = request.getSession();
// 세션에 로그인 회원 정보 보관
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
request.getSession();
- 이전에 생성한 세션이 있으면 세션을 반환한다.
- 세션이 없으면 신규 세션을 생성해야 한다.
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
- 세션에 로그인 회원 정보 보관한다.
return "redirect:" + redirectURL;
- 다시 요청 URL로 이동한다.
(2) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="redirect:/"; model={}]]
- 로그인에 성공하였으므로 이전에 사용한 공간으로 이동한다.
(3) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [9c6c80a6-cd9d-4ad4-ab2e-492f25a259c9][/login][hello.login.web.login.LoginController#loginV4(LoginForm, BindingResult, String, HttpServletRequest)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
(4) 이외 (loginHome의 preHandle, postHandle, afterCompletion)
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [c41ecf9d-b75d-4193-8a8b-7a4c179d60c0][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
homeLoginV3Spring
클래스를 상으로 컨트롤러 호출 전 세팅을 한다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="loginHome"; model={member=Member(id=1, loginId=test, name=테스트, password=test!), org.springframework.validation.BindingResult.member=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
loginHome
이 실행 된다.
templates/loginHome
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [c41ecf9d-b75d-4193-8a8b-7a4c179d60c0][/][hello.login.web.HomeController#homeLoginV3Spring(Member, Model)]
📚 2. 상품 페이지 구동 방식
📖 A. Item
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [a8c9d14d-8bcf-4512-8e7b-1c268a58728c][/items][hello.login.web.item.ItemController#items(Model)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/items"; model={items=[Item(id=1, itemName=itemA, price=10000, quantity=10), Item(id=2, itemName=itemB, price=20000, quantity=20)]}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [a8c9d14d-8bcf-4512-8e7b-1c268a58728c][/items][hello.login.web.item.ItemController#items(Model)]
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [a8c9d14d-8bcf-4512-8e7b-1c268a58728c][/items][hello.login.web.item.ItemController#items(Model)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/items"; model={items=[Item(id=1, itemName=itemA, price=10000, quantity=10), Item(id=2, itemName=itemB, price=20000, quantity=20)]}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [a8c9d14d-8bcf-4512-8e7b-1c268a58728c][/items][hello.login.web.item.ItemController#items(Model)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [a8c9d14d-8bcf-4512-8e7b-1c268a58728c][/items][hello.login.web.item.ItemController#items(Model)]
hello.login.web.item.ItemController#items(Model)
을 실행된다.
itemRepository
에 있는 모든 아이템들을model
에 추가한다.
templates/items/items
- 모델에 있는 요소들을 (테이블 형식으로) 화면에 출력한다.
(2) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items
입력한 내용들을 검증한다. (추가 알게 되면 수정하기)
(3) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/items"; model={items=[Item(id=1, itemName=itemA, price=10000, quantity=10), Item(id=2, itemName=itemB, price=20000, quantity=20)]}]]
items/items
에 아이템 2개를 띄워준다.
(4) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [a8c9d14d-8bcf-4512-8e7b-1c268a58728c][/items][hello.login.web.item.ItemController#items(Model)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 B. 상품 등록
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [d4d83c88-40b2-48dd-99b0-739fce6c25f5][/items/add][hello.login.web.item.ItemController#addForm(Model)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/add
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/addForm"; model={item=Item(id=null, itemName=null, price=null, quantity=null), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [d4d83c88-40b2-48dd-99b0-739fce6c25f5][/items/add][hello.login.web.item.ItemController#addForm(Model)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [d4d83c88-40b2-48dd-99b0-739fce6c25f5][/items/add][hello.login.web.item.ItemController#addForm(Model)]
hello.login.web.item.ItemController#addForm(Model)
이 실행된다.
templates/items/addForm
(2) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items
입력한 내용들을 검증한다. (추가 알게 되면 수정하기)
(3) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/addForm"; model={item=Item(id=null, itemName=null, price=null, quantity=null), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
- 초기값은
null
이다.
(4) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [d4d83c88-40b2-48dd-99b0-739fce6c25f5][/items/add][hello.login.web.item.ItemController#addForm(Model)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 C. 상품 등록 실패
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [74a14543-e8fb-4bb7-ad5f-2747a1ed7aab][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/add
hello.login.web.item.ItemController : errors=org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'item' on field 'quantity': rejected value [111111]; codes [Max.item.quantity,Max.quantity,Max.java.lang.Integer,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.quantity,quantity]; arguments []; default message [quantity],9999]; default message [9999 이하여야 합니다]
Field error in object 'item' on field 'price': rejected value [12]; codes [Range.item.price,Range.price,Range.java.lang.Integer,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.price,price]; arguments []; default message [price],1000000,1000]; default message [1000에서 1000000 사이여야 합니다]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/addForm"; model={item=ItemSaveForm(itemName=itemA, price=12, quantity=111111), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'item' on field 'quantity': rejected value [111111]; codes [Max.item.quantity,Max.quantity,Max.java.lang.Integer,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.quantity,quantity]; arguments []; default message [quantity],9999]; default message [9999 이하여야 합니다]
Field error in object 'item' on field 'price': rejected value [12]; codes [Range.item.price,Range.price,Range.java.lang.Integer,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.price,price]; arguments []; default message [price],1000000,1000]; default message [1000에서 1000000 사이여야 합니다]}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [74a14543-e8fb-4bb7-ad5f-2747a1ed7aab][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [74a14543-e8fb-4bb7-ad5f-2747a1ed7aab][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)
가 실행된다.
(2) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/add
(3) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
hello.login.web.item.ItemController : errors=org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'item' on field 'quantity': rejected value [111111]; codes [Max.item.quantity,Max.quantity,Max.java.lang.Integer,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.quantity,quantity]; arguments []; default message [quantity],9999]; default message [9999 이하여야 합니다]
Field error in object 'item' on field 'price': rejected value [12]; codes [Range.item.price,Range.price,Range.java.lang.Integer,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.price,price]; arguments []; default message [price],1000000,1000]; default message [1000에서 1000000 사이여야 합니다]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/addForm"; model={item=ItemSaveForm(itemName=itemA, price=12, quantity=111111), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'item' on field 'quantity': rejected value [111111]; codes [Max.item.quantity,Max.quantity,Max.java.lang.Integer,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.quantity,quantity]; arguments []; default message [quantity],9999]; default message [9999 이하여야 합니다]
Field error in object 'item' on field 'price': rejected value [12]; codes [Range.item.price,Range.price,Range.java.lang.Integer,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.price,price]; arguments []; default message [price],1000000,1000]; default message [1000에서 1000000 사이여야 합니다]}]]
9999 이하여야 합니다
,1000에서 1000000 사이여야 합니다
: 오류 메세지를 넣은 적도 없는 데 이와 같이 출력된다.- 이는
hibernate-validator
가 기본으로 제공하는 오류 메세지이다. @Range
,@Max
범위를 벗어난 값을 입력하였기에 발생하였다.- 검증 2 - Bean Validation 수업에서 말씀해주셨다.
- 이는
(4) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [74a14543-e8fb-4bb7-ad5f-2747a1ed7aab][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 D. 상품 등록 실패 2
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [d705733c-31e8-4c2e-9006-72c247f7e8ff][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/add
hello.login.web.item.ItemController : errors=org.springframework.validation.BeanPropertyBindingResult: 1 errors
Error in object 'item': codes [totalPriceMin.item,totalPriceMin]; arguments [10000,1000]; default message [null]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/addForm"; model={item=ItemSaveForm(itemName=123, price=1000, quantity=1), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 1 errors
Error in object 'item': codes [totalPriceMin.item,totalPriceMin]; arguments [10000,1000]; default message [null]}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [d705733c-31e8-4c2e-9006-72c247f7e8ff][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [d705733c-31e8-4c2e-9006-72c247f7e8ff][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)
가 실행된다.
(2) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/add
(3) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
hello.login.web.item.ItemController : errors=org.springframework.validation.BeanPropertyBindingResult: 1 errors
Error in object 'item': codes [totalPriceMin.item,totalPriceMin]; arguments [10000,1000]; default message [null]
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/addForm"; model={item=ItemSaveForm(itemName=123, price=1000, quantity=1), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 1 errors
Error in object 'item': codes [totalPriceMin.item,totalPriceMin]; arguments [10000,1000]; default message [null]}]]
- 이게 무엇일까? :
price
은 1000,quantity
은 1을 주었다.totalPriceMin
최소 값이10,000
인데 현재 결과1,000 * 1
로 작은 값이 입력되어 발생한 오류이다.
✔️ 메세지, 오류 설정
application.properties
spring.messages.basename=messages,errors
를 지정해야 한다.
이렇게 할시 messages.properties
, errors.properties
두 파일을 모두 인식한다.
생략할 시 messages.properties
를 기본으로 인식한다.
messages.properties
hello=안녕
hello.name=안녕 {0}
label.item=상품
label.item.id=상품 ID
label.item.itemName=상품명
label.item.price=가격
label.item.quantity=수량
page.items=상품 목록
page.item=상품 상세
page.addItem=상품 등록
page.updateItem=상품 수정
button.save=저장
button.cancel=취소
messages_en.properties
hello=hello
hello.name=hello {0}
label.item=Item
label.item.id=Item ID
label.item.itemName=Item Name
label.item.price=price
label.item.quantity=quantity
page.items=Item List
page.item=Item Detail
page.addItem=Item Add
page.updateItem=Item Update
button.save=Save
button.cancel=Cancel
errors.properties
#required.item.itemName=상품 이름은 필수입니다.
#range.item.price=가격은 {0} ~ {1} 까지 허용합니다.
#max.item.quantity=수량은 최대 {0} 까지 허용합니다.
#totalPriceMin=가격 * 수량의 합은 {0}원 이상이어야 합니다. 현재 값 = {1}
#==ObjectError==
#Level1
totalPriceMin.item=상품의 가격 * 수량의 합은 {0}원 이상이어야 합니다. 현재 값 = {1}
#Level2 - 생략
totalPriceMin=전체 가격은 {0}원 이상이어야 합니다. 현재 값 = {1}
#==FieldError==
#Level1
required.item.itemName=상품 이름은 필수입니다.
range.item.price=가격은 {0} ~ {1} 까지 허용합니다.
max.item.quantity=수량은 최대 {0} 까지 허용합니다.
#Level2 - 생략
#Level3
required.java.lang.String = 필수 문자입니다.
required.java.lang.Integer = 필수 숫자입니다.
min.java.lang.String = {0} 이상의 문자를 입력해주세요.
min.java.lang.Integer = {0} 이상의 숫자를 입력해주세요.
range.java.lang.String = {0} ~ {1} 까지의 문자를 입력해주세요.
range.java.lang.Integer = {0} ~ {1} 까지의 숫자를 입력해주세요.
max.java.lang.String = {0} 까지의 숫자를 허용합니다.
max.java.lang.Integer = {0} 까지의 숫자를 허용합니다.
#Level4
required = 필수 값 입니다.
min= {0} 이상이어야 합니다.
range= {0} ~ {1} 범위를 허용합니다.
max= {0} 까지 허용합니다.
typeMismatch.java.lang.Integer=숫자를 입력해주세요.
typeMismatch=타입 오류입니다.
#Bean Validation 추가
NotBlank={0} 공백X
Range={0}, {2} ~ {1} 허용
Max={0}, 최대 {1}
errors.properties
#Level1
totalPriceMin.item=상품의 가격 * 수량의 합은 {0}원 이상이어야 합니다. 현재 값 = {1}
가 현재 실행된다.
(4) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [d705733c-31e8-4c2e-9006-72c247f7e8ff][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 E. 상품 등록 성공
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [d5284dee-e16c-49c6-896b-1ce7484f6463][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/add
hello.login.domain.item.ItemRepository : Item id=3
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="redirect:/items/{itemId}"; model={itemId=3, status=true}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [d5284dee-e16c-49c6-896b-1ce7484f6463][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [9b49a512-566a-4644-a422-d3934a66f7b6][/items/3][hello.login.web.item.ItemController#item(long, Model)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/3
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/item"; model={item=Item(id=3, itemName=itemA, price=1000, quantity=10), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [9b49a512-566a-4644-a422-d3934a66f7b6][/items/3][hello.login.web.item.ItemController#item(long, Model)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [d5284dee-e16c-49c6-896b-1ce7484f6463][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)
가 실행된다.
(2) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/add
(3) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
hello.login.domain.item.ItemRepository : Item id=3
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="redirect:/items/{itemId}"; model={itemId=3, status=true}]]
(4) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [d5284dee-e16c-49c6-896b-1ce7484f6463][/items/add][hello.login.web.item.ItemController#addItem(ItemSaveForm, BindingResult, RedirectAttributes)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
(5) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [9b49a512-566a-4644-a422-d3934a66f7b6][/items/3][hello.login.web.item.ItemController#item(long, Model)]
hello.login.web.item.ItemController#item(long, Model)
이 실행된다.
templates/items/item
- 정상적으로 저장되어 화면 출력된다. (읽기만 가능하다.)
(6) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/3
(7) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/item"; model={item=Item(id=3, itemName=itemA, price=1000, quantity=10), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
(8) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [9b49a512-566a-4644-a422-d3934a66f7b6][/items/3][hello.login.web.item.ItemController#item(long, Model)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 F. 상품 등록 후, 상품 목록 화면
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [678ecca3-ddf9-4a3d-8b27-eb01ca2d7401][/items][hello.login.web.item.ItemController#items(Model)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/items"; model={items=[Item(id=1, itemName=itemA, price=10000, quantity=10), Item(id=2, itemName=itemB, price=20000, quantity=20), Item(id=3, itemName=itemA, price=1000, quantity=10)]}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [678ecca3-ddf9-4a3d-8b27-eb01ca2d7401][/items][hello.login.web.item.ItemController#items(Model)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [678ecca3-ddf9-4a3d-8b27-eb01ca2d7401][/items][hello.login.web.item.ItemController#items(Model)]
hello.login.web.item.ItemController#items(Model)
을 실행된다.
itemRepository
에 있는 모든 아이템들을model
에 추가한다.
templates/items/items
- 모델에 있는 요소들을 (테이블 형식으로) 화면에 출력한다.
(2) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items
입력한 내용들을 검증한다. (추가 알게 되면 수정하기)
(3) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/items"; model={items=[Item(id=1, itemName=itemA, price=10000, quantity=10), Item(id=2, itemName=itemB, price=20000, quantity=20), Item(id=3, itemName=itemA, price=1000, quantity=10)]}]]
items/items
에 아이템 3개를 띄워준다. (하나가 추가 됨)
(4) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [678ecca3-ddf9-4a3d-8b27-eb01ca2d7401][/items][hello.login.web.item.ItemController#items(Model)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 G. 상품 수정
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [78a5a29b-416f-48d5-af25-7575db3faab3][/items/2][hello.login.web.item.ItemController#item(long, Model)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/2
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/item"; model={item=Item(id=2, itemName=itemB, price=20000, quantity=20), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [78a5a29b-416f-48d5-af25-7575db3faab3][/items/2][hello.login.web.item.ItemController#item(long, Model)]
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [abcdf814-0bf4-4a34-8c8c-d277bbf1e8e5][/items/2/edit][hello.login.web.item.ItemController#editForm(Long, Model)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/2/edit
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/editForm"; model={item=Item(id=2, itemName=itemB, price=20000, quantity=20), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [abcdf814-0bf4-4a34-8c8c-d277bbf1e8e5][/items/2/edit][hello.login.web.item.ItemController#editForm(Long, Model)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [78a5a29b-416f-48d5-af25-7575db3faab3][/items/2][hello.login.web.item.ItemController#item(long, Model)]
hello.login.web.item.ItemController#item(long, Model)
이 실행된다.
templates/items/item
- 정상적으로 저장되어 화면 출력된다. (읽기만 가능하다.)
(2) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/2
입력한 내용들을 검증한다. (추가 알게 되면 수정하기)
(3) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/item"; model={item=Item(id=2, itemName=itemB, price=20000, quantity=20), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
items/item
에 선택된item
이 띄워진다.
(4) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [78a5a29b-416f-48d5-af25-7575db3faab3][/items/2][hello.login.web.item.ItemController#item(long, Model)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
(5) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [abcdf814-0bf4-4a34-8c8c-d277bbf1e8e5][/items/2/edit][hello.login.web.item.ItemController#editForm(Long, Model)]
hello.login.web.item.ItemController#editForm(Long, Model)
이 실행된다.
itemId
를 찾아model
에 추가한다.
templates/items/editForm
- 찾은
item
을 화면에 출력한다.
(6) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/2/edit
입력한 내용들을 검증한다. (추가 알게 되면 수정하기)
(7) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/editForm"; model={item=Item(id=2, itemName=itemB, price=20000, quantity=20), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
- 찾은
items
을 이제 보낸다.
(8) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [abcdf814-0bf4-4a34-8c8c-d277bbf1e8e5][/items/2/edit][hello.login.web.item.ItemController#editForm(Long, Model)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 H. 상품 수정 실행
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [1fde2503-4ac0-49b6-b762-469aa48216d1][/items/2/edit][hello.login.web.item.ItemController#edit(Long, ItemUpdateForm, BindingResult)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/2/edit
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="redirect:/items/{itemId}"; model={}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [1fde2503-4ac0-49b6-b762-469aa48216d1][/items/2/edit][hello.login.web.item.ItemController#edit(Long, ItemUpdateForm, BindingResult)]
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [e33e50eb-afc5-42ba-85a5-b6c21be4f826][/items/2][hello.login.web.item.ItemController#item(long, Model)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/2
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/item"; model={item=Item(id=2, itemName=itemC, price=5000, quantity=300), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [e33e50eb-afc5-42ba-85a5-b6c21be4f826][/items/2][hello.login.web.item.ItemController#item(long, Model)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [1fde2503-4ac0-49b6-b762-469aa48216d1][/items/2/edit][hello.login.web.item.ItemController#edit(Long, ItemUpdateForm, BindingResult)]
hello.login.web.item.ItemController#edit(Long, ItemUpdateForm, BindingResult)
이 실행된다.
- 만약 가격과 수량이 등록할 때와 마찬가지로
- 입력되지 않거나
- 10,000 미만일 시
totalPriceMin
을 호출한다. - 이는 검증에 실패한 경우이다.
- 만약 입력에 성공했다면
- 업데이트 한 후
- 다시
items/itemId
로 이동한다. (http://localhost:8080/items/2
)
리다이렉션(리다이렉트) 이해
: 웹 브라우저는 3xx 응답 결과에 Location
헤더가 있으면, Location
위치로 자동으로 이동한다.
➡️ 현재 Location
: items/2
(2) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/2/edit
입력한 내용들을 검증한다. (추가 알게 되면 수정하기)
(3) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="redirect:/items/{itemId}"; model={}]]
(4) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [1fde2503-4ac0-49b6-b762-469aa48216d1][/items/2/edit][hello.login.web.item.ItemController#edit(Long, ItemUpdateForm, BindingResult)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
(5) preHandle
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [e33e50eb-afc5-42ba-85a5-b6c21be4f826][/items/2][hello.login.web.item.ItemController#item(long, Model)]
hello.login.web.item.ItemController#item(long, Model)
이 실행된다.
templates/items/item
- 정상적으로 저장되어 화면 출력된다. (읽기만 가능하다.)
(6) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items/2
입력한 내용들을 검증한다. (추가 알게 되면 수정하기)
(7) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/item"; model={item=Item(id=2, itemName=itemC, price=5000, quantity=300), org.springframework.validation.BindingResult.item=org.springframework.validation.BeanPropertyBindingResult: 0 errors}]]
items/{itemId}/edit
에서 수정한item
이 적용된다.
(8) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [e33e50eb-afc5-42ba-85a5-b6c21be4f826][/items/2][hello.login.web.item.ItemController#item(long, Model)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
📖 I. 최종 결과
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [19914b48-363d-480a-bf0f-4d94d7f36c65][/items][hello.login.web.item.ItemController#items(Model)]
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/items"; model={items=[Item(id=1, itemName=itemA, price=10000, quantity=10), Item(id=2, itemName=itemC, price=5000, quantity=300), Item(id=3, itemName=itemA, price=1000, quantity=10)]}]]
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [19914b48-363d-480a-bf0f-4d94d7f36c65][/items][hello.login.web.item.ItemController#items(Model)]
(1) preHandle 실행 결과
preHandle
: 컨트롤러 호출 전
h.login.web.interceptor.LogInterceptor : LogInterceptor preHandle REQUEST [19914b48-363d-480a-bf0f-4d94d7f36c65][/items][hello.login.web.item.ItemController#items(Model)]
hello.login.web.item.ItemController#items(Model)
을 실행된다.
itemRepository
에 있는 모든 아이템들을model
에 추가한다.
templates/items/items
- 모델에 있는 요소들을 (테이블 형식으로) 화면에 출력한다.
(2) 인증 체크 실행 결과
h.l.w.interceptor.LoginCheckInterceptor : 인증 체크 인터셉터 실행 /items
입력한 내용들을 검증한다. (추가 알게 되면 수정하기)
(3) postHandle 실행 결과
postHandle
: 컨트롤러 호출 후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor postHandle [ModelAndView [view="items/items"; model={items=[Item(id=1, itemName=itemA, price=10000, quantity=10), Item(id=2, itemName=itemC, price=5000, quantity=300), Item(id=3, itemName=itemA, price=1000, quantity=10)]}]]
items/items
에 아이템 3개를 띄워준다. (하나가 수정 됨)
(4) afterCompletion 실행 결과
afterCompletion
: 뷰가 렌더링 된 이후에 호출된다.
h.login.web.interceptor.LogInterceptor : LogInterceptor afterCompletion RESPONSE [19914b48-363d-480a-bf0f-4d94d7f36c65][/items][hello.login.web.item.ItemController#items(Model)]
- 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
- 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.
Author And Source
이 문제에 관하여(전체적으로 정리 (로그인, 상품 페이지)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@chang626/전체적으로-정리-로그인-상품-페이지저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)