Back-End/Spring
[Spring Boot] 회원 연습 (4) - 로그인
09009
2024. 1. 22. 18:23
MemberController
package com.yyi.member.controller;
import com.yyi.member.dto.MemberDTO;
import com.yyi.member.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
@RequiredArgsConstructor
public class MemberController {
// 생성자 주입
private final MemberService memberService;
// 회원가입 페이지 출력 요청
@GetMapping("/member/save")
public String saveForm() {
return "save"; // templates 폴더에서 "save"라는 html 파일을 찾는다.
}
@PostMapping("/member/save")
public String save(@ModelAttribute MemberDTO memberDTO) {
System.out.println("MemberController.save");
System.out.println("memberDTO = " + memberDTO);
memberService.save(memberDTO);
return "login";
}
}
로그인 페이지 생성하기
templates 폴더에 login.html 생성
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="/member/login" method="post">
이메일 : <input type="text" name="memberEmail"> <br>
비밀번호 : <input type="password" name="memberPassword"> <br>
<input type="submit" value="로그인">
</form>
</body>
</html>
MemberController
@GetMapping("/member/login")
public String loginForm() {
return "login";
}
로그인 메서드 생성
아직 service에 login 메서드가 없기 때문에 오류 발생 (신경 쓰지 않아도 된다)
MemberController
@PostMapping("/member/login")
public String login(@ModelAttribute MemberDTO memberDTO) {
MemberDTO loginResult = memberService.login(memberDTO);
if (loginResult != null) {
// 로그인 성공
return "main";
} else {
// 로그인 실패
return "login";
}
}
이전에 회원가입할 때 사용한 save 메서드는 repository에 없었다.
그 이유는, MemberRepository는 JpaRepository에서 상속을 받아 save 메서드를 제공받았기 때문에
MemberService
public MemberDTO login(MemberDTO memberDTO) {
/*
1. 회원이 입력한 이메일로 DB에서 조회를 함
2. DB에서 조회한 비밀번호와 사용자가 입력한 비밀번호가 일치하는지의 여부 확인
* */
}
MemberRepository
public interface MemberRepository extends JpaRepository<MemberEntity, Long> {
// 이메일로 회원 정보 조회 (select * from member_table where member_email = ? 쿼리를 메서드 정의만으로 실행시키기 위함)
// Optional : java.util에서 제공하는 클래스 (null 방지 위함)
// 모든 repository에서 주고받는 객체는 모두 entity 객체의 형태, 즉 entity 객체로 return을 받는다
Optional<MemberEntity> findByMemberEmail(String memberEmail);
}
MemberService
public MemberDTO login(MemberDTO memberDTO) {
/*
1. 회원이 입력한 이메일로 DB에서 조회를 함
2. DB에서 조회한 비밀번호와 사용자가 입력한 비밀번호가 일치하는지의 여부 확인
* */
// optional 객체로 return 받기, entity 객체를 optional 객체로 한 번 더 감싼 개념 (포장지 두 개로 생각)
Optional<MemberEntity> byMemberEmail = memberRepository.findByMemberEmail(memberDTO.getMemberEmail());
if (byMemberEmail.isPresent()) {
// 조회 결과가 있을 경우 (해당 이메일을 가진 회원 정보가 있을 때)
// get() 메서드 : optional로 감싸진 객체를 하나의 포장지를 벗겨내는 느낌의 메서드
MemberEntity memberEntity = byMemberEmail.get();
// ↓ 비밀번호 일치 여부 확인
if (memberEntity.getMemberPassword().equals(memberDTO.getMemberPassword())) {
// 비밀번호 일치
// Entity로 DB에서 조회를 했지만, 컨트롤러로 넘겨줄 땐 DTO로 넘겨준다.
// Entity 객체는 service 클래스 안에서만 사용하도록 일단 계획. 컨트롤러에서는 dto 객체 사용
// 작업 : entity 객체 -> dto 변환 후 return
} else {
// 비밀번호 불일치 (로그인 실패)
return null;
}
} else {
// 조회 결과가 없을 경우 (해당 이메일을 가진 회원 정보가 없을 때)
return null;
}
}
entity 객체를 dto로 변환하기 위해서 DTO 클래스에서 작업
MemberDTO 메서드 추가
package com.yyi.member.dto;
import com.yyi.member.entity.MemberEntity;
import lombok.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class MemberDTO {
private Long id;
private String memberEmail;
private String memberPassword;
private String memberName;
public static MemberDTO toMemberDTO(MemberEntity memberEntity) {
MemberDTO memberDTO = new MemberDTO();
memberDTO.setId(memberEntity.getId());
memberDTO.setMemberEmail(memberEntity.getMemberEmail());
memberDTO.setMemberPassword(memberEntity.getMemberPassword());
memberDTO.setMemberName(memberEntity.getMemberName());
return memberDTO;
}
}
MemberService 코드 추가
public MemberDTO login(MemberDTO memberDTO) {
/*
1. 회원이 입력한 이메일로 DB에서 조회를 함
2. DB에서 조회한 비밀번호와 사용자가 입력한 비밀번호가 일치하는지의 여부 확인
* */
// optional 객체로 return 받기, entity 객체를 optional 객체로 한 번 더 감싼 개념 (포장지 두 개로 생각)
Optional<MemberEntity> byMemberEmail = memberRepository.findByMemberEmail(memberDTO.getMemberEmail());
if (byMemberEmail.isPresent()) {
// 조회 결과가 있을 경우 (해당 이메일을 가진 회원 정보가 있을 때)
// get() 메서드 : optional로 감싸진 객체를 하나의 포장지를 벗겨내는 느낌의 메서드
MemberEntity memberEntity = byMemberEmail.get();
// ↓ 비밀번호 일치 여부 확인
if (memberEntity.getMemberPassword().equals(memberDTO.getMemberPassword())) {
// 비밀번호 일치
// Entity로 DB에서 조회를 했지만, 컨트롤러로 넘겨줄 땐 DTO로 넘겨준다.
// Entity 객체는 service 클래스 안에서만 사용하도록 일단 계획. 컨트롤러에서는 dto 객체 사용
// 작업 : entity 객체 -> dto 변환 후 return
MemberDTO dto = MemberDTO.toMemberDTO(memberEntity);
return dto;
} else {
// 비밀번호 불일치 (로그인 실패)
return null;
}
} else {
// 조회 결과가 없을 경우 (해당 이메일을 가진 회원 정보가 없을 때)
return null;
}
}
MemberController
@GetMapping("/member/login")
public String loginForm() {
return "login";
}
@PostMapping("/member/login")
public String login(@ModelAttribute MemberDTO memberDTO, HttpSession session) {
MemberDTO loginResult = memberService.login(memberDTO);
if (loginResult != null) {
// 로그인 성공
session.setAttribute("loginEmail", loginResult.getMemberEmail());
return "main";
} else {
// 로그인 실패
return "login";
}
}
(다른 코드)
@PostMapping("/member/login")
public String login(@ModelAttribute MemberDTO memberDTO, HttpSession session) {
MemberDTO sessionUser = memberService.login(memberDTO);
if (sessionUser != null) {
session.setAttribute("memberDTO", sessionUser);
return "main";
} else {
return "login";
}
}
main.html 생성 후 코드 작성
타임리프 적용
xmlns:th="http://www.thymeleaf.org"
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
session 값 확인 : <p th:text="${session.loginEmail}"></p>
</body>
</html>
(다른 코드)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>main</title>
</head>
<body>
session 값 확인 : <p th:text="${session.memberDTO.memberEmail}"></p>
</body>
</html>
application.yml 확인 - ddl-auto는 update로
# spring data jpa 설정
jpa:
database-platform: org.hibernate.dialect.OracleDialect
open-in-view: false
show-sql: true
hibernate:
ddl-auto: update
여기까지 코드 작성 후 실행시키기
로그인 수행 후 모습