-
[스프링MVC - 2편] 로그인 처리1 - 쿠키, 세션스프링&스프링부트 2025. 3. 4. 20:30
패키지 구조 설계
package 구조
- hello.login
- domain
- item
- member
- login
- web
- item
- member
- login
- domain
도메인이 가장 중요하다
도메인 = 화면, UI, 기술 인프라 등등의 영역은 제외한 시스템이 구현해야 하는 핵심 비즈니스 업무 영역을 말한다
향후 web을 다른 기술로 바꾸어도 도메인은 그대로 유지할 수 있어야 한다
이렇게 하려면 web은 domain을 알고있지만 domain은 web을 모르도록 설계해야 한다
이것을 web은 domain을 의존하지만, domain은 web을 의존하지 않는다고 표현한다
홈 화면
HomeController - home() 수정
@GetMapping("/") public String home() { return "home"; }
- templates/home.html 추가
회원 가입
Member
@Data public class Member { private Long id; @NotEmpty private String loginId; // 로그인 ID @NotEmpty private String name; // 사용자 이름 @NotEmpty private String password; }
MemberRepository
/** * 동시성 문제가 고려되어 있지 않음, 실무에서는 ConcurrentHashMap, AtomicLong 사용 고려 */ @Slf4j @Repository public class MemberRepository { private static Map<Long, Member> store = new HashMap<>(); private static long sequence = 0L; //static 사용 public Member save(Member member) { member.setId(++sequence); log.info("save: member={}", member); store.put(member.getId(), member); return member; } public Member findById(Long id) { return store.get(id); } public Optional<Member> findByLoginId(String loginId) { return findAll().stream() .filter(m -> m.getLoginId().equals(loginId)) .findFirst(); } public List<Member> findAll() { return new ArrayList<>(store.values()); } public void clearStore() { store.clear(); } }
MemberController
@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:/"; } }
- 회원 가입 뷰 템플릿 : templates/members/addMemberForm.html 생성
회원용 테스트 데이터 추가
TestDataInit
@Component @RequiredArgsConstructor public class TestDataInit { private final ItemRepository itemRepository; private final MemberRepository memberRepository; @PostConstruct public void init() { itemRepository.save(new Item("itemA", 10000, 10)); itemRepository.save(new Item("itemB", 20000, 20)); Member member = new Member(); member.setLoginId("test"); member.setPassword("test!"); member.setName("테스터"); memberRepository.save(member); } }
로그인 기능
LoginService
@Service @RequiredArgsConstructor public class LoginService { private final MemberRepository memberRepository; /** * @return null이면 로그인 실패 */ public Member login(String loginId, String password) { return memberRepository.findByLoginId(loginId) .filter(m -> m.getPassword().equals(password)) .orElse(null); } }
LoginForm
@Data public class LoginForm { @NotEmpty private String loginId; @NotEmpty private String password; }
LoginController
@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:/"; } }
- 로그인 폼 뷰 템플릿 : templates/login/loginForm.html 생성
로그인 처리하기 - 쿠키 사용
쿠키에는 영속 쿠키와 세션 쿠키가 있다
- 영속 쿠키 : 만료 날짜를 입력하면 해당 날짜까지 유지
- 세션 쿠키 : 만료 날짜를 생략하면 브라우저 종료시 까지만 유지
LoginController - login()
로그인 성공시 세션 쿠키를 생성
@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:/"; }
728x90'스프링&스프링부트' 카테고리의 다른 글
[스프링MVC - 2편] 검증 (4) (0) 2025.03.02 [스프링MVC - 2편] 검증 (3) (1) 2025.03.02 [스프링MVC - 2편] 검증 (2) (0) 2025.02.09 [스프링MVC - 2편] 검증 (1) (0) 2025.02.08 [스프링MVC - 2편] 메시지, 국제화 (0) 2025.02.04 - hello.login