전체적으로 정리 (로그인, 상품 페이지)

📚 1. 로그인 구동 방식

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, afterCompletionHandlerInterceptor 인터페이스로부터 상속받아 구현하였다.

 

(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 [아이디 또는 비밀번호가 맞지 않습니다.]}]]
  • 입력한 idpassword를 확인해보니, 검증 결과 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)]

 

(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)]
  • 뷰가 렌더링 된 이후에 호출된다. 의미 : 사용자에게 제공될 화면 데이터가 준비된 다음 호출된다.
  • 뷰가 렌더링된 후 렌더링된 데이터가 응답의 바디에 담겨져 사용자의 브라우저에 도달하고, 응답의 바디에 담긴 데이터를 읽어 브라우저에 나타낸다.

 

좋은 웹페이지 즐겨찾기