이 내용은 스프링 부트 쇼핑몰 프로젝트 with JPA 책을 학습한 내용입니다.
1. 회원 역할(Role) 구분
- kr.spring.member.constant.java, enum클래스 생성
- 일반 유저 / 관리자
package kr.spring.member.constant;
// 회원 역할 구분 enum 클래스
public enum Role {
USER, ADMIN
}
2. 회원 가입 정보 DTO
- 회원 가입 화면으로부터 넘어오는 가입정보를 담을 DTO 객체
// validation 추가 -> null 값 접근하기 위해
implementation 'org.springframework.boot:spring-boot-starter-validation:3.0.1'
package kr.spring.member.dto;
// 회원가입 화면으로부터 넘어오는 가입정보를 담을 Dto
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.validator.constraints.Length;
@Getter
@Setter
@ToString
public class MemberFormDto {
@NotBlank(message = "이름은 필수 항목입니다.")
private String name;
@NotEmpty(message = "이메일은 필수 항목입니다.")
@Email(message = "이메일 형식으로 입력하세요.")
private String email;
@NotEmpty(message = "비밀번호는 필수 항목입니다.")
@Length(min = 4, max = 12, message = "최소 4자, 최대 12자를 입력하세요.")
private String password;
@NotEmpty(message = "주소는 필수 항목입니다.")
private String address;
}
3. Member Entity
- 회원 정보를 저장하는 Member Entity(Model) 생성
- Member 객체를 생성하기 위해 Member 객체 안에 createMember() static 메소드 생성
package kr.spring.member.entity;
// 회원 엔티티
import jakarta.persistence.*;
import kr.spring.member.constant.Role;
import kr.spring.member.dto.MemberFormDto;
import kr.spring.utils.entity.BaseEntity;
import lombok.*;
import org.springframework.security.crypto.password.PasswordEncoder;
@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Member extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id;
private String name;
@Column(unique = true)
private String email;
private String password;
private String address;
@Enumerated(EnumType.STRING) // 추가를 안하면 열거형은 숫자로 들어감
private Role role;
//사용자 만들기 -> 받아온 DTO를 entity로 변경해준다
public static Member createMember(MemberFormDto memberFormDto, PasswordEncoder passwordEncoder) {
//먼저 Member entity를 만들어준다.
Member member = new Member();
member.setName(memberFormDto.getName()); //실제 웹에서 받아올 이름이니까 dto에서 받아온다
member.setEmail(memberFormDto.getEmail());
member.setAddress(memberFormDto.getAddress());
member.setRole(Role.USER); //기본으로 다 학생으로 가입
String password = passwordEncoder.encode(memberFormDto.getPassword()); //일단 비밀번호를 플레인 텍스트로 받아온다. 후 encode를 이용해서 암호화
member.setPassword(password); //암호화된 패스워드를 넣는다
//만든 member 리턴
return member;
}
}
4. MemberRepository
- 회원가입 시 중복 여부를 판단하기 위해서 이메일로 회원을 검사하도록 쿼리 메소드 작성
package kr.spring.member.repository;
import kr.spring.member.entity.Member;
import org.springframework.data.jpa.repository.JpaRepository;
//저장도 하고 데이터를 가져올 수도 있지만 디테일하게 메소드를 만들어서 사용할 수도 있음!
//jpql을 이용하거나 querydsl을 이용하거나
public interface MemberRepository extends JpaRepository<Member, Long> {
// 문자로 된 이메일을 넣어서 검색하겠다.
// 이메일이 있거나 없거나. 이걸 member로 해도 되지만 자바에서는 최근에 Optional을 사용한다.
// 결과가 있을 수도 있고, 없을 수도 있는 상태
// Optional<Member> findByEmail(String email);
Member findByEmail(String email); // 이메일 받아오기
}
5. MemberService
- @RequiredArgsConstructor를 사용하여 memberRepository DI
package kr.spring.member.service;
import kr.spring.member.entity.Member;
import kr.spring.member.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
// DB로 값을 가져오거나 controller로 가기 전에 따로 처리해야 할 기능이 있다
@Service
@Transactional
@Log4j2
//final이 붙은 애들을 올려준다 이게 싫으면 @autowired 쓰면 됨
//일반적으로 controller나 service에서 쓰면 상관이 없는데 test에서는 이걸 쓰면 에러가 난다.
@RequiredArgsConstructor
public class MemberService implements UserDetailsService {
private final MemberRepository memberRepository;
public Member saveMember(Member member) {
// 중복확인
validateDuplicate(member);
// 중복확인 후 회원 저장
return memberRepository.save(member);
}
private void validateDuplicate(Member member) {
//이메일로 찾았을 때 값이 있는지 없는지 판단
Member findMember = memberRepository.findByEmail(member.getEmail());
// DB에서 이메일이 검색이 되면 이미 등록되어있는 회원이라는 알림 표시
if(findMember != null) {
throw new IllegalStateException("이미 등록된 사용자 입니다.");
}
}
}