- review (로그인)
이전 주차에서는 회원가입 및 로그인을 진행.
회원가입한 user의 data를 h2-database에 저장까지 완료
- preview (회원정보 보기)
DB에 저장되어 있을 로그인 정보를 가져와서 회원정보 페이지에 뿌리려고 합니다.
Spring에서 사용하는 기본 전략인 MVC 패턴에서 이번에는 Controller
→ Service
→ Repository
이 세 파트를 주력으로 설명하겠습니다.
// start of UserController
@PostMapping("/login")
public String login(@Valid UserRequest.LoginDTO requestDTO, Errors errors) {
User sessionUser = userService.로그인(requestDTO);
session.setAttribute("sessionUser", sessionUser); // #1. session 저장소에 User 객체 저장
return "redirect:/";
}
@GetMapping("/user/updateForm")
public String updateForm(HttpServletRequest request) {
User sessionUser = (User) session.getAttribute("sessionUser"); //#2-1
UserResponse.DTO responseDTO = userService.회원정보폼보기(sessionUser.getId()); #2-2
request.setAttribute("user", responseDTO);
return "user/updateForm";
} //#2. server-side 렌더링
// end of UserController
이전에 login 페이지를 작성할 때, session
에 User
객체를 저장해 두었습니다.
session에 저장해 둔 값은 언제든 가져올 수 있는 값이기에 회원정보를 조회하기 위해서 user의 id와 name, email 값을 가져오려 합니다.
updateForm을 호출할 때, HttpServletRequest request
를 받아옵니다.
화면이 redirect 되는것이 아닌, server 안에서 내부적으로 리렌더링 된 후 완성된 값을 가져오는 것이라 정보의 손실없이 전달 가능합니다.
server에서 모든 정보를 처리한 뒤 완전한 페이지를 return 한다고 하여 Server-side Rendering 이라고 합니다.
* redirect : request 요청이 2번 일어나기에 중간에서 전달하고자 하는 정보가 손실될 수 있습니다.
🥬 #2-1
seeion에 저장되어있는 User
객체를 받아오는 코드입니다.
getAttribute
의 return type은 Object로 받아오는데 session에 들어가있는 타입을 미리 알 수 없으니 부모인 Object로 받아와서 사용할 자식 객체로 downCasting 하여 사용하라는 의미입니다.
🥬 #2-2
controller → Service로 session에 저장되어있는 User의 id를 넘깁니다.
//start of UserService
public UserResponse.DTO 회원정보폼보기(Integer id) {
User userPS = userRepository.findById(id) //#1 Service → Repository
.orElseThrow(() -> new Exception404("해당 아이디로 자원을 찾을 수 없습니다. " +id));
return new UserResponse.DTO(userPS);
}
//end of UserService
🥕 #1. Service → Repository로 id 값을 넘기는 과정입니다,
//start of UserRepository
//SELECT * FROM USER_TB WHERE ID=1
//end of UserRepository
🥕#0. findById()
Service에서 사용된 findById()는 JPA에 내장되어 있는 메서드입니다.
따라서 구현을 할 필요가 없어 코드를 첨부하지 않았습니다
findById()는 나와있는 글자 그대로 Id 값을 기준으로 Database에서 값을 찾는 메서드입니다.
→ 여기서는 id값으로 Database에 들어가있는 user 정보를 가져오는 역할을 합니다.
//start of UserService
public UserResponse.DTO 회원정보폼보기(Integer id) {
User userPS = userRepository.findById(id)
.orElseThrow(() -> new Exception404("해당 아이디로 자원을 찾을 수 없습니다. " +id));
//#1.retrun type : Optional
return new UserResponse.DTO(userPS); //#1-1 응답 DTO
}
//end of UserService
//start of UserResponse (UserService에서 사용되는 class)
public class UserResponse { //#1-1 응답 DTO
@Data // getter, setter 생성
public static class DTO {
private int id;
private String username;
private String email;
public DTO(User user) {
this.id = user.getId();
this.username = user.getUsername();
this.email = user.getEmail();
}
}
}
//end of UserResponse
🥕 #1. retrun type : Optional< T >
앞전 포스팅에서 설명했던 Optional과 lamda 함수에 대한 적용입니다.
findById의 return 타입은 Optional< T >
입니다.
Repository를 통해 DB에서 id를 가진 User를 조회하지만, 값이 존재하지 않는 경우, null값이 UserPS에 담길 수 있습니다.
이때 null값도 허용하여 선물박스 안에 담는 Optional 객체를 사용하여 받아온 뒤 .orElseThrow
라는 메서드를 통해 만약 값이 null이라면 exception404를 터트리고, 그렇지 않다면 user의 값이 userPS에 담길 것입니다.
🥬#1-1 응답 DTO
주로 service의 역할은 트랜젝션 관리, 비지니스 플랜 등의 역할을 하지만 저는 추가적으로 응답 DTO생성 (UserResponse) 까지 포함하여 작성하였습니다.
🥬 Q. 응답 DTO의 생성 - why?
A. 회원정보 보기를 진행할 때에 필요한 User정보는 id와 username, email 입니다.
이 외의 불필요한 정보를 (ex Password) User객체에 그대로 담아서 보내게 된다면 FrontEnd에서 해당 DTO를 받게 되었을 때, 착오가 생길 수 있습니다.
// start of UserController
@GetMapping("/user/updateForm")
public String updateForm(HttpServletRequest request) {
User sessionUser = (User) session.getAttribute("sessionUser");
UserResponse.DTO responseDTO = userService.회원정보폼보기(sessionUser.getId());
//#1 Service로부터 받아온 responseDTO 저장
request.setAttribute("user", responseDTO); //#2. session에 정보저장
return "user/updateForm";
}
// end of UserController
🥕 #1. Service로부터 받아온 responseDTO 저장
UserService에서도 언급을 했듯, DB에서 가져온 User를 그대로 가져와도 되지만 resPonseDTO에 필요한 User의 값들만 담아 Controller로 가져왔습니다.
🥕#2. session에 정보저장
session 메모리 영역에 'user'라는 key값으로 userid, username, email이 담겨있습니다.
<form action="/user/update" method="post">
<div class="mb-3">
<input type="text" class="form-control" placeholder="Enter username" disabled value="{{user.username}}">
</div>
<div class="mb-3">
<input type="password" class="form-control" placeholder="Enter password" name="password">
</div>
<div class="mb-3">
<input type="email" class="form-control" placeholder="Enter email" disabled value="{{user.email}}">
</div>
<button type="submit" class="btn btn-primary form-control">회원가입수정</button>
</form>
🥕실제 updatefrom을 호출했을 때 불려오는 mustache 파일입니다.
Controller에서 session에 user
key값으로 저장한 useremail과 username을 value="{{user.username}}"
, value="{{user.email}}"
과 같은 방식으로 가져옵니다.
이렇게 하면 최종적으로 아래와 같이 현재 로그인한 사람의 정보를 들고와 회원정보를 열람하는것이 가능합니다.
🥕FIN🥕