JS/Nest.js

[Nest] enum => 값 제한 하기

Mini_96 2024. 9. 18. 00:36
  • roles.const.ts
@@ -0,0 +1,4 @@
export enum RolesEnum{
  ADMIN = 'ADMIN',
  USER='USER',
}
  • users.entity.ts
@Column({
  enum: Object.values(RolesEnum), //객체의 값들을 가져와서 배열로 만듬
  default: RolesEnum.USER, //기본값
})
role: RolesEnum;
  • gpt

네, 이 코드는 TypeORM에서 사용되는 엔티티 클래스의 한 필드를 정의하는 부분입니다. 각 부분에 대해 자세히 설명해 드리겠습니다.

@Column({
  enum: Object.values(RolesEnum),
  default: RolesEnum.USER,
})
role: RolesEnum;

이 코드의 각 부분을 분석해보겠습니다:

  1. @Column():
    • 이는 TypeORM 데코레이터로, 이 필드가 데이터베이스 테이블의 컬럼임을 나타냅니다.
  2. enum: Object.values(RolesEnum):
    • RolesEnum은 사용자 역할을 정의하는 열거형(Enum)입니다.
    • Object.values(RolesEnum)RolesEnum모든 값들을 배열로 반환합니다.
    • 이 설정은 데이터베이스 컬럼이 이 열거형의 값들만 허용하도록 제한합니다.
  3. default: RolesEnum.USER:
    • 이 필드의 기본값을 RolesEnum.USER로 설정합니다.
    • 새로운 레코드가 생성될 때 role 값이 명시적으로 지정되지 않으면, 자동으로 RolesEnum.USER 값이 할당됩니다.
  4. role: RolesEnum:
    • 이 부분은 TypeScript 타입 선언입니다.
    • role 필드의 타입이 RolesEnum임을 명시합니다.

이 설정의 의미와 사용 사례를 시각화하는 다이어그램을 제공하겠습니다:

classDiagram
    class RolesEnum {
        <<enumeration>>
        USER
        ADMIN
        MODERATOR
    }
    class UserEntity {
        +id: number
        +name: string
        +role: RolesEnum
    }
    class Database {
        +users_table
    }
    RolesEnum --> UserEntity : used in
    UserEntity --> Database : mapped to
    note for Database "users_table\n--------------\nid | name | role\n--------------\n1 | John | USER\n2 | Jane | ADMIN"

이 설정의 장점과 사용 사례:

  1. 타입 안전성: TypeScript와 TypeORM이 협력하여 role 필드에 오직 RolesEnum에 정의된 값만 할당될 수 있도록 보장합니다.
  2. 데이터 무결성: 데이터베이스 레벨에서도 이 컬럼에는 정의된 열거형 값만 저장될 수 있습니다.
  3. 기본값 설정: 명시적으로 역할을 지정하지 않더라도, 모든 새 사용자는 기본적으로 'USER' 역할을 갖게 됩니다.
  4. 코드 가독성: 열거형을 사용함으로써 가능한 역할들을 명확히 정의하고, 코드 전체에서 일관되게 사용할 수 있습니다.
  5. 유지보수성: 새로운 역할을 추가하거나 기존 역할을 수정해야 할 때, RolesEnum만 수정하면 되므로 변경 관리가 용이합니다.

사용 예시:

enum RolesEnum {
  USER = 'user',
  ADMIN = 'admin',
  MODERATOR = 'moderator'
}

@Entity()
class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column({
    enum: Object.values(RolesEnum),
    default: RolesEnum.USER,
  })
  role: RolesEnum;
}

// 사용 예
const user = new User();
user.name = 'John Doe';
// role은 자동으로 RolesEnum.USER가 됩니다.

const admin = new User();
admin.name = 'Jane Doe';
admin.role = RolesEnum.ADMIN;

이러한 방식으로 사용자 역할을 관리하면, 타입 안전성과 데이터 무결성을 유지하면서도 역할 기반의 접근 제어를 쉽게 구현할 수 있습니다.

 

  • 실제 db에는 어떤 쿼리가 나가는가?

죄송합니다. 오해의 소지가 있었네요. enum 부분에 대해서만 자세히 설명해 드리겠습니다.

@Column({ enum: Object.values(RolesEnum), default: RolesEnum.USER }) 설정으로 인해 데이터베이스에서 실행되는 실제 쿼리는 다음과 같습니다:

  1. ENUM 타입 생성:이 쿼리는 데이터베이스에 user_role_enum이라는 새로운 ENUM 타입을 생성합니다.
  2. CREATE TYPE "user_role_enum" AS ENUM ('user', 'admin', 'moderator');
  3. 테이블 생성 시 ENUM 사용:이 쿼리에서 role 컬럼은 위에서 생성한 user_role_enum 타입을 사용하며, 기본값으로 'user'를 설정합니다.
  4. CREATE TABLE "user" ( -- 다른 컬럼들... "role" "user_role_enum" NOT NULL DEFAULT 'user' );

실제 데이터베이스에서 이 설정이 어떻게 표현되는지 시각화해보겠습니다:

erDiagram
    ENUM_TYPE {
        string user
        string admin
        string moderator
    }
    USER {
        int id
        string name
        enum role
    }
    ENUM_TYPE ||--|{ USER : constrains
    note on USER {
        role column uses 
        user_role_enum type
        with default 'user'
    }

이 다이어그램은 다음을 보여줍니다:

  1. user_role_enum이라는 ENUM 타입이 데이터베이스에 정의됩니다.
  2. USER 테이블의 role 컬럼이 이 ENUM 타입을 사용합니다.
  3. role 컬럼의 기본값은 'user'입니다.

이 설정의 주요 이점은 다음과 같습니다:

  1. 데이터 무결성: 데이터베이스 레벨에서 role 컬럼에 지정된 값들만 허용됩니다.
  2. 공간 효율성: ENUM은 문자열을 저장하는 것보다 일반적으로 더 효율적입니다.
  3. 명확성: 가능한 역할 값들이 데이터베이스 스키마에 명시적으로 정의됩니다.

실제 데이터 삽입 시 사용되는 쿼리는 다음과 같을 것입니다:

INSERT INTO "user" (name, role) VALUES ('John Doe', 'user');

이 때 'user'는 ENUM 값 중 하나이며, 다른 값('admin', 'moderator')도 사용할 수 있지만 ENUM에 정의되지 않은 값은 사용할 수 없습니다.