본문 바로가기
Javascript

Prisma의 단점 - Timezone, 다른ORM은?

by for2gles 2021. 7. 23.
반응형

Prisma 를 사용하다보면 모든사람이 느끼고있는 고통이 하나가 있다.

 

바로 DateTime 이다.

 

이게 왜 문제가 되냐하면 문제는 이러하다.

 

prisma.member.create({
	data:{
    	mem_name: '이름',
        mem_wdate: new Date()
    }
})

mem_wdate 칼럼이 DateTime 으로 설정되어있다고 한다면, 위와같이 row를 생성해줄 수 있다.

 

문제는 생성된 Row가 문제다.

데이터베이스에 저장이 될 때 UTC기준으로 저장이된다.

 

분명 DB에 등록한시간이 2021년 7월 23일 오후 7시 0분이기 때문에 2021-07-23 17:00:00 을 기대했지만, 정작 데이터베이스에는 2021-07-23 08:00:00 이 저장되어있다.

 

그 이유는 Prisma에서는 Timezone의 옵션이 존재하지 않는다.

 

그래서 어떻게 사용하느냐

 

https://github.com/prisma/prisma/issues/5051

나는 해당 Issue를 매일마다 확인하며 진행사항을 확인했었다. 이곳에서 질문자(한국인이더라구요)가 획기적인 방법을 알려주었는데 바로 Prisma Middleware를 사용하는것이다.

 

date.middleware.ts

import { Request, Response, NextFunction } from 'express';
import { Prisma } from '@prisma/client';
import _ from 'lodash';

export async function DateMiddleware<T = any>(
    params: Prisma.MiddlewareParams,
    next: (params: Prisma.MiddlewareParams) => Promise<T>,
) {
    check_date(params.args);
    const result = await next(params);
    return_date(result);
    return result;
}

function check_date(obj: any): void {
    _.forEach(obj, (value, key) => {
        if (value instanceof Date) {
            const thisHour = value.getHours();
            value.setHours(thisHour + 9);
            return;
        }
        if (typeof value === 'object') return check_date(value);
        return;
    });
    return;
}

function return_date(obj: any): void {
    _.forEach(obj, (value, key) => {
        if (value instanceof Date) {
            const thisHour = value.getHours();
            value.setHours(thisHour - 9);
            return;
        }
        if (typeof value === 'object') return return_date(value);
        return;
    });
    return;
}

이렇게 하여 데이터베이스에 등록하기 직전에 9시간을 인위적으로 추가해주고, 값을 가져올때에는 -9시간을 진행해준다.

이게 뭐하는짓인가 싶지만 방법이 없다.

 

Github Issue를 보면 알겠지만

Prisma 관리자들은 해당 부분에대해 별 생각이 없다.

"미들웨어 돼? 그럼 그렇게 쓰면 되잖아 되잖아" 혹은 "어차피 데이터베이스에 UTC기준으로 저장되지만, 오류가 발생하는게 아니잖아? 그냥 써" 이런 느낌이다.

 

이게 정말 너무 불편하다.

최근 이런일이 있었다. 하나의 시간을 가지고 여러 데이터베이스에 넣어야하는 일이 있었다.

그래서

const thisDate = new Date();
const create1 = prisma.something1.create({
	data:{
    	something: 'something',
        wdate: thisDate,
    }
})
const create2 = prisma.something2.create({
	data:{
    	something: 'something',
        wdate: thisDate,
    }
})
const create3 = prisma.something3.create({
	data:{
    	something: 'something',
        wdate: thisDate,
    }
})

await prisma.$transaction([create1,create2,create3]);

이런 transaction 을 제작할 일이 있었다.

하지만 정작 wdate가 작동될 때 마다 9시간씩 더해지는 바람에

something1 에는 현재시간

something2 에는 현재시간+9시간

something3 에는 현재시간+18시간

과 같은 값이 들어갔다.

 

하...

결국에 해결 한 방법은


const create1 = prisma.something1.create({
	data:{
    	something: 'something',
        wdate: new Date(),
    }
})
const create2 = prisma.something2.create({
	data:{
    	something: 'something',
        wdate: new Date(),
    }
})
const create3 = prisma.something3.create({
	data:{
    	something: 'something',
        wdate: new Date(),
    }
})

await prisma.$transaction([create1,create2,create3]);

결국 개별적인 Date를 구성해줌으로서 해결을 했다.

 

하지만 경쟁 ORM인 TypeORM은 이렇게 timezone을 설정할 수 있다.

 

ormconfig.json

# https://typeorm.io/#/using-ormconfig
    [
        {
            "name": "default",
            "type": "mariadb",
            "host": "localhost",
            "port": 3306,
            "username": "root",
            "password": "1234",
            "database": "database",
            "timezone": "+09:00",
            "schema": "",
            "synchronize": false,
            "entities": ["src/entities/*{.ts, .js}"]
        }
    ]

 

끝.

 

반응형

댓글