ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [๊ฐ•์˜] ์Šคํ”„๋ง MVC 2ํŽธ - ๋ฐฑ์—”๋“œ ์›น ๊ฐœ๋ฐœ ํ•ต์‹ฌ ๊ธฐ์ˆ  5
    SPRING/INFLEARN 2023. 1. 30. 11:46

    https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2

     

    ์Šคํ”„๋ง MVC 2ํŽธ - ๋ฐฑ์—”๋“œ ์›น ๊ฐœ๋ฐœ ํ™œ์šฉ ๊ธฐ์ˆ  - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜

    ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ๋ชจ๋“  ์›น ๊ธฐ์ˆ ์„ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์ดํ•ดํ•˜๊ณ , ์™„์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. MVC 2ํŽธ์—์„œ๋Š” MVC 1ํŽธ์˜ ํ•ต์‹ฌ ์›๋ฆฌ์™€ ๊ตฌ์กฐ ์œ„์— ์‹ค๋ฌด ์›น ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ๋ชจ๋“  ํ™œ์šฉ ๊ธฐ์ˆ ๋“ค์„ ํ•™์Šตํ•  ์ˆ˜ ์žˆ

    www.inflearn.com

    6. ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ1 - ์ฟ ํ‚ค, ์„ธ์…˜

    - ๋กœ๊ทธ์ธ ์š”๊ตฌ ์‚ฌํ•ญ

    • ํ™ˆ ํ™”๋ฉด - ๋กœ๊ทธ์ธ ์ „
      • ํšŒ์› ๊ฐ€์ž…
      • ๋กœ๊ทธ์ธ
    • ํ™ˆ ํ™”๋ฉด - ๋กœ๊ทธ์ธ ํ›„
      • ๋ณธ์ธ ์ด๋ฆ„(๋ˆ„๊ตฌ๋‹˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.)
      • ์ƒํ’ˆ ๊ด€๋ฆฌ
      • ๋กœ๊ทธ ์•„์›ƒ
    • ๋ณด์•ˆ ์š”๊ตฌ์‚ฌํ•ญ
      • ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž๋งŒ ์ƒํ’ˆ์— ์ ‘๊ทผํ•˜๊ณ , ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ
      • ๋กœ๊ทธ์ธ ํ•˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒํ’ˆ ๊ด€๋ฆฌ์— ์ ‘๊ทผํ•˜๋ฉด ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™
      • ํšŒ์› ๊ฐ€์ž…, ์ƒํ’ˆ ๊ด€๋ฆฌ

    - ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

    • ์˜์กด๊ด€๊ณ„๋Š” ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ํ˜๋Ÿฌ์•ผ ํ•œ๋‹ค
      ๋„๋ฉ”์ธ์ด ๊ฐ€์žฅ ์ค‘์š”ํ•˜๋ฏ€๋กœ ์›น์ด ๋„๋ฉ”์ธ์„ ์ฐธ์กฐํ•˜๋„๋ก ํ•ด์•ผํ•œ๋‹ค.
      ์›น์„ ๋“ค์–ด๋‚ด์„œ ์ฝ”๋“œ๋ฅผ ๋‹ค ๊ฐˆ์•„ ์—Ž์–ด๋„ ๋„๋ฉ”์ธ์—๋Š” ์•„๋ฌด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š๋„๋ก

    - ํšŒ์› ๊ฐ€์ž…

    • ๋กœ๊ทธ์ธ ํผ html ์ถ”๊ฐ€

    • ๋กœ๊ทธ์ธ ๋ ˆํฌ ์ถ”๊ฐ€(List๋ฅผ ์ด์šฉํ•ด ์ž„์‹œ ๋ ˆํฌ, ํ…Œ์ŠคํŠธ์šฉ ๋ฐ์ดํ„ฐ ๋„ฃ๋Š” ์ฝ”๋“œ๋„ ํ•จ๊ป˜)
    • ๋กœ๊ทธ์ธ ์ปจํŠธ๋กค๋Ÿฌ
    @Controller
    @RequiredArgsConstructor
    @RequestMapping("/members")
    public class MemberController {
        private final MemberRepository memberRepository;
    
        @GetMapping("/add")
        public String addForm(@ModelAttribute("member") Member member) {
            return "members/addMemberForm";
        }
        
        @PostMapping("/add")
        public String save(@Valid @ModelAttribute Member member, BindingResult result) {
            if (result.hasErrors()) {
                return "members/addMemberForm";
            }
            memberRepository.save(member);
            return "redirect:/";
        }

    - ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ

    • LoginService ๋„๋ฉ”์ธ์— ์ถ”๊ฐ€, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง , ์•„์ด๋”” ๋น„๋ฐ€๋ฒˆํ˜ธ ๋งž๋Š”์ง€ ํ™•์ธ
    @Service
    @RequiredArgsConstructor
    public class LoginService {
        private final MemberRepository memberRepository;
    
        public Member login(String loginId, String password) {
            return memberRepository.findByLoginId(loginId)
                    .filter(m -> m.getPassword().equals(password))
                    .orElse(null);
        }
    }
    • ๋กœ๊ทธ์ธ ํผ html ์ถ”๊ฐ€

    • ๋กœ๊ทธ์ธ ํผ dto ์ถ”๊ฐ€
    • ๋กœ๊ทธ์ธ Controller
    @Slf4j
    @Controller
    @RequiredArgsConstructor
    public class LoginController {
        private final LoginService loginService;
        @GetMapping("/login")
        public String loginForm(@ModelAttribute("loginForm") LoginForm form) {
            return "login/loginForm";
        }
    
        @PostMapping("/login")
        public String login(@Valid @ModelAttribute LoginForm form, BindingResult
                bindingResult) {
            if (bindingResult.hasErrors()) {
                return "login/loginForm";
            }
            Member loginMember = loginService.login(form.getLoginId(),
                    form.getPassword());
            log.info("login? {}", loginMember);
            if (loginMember == null) {
                bindingResult.reject("loginFail", "์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
                return "login/loginForm";
            }
            //๋กœ๊ทธ์ธ ์„ฑ๊ณต ์ฒ˜๋ฆฌ TODO
            return "redirect:/";
        }

     

    - ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌํ•˜๊ธฐ - ์ฟ ํ‚ค ์‚ฌ์šฉ

    ๋กœ๊ทธ์ธ -> ๋กœ๊ทธ์ธ ์„ฑ๊ณต

               <- ์ฟ ํ‚ค ๋งŒ๋“ค์–ด์„œ ๋ณด๋‚ด์คŒ

    ๋ชจ๋“  ์š”์ฒญ์— ์ฟ ํ‚ค ์ž๋™ ํฌํ•จ

    ์ฟ ํ‚ค์—๋Š” ์˜์†, ์„ธ์…˜ ์ฟ ํ‚ค๊ฐ€ ์žˆ๋Š”๋ฐ ๋กœ๊ทธ์ธ์€ ๋ธŒ๋ผ์šฐ์ € ์ข…๋ฃŒ ์‹œ๊นŒ์ง€๋งŒ ์œ ์ง€๋˜๋ฉด ๋˜๋ฏ€๋กœ ์„ธ์…˜ ๋ฐฉ์‹์„ ์„ ํƒํ•œ๋‹ค.

    @PostMapping("/login")
    public String login(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult
    , HttpServletResponse response) {
        if (bindingResult.hasErrors()) {
            return "login/loginForm";
        }
        Member loginMember = loginService.login(form.getLoginId(),
                form.getPassword());
        log.info("login? {}", loginMember);
        if (loginMember == null) {
            bindingResult.reject("loginFail", "์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
            return "login/loginForm";
        }
        
        //๋กœ๊ทธ์ธ ์„ฑ๊ณต ์ฒ˜๋ฆฌ
        Cookie idCookie = new Cookie("memberId",
                String.valueOf(loginMember.getId()));
        response.addCookie(idCookie);
    
        return "redirect:/";
    }
    
    
    @PostMapping("/logout")
    public String logout(HttpServletResponse response) {
        expireCookie(response, "memberId");
        return "redirect:/";
    }
    private void expireCookie(HttpServletResponse response, String cookieName) {
        Cookie cookie = new Cookie(cookieName, null);
        cookie.setMaxAge(0);
        response.addCookie(cookie);
    }

    ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

    home์—์„œ๋„ ๋กœ๊ทธ์ธ์ด ์œ ์ง€๋  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค๊ธฐ/ ๋กœ๊ทธ์•„์›ƒ ๋งŒ๋“ค๊ธฐ

    @GetMapping("/")
    public String homeLogin(@CookieValue(name = "memberId", required = false) Long memberId, Model model) {
        if (memberId == null) {
            return "home";
        }
    
        //๋กœ๊ทธ์ธ
        Member loginMember = memberRepository.findById(memberId);
        if (loginMember == null) {
            return "home";
        }
        model.addAttribute("member", loginMember);
        return "loginHome";
    }

    ๋กœ๊ทธ์ธ ํ›„์—๋Š” ํ™ˆ ํ™”๋ฉด์ด ์ด๋ ‡๊ฒŒ ๋ฐ”๋€Œ๋ฉฐ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๊ป๋‹ค๊ฐ€ ์ผœ๋ฉด ์‚ฌ๋ผ์ง„๋‹ค.

     

    - ์ฟ ํ‚ค์™€ ๋ณด์•ˆ ๋ฌธ์ œ

    ์ฟ ํ‚ค๋Š” ์‚ฌ์‹ค ํด๋ผ์ด์–ธํŠธ์—์„œ ์ž„์˜๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค -> ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๋“ค์˜ ๊ฐœ์ธ์ •๋ณด๊ฐ€ ๋‹ค ํ„ธ๋ฆฐ๋‹ค

    ํ•ด์ปค๊ฐ€ ์ฟ ํ‚ค๋ฅผ ํ›”์ณ์„œ ์•…์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค

    -> ๋Œ€์•ˆ

    ์ฟ ํ‚ค์— ์‹œ๊ฐ„์ œํ•œ์„ ์ค€๋‹ค

    ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•œ ์ž„์˜์˜ ํ† ํฐ์„ ์ค€๋‹ค

    ํ•ดํ‚น์ด ์˜์‹ฌ๋˜๋Š” ๊ฒฝ์šฐ ์ฟ ํ‚ค๋ฅผ ์ง์ ‘ ์ œ๊ฑฐํ•œ๋‹ค

     

    - ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌํ•˜๊ธฐ - ์„ธ์…˜ ๋™์ž‘ ๋ฐฉ์‹

    ์ฟ ํ‚ค์˜ ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ๋ณด๊ด€ํ•˜๊ณ  ์—ฐ๊ฒฐ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ• : ์„ธ์…˜

    ์ฟ ํ‚ค ๊ฐ’์„ ๋ณ€์กฐ - ์˜ˆ์ƒ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ณต์žกํ•œ ์„ธ์…˜ id

    ํ„ธ๋ ค๋„ ๋ณต์žกํ•˜๋ฏ€๋กœ ์•Œ๊ธฐ ์–ด๋ ต๋‹ค

     

    - ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌํ•˜๊ธฐ - ์„ธ์…˜ ์ง์ ‘ ๋งŒ๋“ค๊ธฐ

    @Component
    public class SessionManager {
        public static final String SESSION_COOKIE_NAME = "mySessionId";
        private Map<String, Object> sessionStore = new ConcurrentHashMap<>();
        /**
         * ์„ธ์…˜ ์ƒ์„ฑ
         */
        public void createSession(Object value, HttpServletResponse response) {
            //์„ธ์…˜ id๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ฐ’์„ ์„ธ์…˜์— ์ €์žฅ
            String sessionId = UUID.randomUUID().toString();
            sessionStore.put(sessionId, value);
            //์ฟ ํ‚ค ์ƒ์„ฑ
            Cookie mySessionCookie = new Cookie(SESSION_COOKIE_NAME, sessionId);
            response.addCookie(mySessionCookie);
        }
        /**
         * ์„ธ์…˜ ์กฐํšŒ
         */
        public Object getSession(HttpServletRequest request) {
            Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
            if (sessionCookie == null) {
                return null;
            }
            return sessionStore.get(sessionCookie.getValue());
        }
        /**
         * ์„ธ์…˜ ๋งŒ๋ฃŒ
         */
        public void expire(HttpServletRequest request) {
            Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
            if (sessionCookie != null) {
                sessionStore.remove(sessionCookie.getValue());
            }
        }
        
        private Cookie findCookie(HttpServletRequest request, String cookieName) {
            if (request.getCookies() == null) {
                return null;
            }
            return Arrays.stream(request.getCookies())
                    .filter(cookie -> cookie.getName().equals(cookieName))
                    .findAny()
                    .orElse(null);
        }
    class SessionManagerTest {
        SessionManager sessionManager = new SessionManager();
    
        @Test
        void sessionTest() {
    
            //์„ธ์…˜ ์ƒ์„ฑ
            //ํ…Œ์ŠคํŠธ์šฉ ๊ฐ€์งœ Mock ์ œ๊ณต
            MockHttpServletResponse response = new MockHttpServletResponse();
            Member member = new Member();
            sessionManager.createSession(member, response);
    
            //์š”์ฒญ์— ์‘๋‹ต ์ฟ ํ‚ค ์ €์žฅ
            MockHttpServletRequest request = new MockHttpServletRequest();
            request.setCookies(response.getCookies());
    
            //์„ธ์…˜ ์กฐํšŒ
            Object result = sessionManager.getSession(request);
            assertThat(result).isEqualTo(member);
            
            //์„ธ์…˜ ๋งŒ๋ฃŒ
            sessionManager.expire(request);
            Object expired = sessionManager.getSession(request);
            assertThat(expired).isNull();
        }

    Key : UUID

    Value : member id๋กœ  

    UUID๋ฅผ ํ†ตํ•ด member id์— ์ ‘๊ทผ

     

    - ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌํ•˜๊ธฐ - ์ง์ ‘ ๋งŒ๋“  ์„ธ์…˜ ์ ์šฉ

    @PostMapping("/login")
    public String loginV2(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletResponse response) {
        if (bindingResult.hasErrors()) {
            return "login/loginForm";
        }
    
        Member loginMember = loginService.login(form.getLoginId(),
                form.getPassword());
        log.info("login? {}", loginMember);
    
        if (loginMember == null) {
            bindingResult.reject("loginFail", "์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
            return "login/loginForm";
        }
    
        //๋กœ๊ทธ์ธ ์„ฑ๊ณต ์ฒ˜๋ฆฌ
        sessionManager.createSession(loginMember, response);
    
        return "redirect:/";
    }
    @PostMapping("/logout")
    public String logoutV2(HttpServletRequest request) {
        sessionManager.expire(request);
        return "redirect:/";
    }
    @GetMapping("/")
    public String homeLoginV2(HttpServletRequest request, Model model) {
        Member member = (Member)sessionManager.getSession(request);
    
        if (member == null) {
            return "home";
        }
    
        //๋กœ๊ทธ์ธ
        model.addAttribute("member", member);
        return "loginHome";
    }

    sessionManager๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ชจ๋‘ ์ˆ˜์ •ํ•œ๋‹ค.

    ์ด๋ ‡๊ฒŒ ์ผ์ผํžˆ ๊ฐœ๋ฐœํ•ด์•ผ ๋˜๋Š” ์„ธ์…˜์„ ์„œ๋ธ”๋ฆฟ์—์„œ ์ง€์›ํ•ด์ค€๋‹ค.

    ์ฟ ํ‚ค๊ฐ€ ์ €์žฅ๋œ ๋ชจ์Šต

    - ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌํ•˜๊ธฐ - ์„œ๋ธ”๋ฆฟ HTTP ์„ธ์…˜1

    ๊ธฐ๋ณธ์œผ๋กœ ๋‚ด์žฅ๋œ ๊ธฐ๋Šฅ ์‚ฌ์šฉ

    @PostMapping("/login")
    public String loginV3(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult, HttpServletRequest request) {
        if (bindingResult.hasErrors()) {
            return "login/loginForm";
        }
    
        Member loginMember = loginService.login(form.getLoginId(), form.getPassword());
        log.info("login? {}", loginMember);
    
        if (loginMember == null) {
            bindingResult.reject("loginFail", "์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
            return "login/loginForm";
        }
    
        //๋กœ๊ทธ์ธ ์„ฑ๊ณต ์ฒ˜๋ฆฌ
        //์„ธ์…˜์ด ์žˆ์œผ๋ฉด ์žˆ๋Š” ์„ธ์…˜ ๋ฐ˜ํ™˜, ์—†์œผ๋ฉด ์‹ ๊ทœ ์„ธ์…˜ ์ƒ์„ฑ
        HttpSession session = request.getSession();
        //์„ธ์…˜์— ๋กœ๊ทธ์ธ ํšŒ์› ์ •๋ณด ๋ณด๊ด€
        session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
    
        return "redirect:/";
    }

    request.getSession(), (true)  -> ์„ธ์…˜์ด ์žˆ์œผ๋ฉด ์„ธ์…˜ ๋ฐ˜ํ™˜, ์—†์œผ๋ฉด ์ƒ์„ฑ

                                       (false) -> ์žˆ์œผ๋ฉด ๋˜‘๊ฐ™์ด, ์—†์œผ๋ฉด null

    @PostMapping("/logout")
    public String logoutV3(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate();
        }
        return "redirect:/";
    }
    @GetMapping("/")
    public String homeLoginV3(HttpServletRequest request, Model model) {
        HttpSession session = request.getSession(false);
        if(session == null)
            return "home";
    
    
        Member loginMember = (Member)session.getAttribute(SessionConst.LOGIN_MEMBER);
    
        if (loginMember == null) {
            return "home";
        }
    
        //๋กœ๊ทธ์ธ
        model.addAttribute("member", loginMember);
        return "loginHome";
    }

    JSESSIONID๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์ฟ ํ‚ค๊ฐ€ ์ ์ ˆํ•˜๊ฒŒ ์ƒ์„ฑ๋œ๋‹ค

    - ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌํ•˜๊ธฐ - ์„œ๋ธ”๋ฆฟ HTTP ์„ธ์…˜2

    • @SessionAttribute
    @GetMapping("/")
    public String homeLoginV3Spring(
            @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember, Model model) {
    
        if (loginMember == null) {
            return "home";
        }
    
        //๋กœ๊ทธ์ธ
        model.addAttribute("member", loginMember);
        return "loginHome";
    }

    @SessionAttribute๋กœ ์ฝ”๋“œ๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

    ์„ธ์…˜์„ ์ฐพ์•„์˜จ๋‹ค(์ƒ์„ฑํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค.)

     

    • TrakingModes

    ์ฟ ํ‚ค๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ, URL์„ ์ด์šฉํ•ด์„œ ์œ ์ง€์‹œํ‚จ๋‹ค. ์ฒ˜์Œ์— ํŒ๋‹จ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ

    ์ง€์ €๋ถ„ํ•˜๋‹ค.

    ์ด๋ฅผ ๋„๋Š” ๋ฐฉ๋ฒ•์€

    server.servlet.session.tracking-modes=cookie

    ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋Œ ์ˆ˜ ์žˆ๋‹ค. 

     

    - ์„ธ์…˜ ์ •๋ณด์™€ ํƒ€์ž„์•„์›ƒ ์„ค์ •

    @Slf4j
    @RestController
    public class SessionInfoController {
        
        @GetMapping("/session-info")
        public String sessionInfo(HttpServletRequest request) {
            HttpSession session = request.getSession(false);
            if (session == null) {
                return "์„ธ์…˜์ด ์—†์Šต๋‹ˆ๋‹ค.";
            }
            
            //์„ธ์…˜ ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ
            session.getAttributeNames().asIterator()
                    .forEachRemaining(name -> log.info("session name={}, value={}",
                            name, session.getAttribute(name)));
            log.info("sessionId={}", session.getId());
            log.info("maxInactiveInterval={}", session.getMaxInactiveInterval());
            log.info("creationTime={}", new Date(session.getCreationTime()));
            log.info("lastAccessedTime={}", new
                    Date(session.getLastAccessedTime()));
            log.info("isNew={}", session.isNew());
            return "์„ธ์…˜ ์ถœ๋ ฅ";
        }
    }

     

    ์„ธ์…˜์˜ ์ •๋ณด๋“ค์„ ๋ณธ๋‹ค.

    ์„ธ์…˜์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์•„์›ƒ์„ ์ง์ ‘ ํ˜ธ์ถœํ•  ๋•Œ๋งŒ ์‚ญ์ œ๋œ๋‹ค.

    ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ์ž๋“ค์€ ์ด๋ฅผ ์„ ํƒํ•˜์ง€ ์•Š๊ณ , HTTP๋Š” ๋น„์—ฐ๊ฒฐ์„ฑ์ด๋ฏ€๋กœ ์„œ๋ฒ„ ์ž…์žฅ์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์›น ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ข…๋ฃŒํ•œ ๊ฒƒ์ธ์ง€ ์•„๋‹Œ์ง€ ์ธ์‹ํ•  ์ˆ˜ ์—†๋‹ค.

    ์„œ๋ฒ„์—์„œ ์„ธ์…˜ ๋ฐ์ดํ„ฐ๋ฅผ ์–ธ์ œ ์‚ญ์ œํ•ด์•ผ๋ ๊นŒ? - ์ผ๋‹จ ๋ฌดํ•œ์ •์€ ์•ˆ๋จ, ๋ณด์•ˆ์ƒ/ ๋ฉ”๋ชจ๋ฆฌ์ƒ 

    ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์šฐ๋‘๋‘ ์Œ“์ด๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋งค์šฐ ๋†’๋‹ค.

    -> ์„ธ์…˜์—์„  ์ตœ์†Œํ•œ์˜ ๋ฐ์ดํ„ฐ๋งŒ ๋ณด๊ด€ํ•ด์•ผํ•œ๋‹ค.

    -> ์‚ฌ์šฉ์ž๊ฐ€ ์„œ๋ฒ„์— ์ตœ๊ทผ์— ์š”์ฒญํ•œ ์‹œ๊ฐ„์„ ๊ธฐ์ค€์œผ๋กœ 30๋ถ„์„ ์œ ์ง€ํ•ด์ฃผ๋ฉด ์–ด๋–จ๊นŒ?

    • ๊ธ€๋กœ๋ฒŒ์„ค์ •
    server.servlet.session.timeout=60
    • ์„ธ์…˜ ๋‹จ์œ„๋กœ ์„ค์ •
    session.setMaxInactiveInterval(1800);
    • ์„ธ์…˜ ํƒ€์ž„์•„์›ƒ ๋ฐœ์ƒ

    ์„ธ์…˜ ํƒ€์ž„์•„์›ƒ ์‹œ๊ฐ„์€ ํ•ด๋‹น ์„ธ์…˜๊ณผ ๊ด€๋ จ๋œ JSESSIONID๋ฅผ ์ „๋‹ฌํ•˜๋Š” HTTP  ์š”์ฒญ์ด ์žˆ์„ ๋•Œ๋งˆ๋‹ค ์ดˆ๊ธฐํ™”์‹œํ‚จ๋‹ค.

    LastAccessedTime(session.getLastAccessedTime()) ์ดํ›„๋กœ timeout ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด WAS๊ฐ€ ๋‚ด๋ถ€์—์„œ ํ•ด๋‹น ์„ธ์…˜์„ ์ œ๊ฑฐ

     

    7. ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ2 - ํ•„ํ„ฐ, ์ธํ„ฐ์…‰ํ„ฐ

    - ์„œ๋ธ”๋ฆฟ ํ•„ํ„ฐ - ์†Œ๊ฐœ

    URL๋กœ ๋ง‰ ์—ฌ๊ธฐ์ €๊ธฐ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์œผ๋ฉด ๋กœ๊ทธ์ธ ๋˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋“ค์–ด๊ฐ€๋ฉด ์•ˆ๋˜๋Š” ๊ณณ๊นŒ์ง€ ๋“ค์–ด๊ฐ€์ง„๋‹ค = ๋ฌธ์ œ

    ์ด๋ฅผ 

     

    ํ•„ํ„ฐ : ์„œ๋ธ”๋ฆฟ์ด

    ์ธํ„ฐ์…‰ํ„ฐ : ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ

     

    ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ ์ฒดํฌ๋ฅผ ๋งค api ํ˜ธ์ถœ ๋•Œ๋งˆ๋‹ค ํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋ณ„๋กœ๋‹ค.

    ์ด๋Ÿฐ ๊ณตํ†ต๊ด€์‹ฌ์‚ฌ๋Š” ์Šคํ”„๋ง AOP๋กœ๋„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์›น๊ณผ ๊ด€๋ จํ•œ ๊ณตํ†ต ๊ด€์‹ฌ์‚ฌ๋Š” ์„œ๋ธ”๋ฆฟ ํ•„ํ„ฐ, ์Šคํ”„๋ง ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.(HttpServletRequest๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ)

     

    ์„œ๋ธ”๋ฆฟ ํ•„ํ„ฐ : ์„œ๋ธ”๋ฆฟ์ด ์ง€์›ํ•˜๋Š” ์ˆ˜๋ฌธ์žฅ

    URL ํŒจํ„ด๋ณ„๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Œ(/* = ๋ชจ๋“  ์š”์ฒญ)

     

    ํ•„ํ„ฐ ํ๋ฆ„

    HTTP ์š”์ฒญ -> WAS -> ํ•„ํ„ฐ -> ์„œ๋ธ”๋ฆฟ -> ์ปจํŠธ๋กค๋Ÿฌ

     

    ํ•„ํ„ฐ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„, ๋“ฑ๋กํ•˜๋ฉด

    ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋กœ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•จ.

    init(): ํ•„ํ„ฐ ์ดˆ๊ธฐํ™” ๋ฉ”์„œ๋“œ, ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.
    doFilter(): ๊ณ ๊ฐ์˜ ์š”์ฒญ์ด ์˜ฌ ๋•Œ ๋งˆ๋‹ค ํ•ด๋‹น ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ํ•„ํ„ฐ์˜ ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค.
    destroy(): ํ•„ํ„ฐ ์ข…๋ฃŒ ๋ฉ”์„œ๋“œ, ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.

     

    - ์„œ๋ธ”๋ฆฟ ํ•„ํ„ฐ - ์š”์ฒญ ๋กœ๊ทธ

    @Slf4j
    public class LogFilter implements Filter {
    
        
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            log.info("log filter init");
        }
    
        //HTTP ์š”์ฒญ์ด ์˜ฌ ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ
        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                             FilterChain chain) throws IOException, ServletException {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            String requestURI = httpRequest.getRequestURI();
            String uuid = UUID.randomUUID().toString();
            try {
                log.info("REQUEST [{}][{}]", uuid, requestURI);
                chain.doFilter(request, response);
            } catch (Exception e) {
                throw e;
            } finally {
                log.info("RESPONSE [{}][{}]", uuid, requestURI);
            }
        }
    
        @Override
        public void destroy() {
            log.info("log filter destroy");
        }
    }


    ServletRequest request ๋Š” HTTP ์š”์ฒญ์ด ์•„๋‹Œ ๊ฒฝ์šฐ๊นŒ์ง€ ๊ณ ๋ คํ•ด์„œ ๋งŒ๋“  ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค. HTTP๋ฅผ
    ์‚ฌ์šฉํ•˜๋ฉด HttpServletRequest httpRequest = (HttpServletRequest) request; ์™€ ๊ฐ™์ด ๋‹ค์šด ์ผ€์ŠคํŒ… ํ•˜๋ฉด ๋œ๋‹ค.

     

    String uuid = UUID.randomUUID().toString();
    HTTP ์š”์ฒญ์„ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ์š”์ฒญ๋‹น ์ž„์˜์˜ uuid ๋ฅผ ์ƒ์„ฑํ•ด๋‘”๋‹ค.

     

    chain.doFilter(request, response);
    ๋‹ค์Œ ํ•„ํ„ฐ๊ฐ€ ์žˆ์œผ๋ฉด ํ•„ํ„ฐ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ํ•„ํ„ฐ๊ฐ€ ์—†์œผ๋ฉด ์„œ๋ธ”๋ฆฟ์„ ํ˜ธ์ถœํ•œ๋‹ค.
    ๋งŒ์•ฝ ์ด ๋กœ์ง์„ ํ˜ธ์ถœํ•˜์ง€ ์•Š์œผ๋ฉด ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ์ง„ํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.

    @Configuration
    public class WebConfig {
        @Bean
        public FilterRegistrationBean logFilter() {
            FilterRegistrationBean<Filter> filterRegistrationBean 
                    = new FilterRegistrationBean<>();
            filterRegistrationBean.setFilter(new LogFilter());
            //ํ•„ํ„ฐ๋Š” ์ฒด์ธ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์ˆœ์„œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ๋‚ฎ์„ ์ˆ˜๋ก ๋จผ์ € ๋™์ž‘ํ•œ๋‹ค.
            filterRegistrationBean.setOrder(1);
            filterRegistrationBean.addUrlPatterns("/*");
            return filterRegistrationBean;
        }
    }

     

    - ์„œ๋ธ”๋ฆฟ ํ•„ํ„ฐ - ์ธ์ฆ ์ฒดํฌ

    @Slf4j
    public class LoginCheckFilter implements Filter {
    
        //ํ’€์–ด์ค„ url ๋ฆฌ์ŠคํŠธ
        private static final String[] whitelist = {"/", "/members/add", "/login", "/logout","/css/*"};
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                             FilterChain chain) throws IOException, ServletException {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            String requestURI = httpRequest.getRequestURI();
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            try {
                log.info("์ธ์ฆ ์ฒดํฌ ํ•„ํ„ฐ ์‹œ์ž‘ {}", requestURI);
    
                if (isLoginCheckPath(requestURI)) {
                    log.info("์ธ์ฆ ์ฒดํฌ ๋กœ์ง ์‹คํ–‰ {}", requestURI);
                    HttpSession session = httpRequest.getSession(false);
    
                    if (session == null ||
                            session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
                        log.info("๋ฏธ์ธ์ฆ ์‚ฌ์šฉ์ž ์š”์ฒญ {}", requestURI);
    
                        //๋กœ๊ทธ์ธ์œผ๋กœ redirect
                        httpResponse.sendRedirect("/login?redirectURL=" +
                                requestURI);
                        return; //์—ฌ๊ธฐ๊ฐ€ ์ค‘์š”, ๋ฏธ์ธ์ฆ ์‚ฌ์šฉ์ž๋Š” ๋‹ค์Œ์œผ๋กœ ์ง„ํ–‰ํ•˜์ง€ ์•Š๊ณ  ๋!
                    }
                }
                
                chain.doFilter(request, response);
            } catch (Exception e) {
                throw e; //์˜ˆ์™ธ ๋กœ๊น… ๊ฐ€๋Šฅ ํ•˜์ง€๋งŒ, ํ†ฐ์บฃ๊นŒ์ง€ ์˜ˆ์™ธ๋ฅผ ๋ณด๋‚ด์ฃผ์–ด์•ผ ํ•จ
            } finally {
                log.info("์ธ์ฆ ์ฒดํฌ ํ•„ํ„ฐ ์ข…๋ฃŒ {}", requestURI);
            }
        }
    
        /**
         * ํ™”์ดํŠธ ๋ฆฌ์ŠคํŠธ์˜ ๊ฒฝ์šฐ ์ธ์ฆ ์ฒดํฌX
         */
        private boolean isLoginCheckPath(String requestURI) {
            return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
        }
    }

    webconfig์— ๋“ฑ๋ก

    @Bean
    public FilterRegistrationBean loginCheckFilter() {
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new LoginCheckFilter());
        filterRegistrationBean.setOrder(2);
        filterRegistrationBean.addUrlPatterns("/*");
        
        return filterRegistrationBean;
    }

    -> ์•„๋ฌด๋ฆฌ ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋ฅด ๋“ค์–ด๊ฐ€๋ คํ•ด๋„ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฐ–์— ๋“ค์–ด๊ฐˆ ์ˆ˜ ์—†๋‹ค.

    @PostMapping("/login")
    public String loginV4(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult,
                          @RequestParam(defaultValue = "/") String redirectURL,
                          HttpServletRequest request) {
        /*์ƒ๋žต*/
        return "redirect:" + redirectURL;
    }

    ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์›๋ž˜ ๊ฐ€๋ ค๋˜ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

     

    - ์Šคํ”„๋ง ์ธํ„ฐ์…‰ํ„ฐ - ์†Œ๊ฐœ

    HTTP ์š”์ฒญ -> WAS -> ํ•„ํ„ฐ -> ์„œ๋ธ”๋ฆฟ -> ์Šคํ”„๋ง ์ธํ„ฐ์…‰ํ„ฐ -> ์ปจํŠธ๋กค๋Ÿฌ

    ์„œ๋ธ”๋ฆฟ ํ•„ํ„ฐ์— ๋น„ํ•ด ์ •๋ฐ€ํ•œ ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค

    preHandle 

    ์ปจํŠธ๋กค๋Ÿฌ ํ˜ธ์ถœ ์ „์— ํ˜ธ์ถœ๋œ๋‹ค. (๋” ์ •ํ™•ํžˆ๋Š” ํ•ธ๋“ค๋Ÿฌ ์–ด๋Œ‘ํ„ฐ ํ˜ธ์ถœ ์ „์— ํ˜ธ์ถœ๋œ๋‹ค.)

    ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ์—๋„ ์ปจํŠธ๋กค๋Ÿฌ ํ˜ธ์ถœ ์ „์— ํ˜ธ์ถœ๋œ๋‹ค.
    preHandle ์˜ ์‘๋‹ต๊ฐ’์ด true ์ด๋ฉด ๋‹ค์Œ์œผ๋กœ ์ง„ํ–‰ํ•˜๊ณ , false ์ด๋ฉด ๋”๋Š” ์ง„ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค. false
    ์ธ ๊ฒฝ์šฐ ๋‚˜๋จธ์ง€ ์ธํ„ฐ์…‰ํ„ฐ๋Š” ๋ฌผ๋ก ์ด๊ณ , ํ•ธ๋“ค๋Ÿฌ ์–ด๋Œ‘ํ„ฐ๋„ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ฆผ์—์„œ 1๋ฒˆ์—์„œ ๋์ด
    ๋‚˜๋ฒ„๋ฆฐ๋‹ค.


    postHandle

    ์ปจํŠธ๋กค๋Ÿฌ ํ˜ธ์ถœ ํ›„์— ํ˜ธ์ถœ๋œ๋‹ค. (๋” ์ •ํ™•ํžˆ๋Š” ํ•ธ๋“ค๋Ÿฌ ์–ด๋Œ‘ํ„ฐ ํ˜ธ์ถœ ํ›„์— ํ˜ธ์ถœ๋œ๋‹ค.)

    ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค.


    afterCompletion

    ๋ทฐ๊ฐ€ ๋ Œ๋”๋ง ๋œ ์ดํ›„์— ํ˜ธ์ถœ๋œ๋‹ค.

    ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ํ˜ธ์ถœ๋œ๋‹ค.

     

    - ์Šคํ”„๋ง ์ธํ„ฐ์…‰ํ„ฐ - ์š”์ฒญ ๋กœ๊ทธ

    @Slf4j
    public class LogInterceptor implements HandlerInterceptor {
        public static final String LOG_ID = "logId";
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            String requestURI = request.getRequestURI();
            String uuid = UUID.randomUUID().toString();
    
            request.setAttribute(LOG_ID, uuid);
    
            //@RequestMapping: HandlerMethod
            //์ •์  ๋ฆฌ์†Œ์Šค: ResourceHttpRequestHandler
            if (handler instanceof HandlerMethod) {
                //ํ˜ธ์ถœํ•  ์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ์˜๋ชจ๋“  ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.
                HandlerMethod hm = (HandlerMethod) handler;
            }
    
            log.info("REQUEST [{}][{}][{}]", uuid, requestURI, handler);
            return true; //false ์ง„ํ–‰X
        }
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("postHandle [{}]", modelAndView);
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            String requestURI = request.getRequestURI();
            String logId = (String)request.getAttribute(LOG_ID);
            log.info("RESPONSE [{}][{}]", logId, requestURI);
            if (ex != null) {
                log.error("afterCompletion error!!", ex);
            }
        }
    }
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LogInterceptor())
                    .order(1)
                    .addPathPatterns("/**")
                    .excludePathPatterns("/css/**", "/*.ico", "/error");
        }

    registry.addInterceptor(new LogInterceptor()) : ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ๋“ฑ๋กํ•œ๋‹ค.
    order(1) : ์ธํ„ฐ์…‰ํ„ฐ์˜ ํ˜ธ์ถœ ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•œ๋‹ค. ๋‚ฎ์„ ์ˆ˜๋ก ๋จผ์ € ํ˜ธ์ถœ๋œ๋‹ค.
    addPathPatterns("/**") : ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์ ์šฉํ•  URL ํŒจํ„ด์„ ์ง€์ •ํ•œ๋‹ค.
    excludePathPatterns("/css/**", "/*.ico", "/error") : ์ธํ„ฐ์…‰ํ„ฐ์—์„œ ์ œ์™ธํ•  ํŒจํ„ด์„ ์ง€์ •ํ•œ๋‹ค.

    HandlerMethod
    ํ•ธ๋“ค๋Ÿฌ ์ •๋ณด๋Š” ์–ด๋–ค ํ•ธ๋“ค๋Ÿฌ ๋งคํ•‘์„ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค. ์Šคํ”„๋ง์„ ์‚ฌ์šฉํ•˜๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ
    @Controller , @RequestMapping ์„ ํ™œ์šฉํ•œ ํ•ธ๋“ค๋Ÿฌ ๋งคํ•‘์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ด ๊ฒฝ์šฐ ํ•ธ๋“ค๋Ÿฌ ์ •๋ณด๋กœ
    HandlerMethod ๊ฐ€ ๋„˜์–ด์˜จ๋‹ค.


    ResourceHttpRequestHandler
    @Controller ๊ฐ€ ์•„๋‹ˆ๋ผ /resources/static ์™€ ๊ฐ™์€ ์ •์  ๋ฆฌ์†Œ์Šค๊ฐ€ ํ˜ธ์ถœ ๋˜๋Š” ๊ฒฝ์šฐ
    ResourceHttpRequestHandler ๊ฐ€ ํ•ธ๋“ค๋Ÿฌ ์ •๋ณด๋กœ ๋„˜์–ด์˜ค๊ธฐ ๋•Œ๋ฌธ์— ํƒ€์ž…์— ๋”ฐ๋ผ์„œ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

     

    postHandle, afterCompletion
    ์ข…๋ฃŒ ๋กœ๊ทธ๋ฅผ postHandle ์ด ์•„๋‹ˆ๋ผ afterCompletion ์—์„œ ์‹คํ–‰ํ•œ ์ด์œ ๋Š”, ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ
    postHandle ๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. afterCompletion ์€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ํ˜ธ์ถœ ๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•œ๋‹ค.

     

    PathPattern  ๊ณต์‹ ๋ฌธ์„œ

     

    PathPattern (Spring Framework 6.0.4 API)

    Compare this pattern with a supplied pattern: return -1,0,+1 if this pattern is more specific, the same or less specific than the supplied pattern.

    docs.spring.io

     

    - ์Šคํ”„๋ง ์ธํ„ฐ์…‰ํ„ฐ - ์ธ์ฆ ์ฒดํฌ

    @Slf4j
    public class LoginCheckInterceptor implements HandlerInterceptor {
        
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            
            String requestURI = request.getRequestURI();
            
            log.info("์ธ์ฆ ์ฒดํฌ ์ธํ„ฐ์…‰ํ„ฐ ์‹คํ–‰ {}", requestURI);
            
            HttpSession session = request.getSession(false);
            
            if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
                log.info("๋ฏธ์ธ์ฆ ์‚ฌ์šฉ์ž ์š”์ฒญ");
                //๋กœ๊ทธ์ธ์œผ๋กœ redirect
                response.sendRedirect("/login?redirectURL=" + requestURI);
                return false;
            }
            return true;
        }
    }
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LogInterceptor())
                    .order(1)
                    .addPathPatterns("/**")
                    .excludePathPatterns("/css/**", "/*.ico", "/error");
    
            registry.addInterceptor(new LoginCheckInterceptor())
                    .order(2)
                    .addPathPatterns("/**") //๋ชจ๋“  ๊ณณ์— ์ ์šฉ
                    .excludePathPatterns(
                            "/", "/members/add", "/login", "/logout",
                            "/css/**", "/*.ico", "/error" //ํ•˜์ง€๋งŒ ์ด๊ฑด ๋นผ
                    );
        }

    ์ฝ”๋“œ๊ฐ€ ์„œ๋ธ”๋ฆฟ์— ๋น„ํ•ด์„œ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๋‹ค

    ํŠน๋ณ„ํ•œ ์ด์œ ๊ฐ€ ์—†๋‹ค๋ฉด ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜์ž

     

    - ArgumentResolver ํ™œ์šฉ

    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Login {
    }

    @Target(ElementType.PARAMETER) : ํŒŒ๋ผ๋ฏธํ„ฐ์—๋งŒ ์‚ฌ์šฉ
    @Retention(RetentionPolicy.RUNTIME) : ๋ฆฌํ”Œ๋ ‰์…˜ ๋“ฑ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋Ÿฐํƒ€์ž„๊นŒ์ง€ ์• ๋…ธํ…Œ์ด์…˜ ์ •๋ณด๊ฐ€ ๋‚จ์•„์žˆ์Œ

    @GetMapping("/")
    public String homeLoginV3ArgumentResolver(@Login Member loginMember, Model model) {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new LoginMemberArgumentResolver());
    }

     

    @Slf4j
    public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
    
        @Override
        public boolean supportsParameter(MethodParameter parameter) {
            log.info("supportsParameter ์‹คํ–‰");
            boolean hasLoginAnnotation =
                    parameter.hasParameterAnnotation(Login.class);
            boolean hasMemberType =
                    Member.class.isAssignableFrom(parameter.getParameterType());
            return hasLoginAnnotation && hasMemberType;
        }
    
        @Override
        public Object resolveArgument(MethodParameter parameter,
                                      ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
                                      WebDataBinderFactory binderFactory) throws Exception {
    
            log.info("resolveArgument ์‹คํ–‰");
    
            HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
            HttpSession session = request.getSession(false);
    
            if (session == null) {
                return null;
            }
    
            return session.getAttribute(SessionConst.LOGIN_MEMBER);
        }
    }

    ๊ฒฐ๊ณผ๋Š” ๋™์ผํ•˜๊ฒŒ, ์• ๋…ธํ…Œ์ด์…˜์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Œ

     

     

Designed by Tistory.