블로그 만들기 9. 로그인 구현 : 오류잡기

Feb 05, 2024
블로그 만들기 9. 로그인 구현 : 오류잡기

1. 로그인 할 때 터지는 것 해결하기

  • 원인 : 받을 때 결과값이 없어서 터짐
  • 게시글 내부에 try/catch가 내재되어 있을 때
내가 만든 것이 아니니까 직접 제어할 방법 : 위치를 찾아서 직접 try/catch로 묶기
  • @Entity
Entity : DB데이터와 같은 테이블을 만들어 줌
반드시 @entity가 걸려있는 class여야 파싱이 됨
데이터 테이블을 Entity에 담아서 민감한 정보들을 DTO에 담아서 전달함
응답 받을 때) object를 리턴하니까 다운 캐스팅해서 받으면 됨
💡
오류가 안나오면 = 어디서 터졌는지 모르면
하나하나 다 번호를 남겨서 실행해서 위치를 찾으면 됨
 

2. 위치를 찾아서 직접 try/catch로 묶기

public User findByUsernameAndPassword(UserRequest.loginDTO requestDTO) { Query query = em.createNativeQuery("SELECT * FROM user_tb WHERE username=? AND password=?", User.class); // 알아서 매핑해줌 query.setParameter(1, requestDTO.getUsername()); query.setParameter(2, requestDTO.getPassword()); try { // 내부적으로 터지면 터지는 위치를 찾아서 내가 잡으면 됨 User user = (User) query.getSingleResult(); return user; }catch (Exception e){ return null; }
💡
컨트롤러 만들 때 책임 다 만들기!
다 만들고 넘어가면 컨트롤러에서 오류가 나지 않음
그렇지 않으면 컨트롤러에서 난 오류를 DB가 출력해 줌
 
package shop.mtcoding.blog.user; import jakarta.servlet.http.HttpSession; import org.springframework.context.annotation.ComponentScan; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @Controller public class UserController { // fianl 변수는 반드시 초기화 되어야 함 private final UserRepository userRepository; // null private final HttpSession session; public UserController(UserRepository userRepository, HttpSession session) { this.userRepository = userRepository; this.session = session; } //원래는 get요청이나 예외 post요청하면 됨 //민감한 정보는 쿼리 스트링에 담아보낼 수 없음 @PostMapping("/login") public String login(UserRequest.LoginDTO requestDTO) { // 1. 유효성 검사 if(requestDTO.getUsername().length() < 3) { return "error/400"; } // 2. 모델 필요 select * from user_tb where username=? and password=? User user = userRepository.findByUsernameAndPassword(requestDTO); // DB에 조회할때 필요하니까 데이터를 받음 if (user == null) { return "error/401"; }else { session.setAttribute("sessionUser", user); return "redirect:/"; } } @PostMapping("/join") public String join(UserRequest.JoinDTO requestDTO) { System.out.println(requestDTO); // 1. 유효성 검사 if (requestDTO.getUsername().length() < 3) { return "error/400"; } userRepository.save(requestDTO); // 모델에 위임하기 return "redirect:/loginForm"; //리다이렉션불러놓은게 있어서 다시부른거 } @GetMapping("/joinForm") // view만 원함 public String joinForm() { return "user/joinForm"; } @GetMapping("/loginForm") // view만 원함 public String loginForm() { return "user/loginForm"; } @GetMapping("/user/updateForm") public String updateForm() { return "user/updateForm"; } @GetMapping("/logout") public String logout() { return "redirect:/"; } }
notion image

3. try/catch 안 하는 이유

  • 터트린 것을 잡겠다는 것 → 통신만 이루어지지 않음
insert 시도하기 위한 하드디스크 접촉까지 일어나 IO가 일어남
  • DB는 하드디스크에 저장된 데이터를 저장된 문서를 들고 있는 것을 메타 데이터로 적어놓음
안 적어놓으면 직접 찾아가서 넣으려고 하다가 못 넣어서 실패하는 과정 또한 비용이 많이 듦
→ 데이터 사전(메타데이터)같은 것 : 데이터 사서가 확인해서 오류이면 터뜨림
  • 경우의 수가 너무 다양해서 에러를 명확하게 판단하기 힘듦
→ try/catch 는 어쩔 수 없는 상황에서 써야 함
 

4. 유효성 검사를 미리 감지

  • try/catch보다 코드를 짜는게 더 좋음!!
  • 얘도 조회해야되니까 IO가 일어나긴함
ex) 3명이 오차 없이 정확하게 동시에 접속해서 join요청을 함
각각 3개의 스레드가 생김 → 리쿼스트 객체 2개가 각각 생성
UserController는 메모리에 하나 떠 있음
join이라는 메서드는 호출(실행)시 스택 메모리에 뜸
→ 객체는 1개이나 메서드는 3개가 될 수 있음
동시에 실행되고 독립적인 공간이 생기니까 싱크로나이즈드 할 필요가 없음
DAO도 메서드라 동시에 실행됨
  • read는 동시에 가능함
  • write가 있는 순간 불가능해짐
ex) 회원가입을 하는데 데이터에 ssar만 있음
셋 다 db에 cos라는 id가 있는지 동시에 요청해서 없는 것을 확인
셋 다 동시에 cos라고 요청하면 두 명은 터지게 됨
→ read는 상관없음 insert때문에 터지는 것
insert는 한 명에게 rock을 걸려서 다른 사람들은 isolation(고립)됨
다른 사람을 느리게 만드는 wait가 걸리니까 최대한 자제하는 것이 좋음
얘 때문에 다른 사람이 rock 걸릴 수가 있으니까 최대한 안 터뜨리는 것이 좋음
 
Share article
RSSPowered by inblog