엘리스 AI트랙 4기/프로젝트

[TypeScript Express] Sequelize의 Getters와 Setters

남쪽마을밤송이 2022. 6. 18. 21:37

 [01 들어가기에 앞서 ] 

  • 먼저 상황은 이렇다. 체크리스트의 true 개수를 계산해 그 날의  level 을 1, 2, 3단계로 나누어 저장한다. 각각의 단계는 초록색, 노란색, 빨간색을 뜻한다.
  • 따라서 DB에는  int  Datatype으로 저장하고 가져올 때는 green, yellow, red로  convert 해서 응답을 보내주는 과정이 필요했다.
  • 구현을 위해 처음에는 다음과 같이 응답값을 변경하려고 했지만, TypeScript 특성상 다른 Datatype을 할당할 수 없었고 모델의 attributes에 없는 컬럼을 추가할수도 없었다. 따라서 응답값을 복사해 새로 객체를 만들고 key: value를 추가해야만 했다.
getWeeklyChecklist: async (fk_user_id: string, { start, finish }: IChecklistWeeklyInput) => {
    const weeklyChecklist = await Checklist.findByWeek(fk_user_id, { start, finish });
    const checklistColors: any = [...weeklyChecklist];

    enum colorType {
      GREEN = "green",
      YELLOW = "yellow",
      RED = "red",
    }
    interface dataValues {
      level: number;
      color: colorType;
    }
    checklistColors.forEach((element: { dataValues: dataValues }) => {
      if (element.dataValues.level == 1) {
        element.dataValues.color = colorType.GREEN;
      } else if (element.dataValues.level == 2) {
        element.dataValues.color = colorType.YELLOW;
      } else {
        element.dataValues.color = colorType.RED;
      }
    });

    return checklistColors;
  },
  • 이러한 방법은 convert라고 하기도 애매하고 비효율적이라 다른 방법을 찾아보게 되었다.

  • Sequelize에는 데이터 모델을 생성할 때 "데이터 조회시 후처리",  "데이터 입력시 전처리"를 할 수 있는  Getters 와   Setters  기능이 제공된다.
  • 이중 Getters에 해당하는  get( )  함수를 이용하면 1, 2, 3이라고 DB에 저장해도 조회시에는 green, yellow, red로 불러올 수 있는 것이다!
  • 자세한 개념은 공식문서를 참고하자.
 

 [02 Getters와 Setters ] 

  • 둘 다 모델 생성시에 정의해준다.

 (1) Getters - get( ) 

  • 공식문서에 나온 예제에 따르면  get( ) 은 다음과 같이 사용한다.
  • DataBase에서 조회한 값을 return하기 전 원하는 형태로 변경하고 싶을 때 사용한다.
const User = sequelize.define('user', {
  // Let's say we wanted to see every username in uppercase, even
  // though they are not necessarily uppercase in the database itself
  username: {
    type: DataTypes.STRING,
    get() {
      const rawValue = this.getDataValue('username');
      return rawValue ? rawValue.toUpperCase() : null;
    }
  }
});

 (2) Setters - set( ) 

  • 공식문서에 나온 예제에 따르면  set( ) 은 다음과 같이 사용한다.
  • DataBase에 넣기 전 Datetype을 변경해야 하거나 데이터 전처리가 필요할 때 사용한다.
const User = sequelize.define('user', {
  username: DataTypes.STRING,
  password: {
    type: DataTypes.STRING,
    set(value) {
      // Storing passwords in plaintext in the database is terrible.
      // Hashing the value with an appropriate cryptographic hash function is better.
      this.setDataValue('password', hash(value));
    }
  }
});

 

 [03 코드 적용 ] 

  • get( )을 사용해서 처음의 코드를 수정한 부분은 다음과 같다.

 (1) checklistInput.ts 

export enum colorType {
  ONE = "green",
  TWO = "yellow",
  THREE = "red",
}
  • 이 부분은 유지보수와 확장성을 고려해 따로 interface를 분리해 만들어주었다.

 (2) checklist.ts 

import { DataTypes, Model } from "sequelize";
import { sequelize } from "./index";
import { colorType } from "../../interfaces/checklistInput";

...

Checklists.init(
  {
    pk_checklist_id: {
      type: DataTypes.INTEGER,
      autoIncrement: true,
      primaryKey: true,
    },
    date: {
      type: DataTypes.DATEONLY,
      allowNull: false,
    },
    level: {
      type: DataTypes.INTEGER,
      allowNull: true,
      // 데이터 조회시 후처리
      get() {
        const color = this.getDataValue("level");
        if (color == 1) {
          return colorType.ONE;
        } else if (color == 2) {
          return colorType.TWO;
        } else {
          return colorType.THREE;
        }
      },
    },
    one: {
      type: DataTypes.BOOLEAN,
      allowNull: true,
      defaultValue: false,
    },
    
 ...

 (3) checklistService.ts 

import { Checklist } from "../db/Checklist";
import { IChecklistCreateType, IChecklistWeeklyInput } from "../interfaces/checklistInput";

const ChecklistService = {
  getWeeklyChecklist: async (fk_user_id: string, { start, finish }: IChecklistWeeklyInput) => {
    const weeklyChecklist = await Checklist.findByWeek(fk_user_id, { start, finish });
    return weeklyChecklist;
  },
};

export { ChecklistService };
  • Checklist 파일에 정의되어 있는 findByWeek 메소드로 가져온 응답값을 바로 return 해도  int  Datatype인  level  컬럼에  string  Datatype인 green, yellow, red 값이 들어있고 타입 오류가 나지 않는다.