저장을 습관화

에러 기록 - DB에 createdAt이 9시간 전으로 저장되는 현상 본문

공부/node.js

에러 기록 - DB에 createdAt이 9시간 전으로 저장되는 현상

ctrs 2023. 11. 18. 18:19

- 증상

NestJS + TypeORM + Socket.io로 사용자 간의 채팅 기능 작성 중

 

서로의 채팅 입력 시간이 9시간 전으로 표시되는 문제 발생

 

/src/channel.service.ts (입력 내용을 DB에 먼저 저장하고, socket.io를 이용하여 같은 채널 사람들에게 전송함)

// ...
// 채팅 작성 
  async postChat({ url, name, content, myId }) {
    // 채널 조회
    const channel = await this.channelsRepository
      .createQueryBuilder('channel') // 'alias'
      .innerJoin('channel.Workspace', 'workspace', 'workspace.url = :url', {
        url: url,
      }) // 'property', 'alias', 'condition', 'parameters'
      .where('channel.name = :name', { name: name }) // 'where', 'parameters
      .getOne();
    if (!channel) {
      throw new NotFoundException('채널이 존재하지 않습니다.');
    }

    const chats = new ChannelChats();
    chats.content = content;
    chats.UserId = myId;
    chats.ChannelId = channel.id;
    const savedChat = await this.channelChatsRepository.save(chats);
    const chatWithUser = await this.channelChatsRepository.findOne({
      where: { id: savedChat.id },
      relations: ['User', 'Channel'],
    });
    // socket.io로 워크스페이스/채널 사용자에게 전송
    this.eventsGateway.server
      .to(`/ws-${url}-${channel.id}`)
      // `워크스페이스-워크스페이스 이름-채널ID`
      .emit('message', chatWithUser);
  }
// ...

 

 

/src/entities/ChannelChats.ts

@CreateDataColumn() 데코레이터와 기본 옵션 Date 사용 중

// ...

// ...
export class ChannelChats {
  // ...

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;

  // ...
}

 

이러한 환경에서

DB에 createdAt이 9시간 전으로 저장되고 있는 중

 

 

DB는 AWS RDS를 이용 MySQL를 사용중임

지역은 ap-northeast-2a(아시아 태평양, 서울)

 

 

- 원인

백엔드(NestJS) 서버와 DB 서버 각각의 타임존이 잘못되어있는 것이라고 생각됨..

 

 

- 해결을 위한 시도

NestJS 실행 중인 서버의 시간과 타임존

// 2023년 11월 18일 오후 4시 34분 기준

console.log(new Date());
// 2023-11-18T07:34:51.817Z

console.log(Date());
// Sat Nov 18 2023 16:34:51 GMT+0900 (대한민국 표준시)

console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);
// Asia/Seoul

 

 

DB의 타임존

 

 

'DB는 NestJS가 TypeORM 이용해서 전송하는 데이터를 저장만 할테니, 

DB의 타임존이나 시간 설정은 불필요하지 않을까?'라고 생각함

 

검색해보니 옵션을 넣어주는 것으로 NestJS의 타임존을 설정할 수 있다는 내용을 발견

app.module.ts에 아래와 같이 timzone 옵션을 넣어줌

TypeOrmModule.forRoot({
timezone: 'Asia/Seoul',
}),

 

 

이후 브라우저에서는 서로의 채팅 입력 시간이 정상적으로 확인되나

 

 

DB에서는 여전히 9시간 전으로 저장되는것을 확인

 

 

AWS RDS의 타임존을 Asia/Seoul로 변경함

그에 대한 기록

https://ctrs.tistory.com/471

 

AWS RDS MySQL DB Timezone 변경

AWS RDS를 이용하여 생성한 MySQL DB의 기본 타임존은 UTC로, `select now()`를 입력해서 시간을 확인하였을때 실제 현지 시간보다 9시간 느림 이것을 수정하기 위하여 타임존을 변경하는 방법에 대한 메

ctrs.tistory.com

 

 

DB 타임존 변경 이후 다시 채팅 테스트를 진행하였고

DB에는 제대로 된 시간이 저장되었으나

 

 

브라우저에서는 서로 상대방의 채팅 내역이 9시간 빠르게 표시되는 것을 확인함..

 

 

 

다시 app.module.ts의 TypeOrmModule의 timezone 옵션을 제거하고 NestJS를 재실행

TypeOrmModule.forRoot({
// timezone: 'Asia/Seoul',
}),

 

 

브라우저와 DB 모두 정상적으로 시간이 나오는 것을 확인함