[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 값이 들어있고 타입 오류가 나지 않는다.