= 로그인 이력 == 개요 사용자가 시스템에 로그인한 이력을 조회 == Table * 로그인 이력 : TN_CF_LOGIN_OUT * 사용자 : TN_CF_USER == API .HistoryController.java . 로그인 이력 목록 조회 + GET /history/login-out-logs Query ID : selectListLoginOut == 화면 사용자가 시스템에 로그인한 이력을 조회 image::loginHistory.png[] == LoginOutLogInterceptor 시스템에 사용자가 로그인/아웃을 하면 LoginOutLogInterceptor에 의해 사용자 정보가 저장된다. LoginOutLogInterceptor는 LoginInterceptor의 구현클래스로 LoginInterceptor의 자세한 설명은 <<_로그인, 로그인>>의 **로그인/아웃 전,후 처리**를 참고한다. [source, java] ---- @Override public void postLogin(HttpServletRequest request, HttpServletResponse response, User user) { LoginOut loginOut = new LoginOut(); if (StringUtils.isNotEmpty(user.getJwt())) { loginOut.setToken(user.getJwt().substring(user.getJwt().lastIndexOf('.') + 1)); } loginOut.setUserId(user.getUserId()); loginOut.setLoginTime(new Date()); loginOut.setUseIp(user.getRecentLoginIp()); loginOut.setReqType("WEB"); loginOutLogService.insertLogin(loginOut); } ---- 로그인 시 사용자 ID, 로그인 시간, IP 등을 TN_CF_LOGIN_OUT 테이블에 저장한다. [source, java] ---- @Override public void preLogout(HttpServletRequest request, HttpServletResponse response, User user) { LoginOut loginOut = new LoginOut(); if (StringUtils.isNotEmpty(user.getJwt())) { loginOut.setToken(user.getJwt().substring(user.getJwt().lastIndexOf('.') + 1)); } loginOut.setUserId(user.getUserId()); loginOut.setLoginTime(user.getRecentLoginDatetime()); loginOut.setLogoutTime(new Date()); loginOut.setUseIp(webUtil.getClientIp(request)); loginOut.setReqType("WEB"); loginOutLogService.updateLogout(loginOut); userService.updateUserJwt(Map.of("userId", user.getUserId(), "lastLogoutDate", new Date(), "jwt", "")); } ---- 로그아웃 전에는 TN_CF_LOGIN_OUT에 정보를 저장하는 것 외에 사용자의 jwt 값을 초기화 한다. 중복 로그인 방지를 위해 jwt값을 이용한다.