스프링 부트 쇼핑몰 프로젝트 with JPA (4)
스프링 시큐리티를 이용한 회원가입 및 로그인 -1
📌 스프링 시큐리티 설정 추가하기
<pom.xml>

📌 회원가입 기능 구현하기
package com.shop.constant;
public enum Role {
    USER, ADMIN
}
👆🏻회원이 일반 유저인지, 관리자인지 구분하기 위한 Role 클래스
<pom.xml>
<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>package com.shop.dto;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
@Getter
@Setter
public class MemberFormDto {
    @NotBlank(message = "이름은 필수 입력 값입니다.")
    private String name;
    @NotEmpty(message = "이메일은 필수 입력 값입니다.")
    private String email;
    @NotEmpty(message = "비밀번호는 필수 입력 값입니다.")
    @Length(min=8, max=16, message = "비밀번호는 8자 이상, 16자 이하로 입력해주세요")
    private String password;
    @NotEmpty(message = "주소는 필수 입력 값입니다.")
    private String address;
}👆🏻회원가입 화면으로부터 넘어온 회원의 정보를 담을 MemberFormDto 클래스. 회원가입 시 서버로 넘어오는 값을 검증하기 위해 javax.validation 어노테이션 사용.
ENTITY
package com.shop.entity;
import com.shop.constant.Role;
import com.shop.dto.MemberFormDto;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.security.crypto.password.PasswordEncoder;
import javax.persistence.*;
@Entity
@Table(name="member")
@Getter@Setter
@ToString
public class Member{
    @Id
    @Column(name="member_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    @Column(unique = true)
    private String email;
    private String password;
    private String address;
    @Enumerated(EnumType.STRING)
    private Role role;
    public static Member createMember(MemberFormDto memberFormDto, PasswordEncoder passwordEncoder){
        Member member = new Member();
        member.setName(memberFormDto.getName());
        member.setEmail(memberFormDto.getEmail());
        member.setAddress(memberFormDto.getAddress());
        String password = passwordEncoder.encode(memberFormDto.getPassword());
        member.setPassword(password);
        member.setRole(Role.ADMIN);
        return member;
    }
}
👆🏻회원정보를 저장하는 Member 엔티티. 이메일을 통해 회원을 구분하므로 중복된 값이 데이터베이스에 들어올 수 없도록 @Column(unique = true)를 설정함. createMember()는 Member 엔티티를 생성하는 메소드이다.
REPOSITORY
package com.shop.repository;
import com.shop.entity.Member;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MemberRepository extends JpaRepository<Member, Long> {
    //회원 가입 시 중복 회원 검사(쿼리 메소드)
    Member findByEmail(String email);
}
👆🏻MemberRepository는 Member 엔티티를 데이터베이스에 저장함. 이메일로 중복된 회원이 있는지 검사하기 위해 쿼리 메소드를 작성함.
SERVICE
package com.shop.service;
import com.shop.entity.Member;
import com.shop.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import 
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
@RequiredArgsConstructor
public class MemberService implements UserDetailsService {
    private final MemberRepository memberRepository;
    public Member saveMember(Member member){
        validateDuplicateMember(member);
        return memberRepository.save(member);
    }
    private void validateDuplicateMember(Member member){
        Member findMember = memberRepository.findByEmail(member.getEmail());
        if(findMember != null) {
            throw new IllegalStateException("이미 가입된 회원입니다.");
        }
    }   
}
👆🏻@Transactional 어노테이션을 선언하면 로직을 실행하다가 에러가 발생 시, 로직이 실행되기 전으로 롤백 시켜줌. @RequiredArgsConstructor 어노테이션은 final이나 @NonNull이 붙은 필드에 생성자를 생성해줘 빈을 주입함.
CONTROLLER
package com.shop.controller;
import lombok.RequiredArgsConstructor;
import com.shop.dto.MemberFormDto;
import com.shop.service.MemberService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/members")
@RequiredArgsConstructor
public class MemberController {
    private final MemberService memberService;
    private final PasswordEncoder passwordEncoder;
    @GetMapping("/new")
    public String memberForm(Model model){
        model.addAttribute("memberFormDto", new MemberFormDto());
        return "member/memberForm";
    }
    
    @PostMapping("/new")
    public String memberForm(@Valid MemberFormDto memberFormDto, BindingResult bindingResult, Model model){
        if(bindingResult.hasErrors()){
            return "member/memberForm";
        }
        try{
            Member member = Member.createMember(memberFormDto, passwordEncoder);
            memberService.saveMember(member);
        } catch (IllegalStateException e){
            model.addAttribute("errorMessage", e.getMessage());
            return "member/memberForm";
        }
        return "redirect:/";
    }
}👆🏻회원가입 페이지로 이동할 수 있도록 @GetMapping으로 memberForm 메소드 작성. 검증하려는 객체 앞에 @Valid 어노테이션 선언하고, bindingResult를 파라미터로 추가하면 검사 결과가 bindingResult에 담김. bindingResult.hasErrors()일 경우 회원가입 페이지로 이동함. Member 엔티티를 생성하여 데이터베이스에 저장함. 회원 가입 시 중복 회원 예외가 발생하면 에러 메시지를 뷰로 전달함.
package com.shop.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
    @GetMapping("/")
    public String main(){
        return "main";
    }
}
Author And Source
이 문제에 관하여(스프링 부트 쇼핑몰 프로젝트 with JPA (4)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@uuuuu_j_/스프링-부트-쇼핑몰-프로젝트-with-JPA-4저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)