회원가입 기능구현

김소희·2023년 12월 11일
1

Member Entity 생성

  • build gradle에
    implementation 'implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.2.0'를 추가하고
    @Entity와 @Table(name = "members")를 사용하여 엔티티를 작성했다.
    JPA 버전 확인 하기
  • build gradle에 자바 17과 호환되는 롬북 최선 버전을 추가하고 @Getter, @Setter를 추가했다.
    compileOnly 'org.projectlombok:lombok:1.18.30'
    annotationProcessor 'org.projectlombok:lombok:1.18.30'
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

import java.util.Date;

@Getter
@Setter
@Entity
@Table(name = "members")
public class Member extends Auditable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer memberId;

    @Column(unique = true, nullable = false)
    private String email;

    @Column(length = 20, nullable = false)
    private String password;
    
    //이하생략
    
}

Auditable class 생성

생성시간인 createdAt는 회원뿐만 아니라 주요 엔티티가 모두 사용하기 때문에
공용으로 코드를 재활용해서 사용하기 위해서 추상클래스로 만들고 extends(상속)받았다.
그리고 SpringApplication에 @EnableJpaAuditing 붙이면 잘 작동한다.

@Getter
@Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable {

    @CreatedDate
    @Column(name= "createdAt", updatable = false)
    private LocalDate createdAt;

    @LastModifiedDate
    @Column(name= "modifiedAt")
    private LocalDate modifiedAt;


}

DTO 생성

자바 17을 처음 사용해보기 때문에 자바 11에는 없었던 record 키워드를 사용하여 DTO를 만들었다.
record란 불변 데이터 객체로 생성자를 작성하지 않아도 되고 toString, equals, hashCode 메소드에 대한 구현을 자동으로 제공하며 코드가 더 간결해진다.
하단에는 bulder를 사용하여 DTO를 Entity로 변환해주는 코드를 만들었다.

build gradle에 implementation 'org.springframework.boot:spring-boot-starter-validation'를 추가하면 @NotBlank이나, @Email 등을 사용하여 데이터를 검증할 수 있다.

예를들어 비밀번호는 영문, 숫자를 포함한 8자 이상 20자 이하라는 요구사항이 있을 경우, 프론트에서도 검증을 하겠지만 백엔드에서도 검증을 거치면 데이터 품질을 높일 수 있다.

import jakarta.validation.constraints.*;

public record JoinRequest(

        @NotNull(message = "이메일은 필수 입력 사항입니다.")
        @NotBlank(message = "이메일은 공백일 수 없습니다.")
        @Email(message = "올바른 이메일 주소 형식으로 작성해주세요.")
        @Size(max = 50, message = "이메일은 50글자 이내로 입력해주세요.")
        String email,

        @NotNull(message = "비밀번호는 필수 입력 사항입니다.")
        @NotBlank(message = "비밀번호는 공백일 수 없습니다.")
        @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d).{8,20}$",
                message = "영문, 숫자를 포함한 8자 이상 20자 이하의 비밀번호를 입력해주세요.")
        String password,
        
        //이하생략
) {   
		public Member toEntity() {
                return Member.builder()
                        .email(email())
                        .password(password())
                        .name(name())
                        ...
                        .build();
        }
        
}

Controller

회원가입 이후에 자동 로그인을 하는 경우와 로그인 페이지로 이동시키는 경우가 있는데
자동 로그인의 경우에는 자신의 아이디와 비번에 대해서 까먹게 되는 경우가 다수 발생하고,
로그인시 '아이디 기억하기' 기능을 사용할 수 없게 되므로 로그인 계정의 확인 과정으로서
회원가입이 완료되었다는 정보를 주는 것으로 요구사항이 결정되었다.

따라서 Controller 코드는 간단했고, Dto를 Entity로 바꾸어서 Service로 전달하였다.

@RestController
@RequiredArgsConstructor
public class MemberController {

    private final MemberService memberService;

    @PostMapping("/join")
    public ResponseEntity<String> join(@RequestBody @Valid JoinRequest joinRequest) {

        memberService.createNewMember(joinRequest.toEntity());

        return ResponseEntity.ok("회원가입이 성공적으로 완료되었습니다.");
    }

Service

서비스에서는 이미 회원가입된 이메일로는 회원가입이 불가한 점을 고려하여
데이터베이스에 email을 한번 확인 한 후에 중복이 있을 경우엔 예외처리를 하였다.

비밀번호는 사용자가 입력한 그대로 데이터베이스에 저장하는 것이 아니라 암호화로 해싱처리를 해야하는데 현재 security 설정을 하지 않았기 때문에 우선 주석처리하였다.

@Service
@Transactional
@RequiredArgsConstructor
public class MemberService {

    private final MemberRepository memberRepository;
//    private final PasswordEncoder passwordEncoder;

    public void createNewMember(Member member) {
        // 이메일 중복 체크
        if (isEmailAlreadyExists(member.getEmail())) {
            throw new BusinessLogicException(ExceptionCode.MEMBER_EMAIL_ALREADY_EXISTS);
        }
//        String encryptedPassword = passwordEncoder.encode(member.getPassword());
//        member.setPassword(encryptedPassword);
        memberRepository.save(member);
    }

    private boolean isEmailAlreadyExists(String email) {
        Optional<Member> optionalMember = memberRepository.findByEmail(email);
        return optionalMember.isPresent();
    }

}

Postman으로 테스트

HTTP post, 엔트포인트, json타입의 바디를 작성하여 테스트해보았다.

  • 성공시 상태코드 200 OK와, 완료문구를 보여준다.

  • 동일한 요청을 한번 더 보내보면 이메일 중복으로 인해 요청이 실패되는데 기본 응답메세지로는 원인을 상세하게 알기가 어렵다.

  • enum ExceptionCode를 작성하고, ErrorResponse class를 만들어서 커스텀 응답메세지를 호출하게끔 변경하여 에러 원인을 정확히 파악할 수 있도록 하였다.

profile
백엔드 자바 개발자 소희의 노트

0개의 댓글