본문 바로가기
IT 프로젝트 공모전(백엔드)

[Spring boot] 회원가입 기능구현 2(Domain)

by CromArchive 2025. 7. 15.
반응형

이제 본격적인 회원가입 기능 구현에 들어가보려고 한다.

*application.properties와 build.gradle에 의존성 설정같은것은 생략했다.

Domain패키지

Domain 패키지에서는 DB 테이블과 1:1로 매핑되는 JPA 엔티티로 구성한다.

User DB에는 User, Stack, Position, Organization으로 구성되어 있기 때문에 아래와 같이 코드를 작성하였다.

User.java 소스코드

package ssu.cromi.teamit.domain;

import jakarta.persistence.*;
import lombok.*;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;

//유저테이블 도메인
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)  // JPA 용
@AllArgsConstructor
@Data // @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor
@Entity
@Table(name = "users")
public class User {
    @Id
    @Column(name = "uid", length = 50, nullable = false, updatable = false)
    private String uid;
    @Column(name = "pw", length = 255, nullable = false)
    private String password;
    @Column(name = "nick_name", length = 100, nullable = false)
    private String nickName;
    @Column(name = "email", length = 255, nullable = false)
    private String email;
    @Column(name = "email_verified", length = 1, nullable = false)
    private Boolean emailVerified = false;
    @Column(nullable = false)
    private Integer birthday;
    @Column(nullable = false)
    private Long point;
    @Column(name = "profile_img", length = 2083)
    private String profileImg;
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;
    @Column(name = "my_score")
    private Double myScore;
    @Column(name = "roles", length = 50, nullable = false)
    private String roles = "ROLE_USER";
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;

    // 관계 매핑
    @ManyToMany
    @JoinTable(
            name = "user_organizations",
            joinColumns = @JoinColumn(name = "uid"),
            inverseJoinColumns = @JoinColumn(name = "organization_id")
    )
    private Set<Organization> organizations = new HashSet<>();

    @ManyToMany
    @JoinTable(
            name = "user_stacks",
            joinColumns = @JoinColumn(name = "uid"),
            inverseJoinColumns = @JoinColumn(name = "stack_id")
    )
    private Set<Stack> stacks = new HashSet<>();

    @ManyToMany
    @JoinTable(
            name = "user_positions",
            joinColumns = @JoinColumn(name = "uid"),
            inverseJoinColumns = @JoinColumn(name = "position_id")
    )
    private Set<Position> positions = new HashSet<>();

    public User(String uid, String password, String nickName, String email, Integer birthday) {
        this.uid = uid;
        this.password = password;
        this.nickName = nickName;
        this.email = email;
        this.birthday = birthday;
    }

    @ToString
    public enum RoleEnum {
        ROLE_USER,
        ROLE_ADMIN
    }
}

클래스 선언부

@Entity

이 클래스의 인스턴스(객체)를 데이터베이스의 한 row와 매핑 하겠다는 의미

@Table(name = “users”)

실제 테이블 이름을 users로 지정한다는 의미

Lombok 애노테이선

@Data

자동으로 Getter/Setter, toString, equalsAndHashCode등의 bean과 관련된 모든 재사용 가능한 코드를 생성해줌

@Builder

빌더 패턴을 지원한다는 의미

User u = User.builder()
             .uid("Crom")
             .nickName("Kiwi")
             .build();

@NoArgsConstructor(access = PROTECTED)

파라미터 없는 생성자를 만들되, 외부에서 직접 호출하지 못하도록 protected접근 제한 (JPA가 내부적으로 객체를 생성할 때 필요함)

@AllArgsConstructor

모든 필드를 파라미터로 받는 생성자를 자동 생성

주요 필드와 매핑

@ID

기본 키(PK)역할을 하는 필드

@Comlum

데이터베이스 칼럼 설정(이름, 길이, 널 허용 여부, 수정 가능 여부 등)

연관 관계 매핑

@ManyToMany

N:N 관계 설정하기 위한 애노테이션

@JoinTable

두 테이블을 중간 테이블로 연결

권한 정의

@ToString
public enum RoleEnum {
    ROLE_USER,
    ROLE_ADMIN
}

ROLE_USER, ROLE_ADMIN 두 가지 역할을 미리 enum 으로 정의

Stack.java 소스코드

package ssu.cromi.teamit.domain;

import jakarta.persistence.*;
import lombok.Data;
import java.util.HashSet;
import java.util.Set;

@Data
@Entity
@Table(name = "stack_table")
public class Stack {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "stack_tag", nullable = false, unique = true)
    private String tag;
    @Column(name = "stack_icon", length = 2083)
    private String icon;
    @ManyToMany(mappedBy = "stacks")
    private Set<User> users = new HashSet<>();

    protected Stack(){}
}

@GeneratedValue(strategy = GenerationType.IDENTITY)

이 필드가 데이터베이스에 저장될 때 JPA가 자동으로 키 값을 생성해주도록 설정 데이터베이스의 AUTO_INCREMENT(MySQL)기능에 맡겨 값이 자동으로 1씩 증가하도록 설정

Position.java

package ssu.cromi.teamit.domain;

import jakarta.persistence.*;
import lombok.Data;
import java.util.HashSet;
import java.util.Set;

@Data
@Entity
@Table(name = "position_table")
public class Position {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "position_tag", nullable = false, unique = true)
    private String tag;
    @Column(name = "position_icon", length = 2083)
    private String icon;

    @ManyToMany(mappedBy = "positions")
    private Set<User> users = new HashSet<>();

    protected Position(){}
}

SignupRequest.java

package ssu.cromi.teamit.DTO.auth;
//회원가입 DTO
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.*;
import lombok.*;
import org.hibernate.validator.constraints.Length;

@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
@ToString
public class SignupRequest {
    @JsonProperty("uid")
    @NotBlank(message = "UID 누락됨")
    private String uid;

    @JsonProperty("nickName")
    @NotBlank(message = "닉네임 누락됨")
    private String nickName;

    @JsonProperty("password")
    @ToString.Exclude // pw는 toString, Equals 제외
    @EqualsAndHashCode.Exclude
    @NotBlank(message = "PW 누락됨")
    @Length(min = 8, max=20, message = "최소길이 8, 최대길이 20")// pw 최소, 최대 길이 설정
    private String password;

    @JsonProperty("email")
    @NotBlank(message = "이메일 누락됨")
    @Email(message = "유효한 이메일 형식이 아님")
    private String email;

    @JsonProperty("emailVerified")
    private boolean emailVerified;

    @JsonProperty("birthDay")
    private Integer birthDay;
}

@JsonProperty()

JSON필드 이름과 자바 클래스의 프로퍼티를 매핑해주는 역할

728x90
반응형