Member 패키지는 기본적인 회원관리를 위한 클래스들이 담겨있는 패키지로 굉장히 간단한 회원가입 절차만을 구현했기 때문에 클래스들이 복잡하지 않고 각 패키지의 기능이나 역할들에 대해서는 앞선 게시글에서 충분히 다뤘기 때문에 간단하게 소개만 하고 넘어가려고 한다.
#1. Domain
com.security_board.security.member.domain.Member
package com.security_board.security.member.domain;
import com.security_board.security.util.Role;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Getter
@Table(name= "member")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 50, nullable = false)
private String email;
@Column(length = 100)
private String password;
@Column(length = 20, nullable = false)
private String name;
@Column(length = 20)
private String socialId;
@Enumerated(EnumType.STRING)
private Role role;
}
Board와 마찬가지로 Primary Key 역할을 하는 id와 함께 정말 기본적인 email, password 그리고 유저의 이름만 담는 간단한 entity로 구성했다.
#2. DTO
com.security_board.security.member.dto.MemberDto
package com.security_board.security.member.dto;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class MemberDto {
private String email;
private String password;
private String name;
public static MemberDto postDto(String email, String password, String name) {
return MemberDto.builder()
.email(email)
.password(password)
.name(name)
.build();
}
public static MemberDto getDto(String email, String name) {
return MemberDto.builder()
.email(email)
.name(name)
.build();
}
}
DTO는 등록할 때의 DTO와 다르게 조회할 때는 클라이언트에서 사용할 이메일과 이름만 가져올 수 있도록 만들었다.
#3. Repository
com.security_board.security.member.repository.MemberRepository
package com.security_board.security.member.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import com.security_board.security.member.domain.Member;
public interface MemberRepository extends JpaRepository<Member, Long>{
Optional<Member> findByEmail(@Param("email") String email);
Optional<Member> findBySocialId(@Param("socialId") String socialId);
}
#4. Contorller
com.security_board.security.member.contorller.MemberController
package com.security_board.security.member.contorller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.security_board.security.member.dto.MemberDto;
import com.security_board.security.member.service.MemberService;
import com.security_board.security.util.Header;
import lombok.AllArgsConstructor;
@RestController
@AllArgsConstructor
public class MemberController {
private final MemberService memberService;
@PostMapping("/signup")
public Header<String> signUp(@RequestBody MemberDto memberDto){
return memberService.saveMember(memberDto);
}
}
#5. Service
com.security_board.security.member.service.MemberService
package com.security_board.security.member.service;
import java.util.Optional;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.security_board.security.member.domain.Member;
import com.security_board.security.member.dto.MemberDto;
import com.security_board.security.member.repository.MemberRepository;
import com.security_board.security.util.Header;
import com.security_board.security.util.MemberMapper;
import jakarta.transaction.Transactional;
import lombok.AllArgsConstructor;
@Service
@Transactional
@AllArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;
public Header<String> saveMember(MemberDto memberDto) {
if(this.searchMember(memberDto.getEmail()).isPresent()) {
return Header.ERROR("동일한 이메일이 존재합니다");
}
memberRepository.save(MemberMapper.toEntityFromPostDto(memberDto, passwordEncoder));
return Header.OK("성공적으로 가입되었습니다");
}
public Optional<Member> searchMember(String email){
return memberRepository.findByEmail(email);
}
public boolean validatePassword(String rawPassword, Member member) {
return passwordEncoder.matches(rawPassword, member.getPassword());
}
}
#6. Util
com.security_board.security.util.MemberMapper
package com.security_board.security.util;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.security_board.security.member.domain.Member;
import com.security_board.security.member.dto.MemberDto;
public class MemberMapper {
public static MemberDto toGetDtoFromEntity(Member member) {
return MemberDto.getDto(
member.getEmail(),
member.getName()
);
}
public static Member toEntityFromPostDto(MemberDto memberDto, PasswordEncoder passwordEncoder) {
Member member = Member.builder()
.email(memberDto.getEmail())
.password(passwordEncoder.encode(memberDto.getPassword()))
.name(memberDto.getName())
.role(Role.USER)
.build();
return member;
}
}
com.security_board.security.util.Role
package com.security_board.security.util;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum Role {
ADMIN("ROLE_ADMIN", "관리자"),
USER("ROLE_USER", "일반 사용자"),
NOT_REGISTERED("ROLE_NOT_REGISTERED", "회원가입 이전 사용자");
private final String key;
private final String title;
}