시드 스크립트를 실행한 뒤 회원가입 API를 실행했을 때 다음과 같은 에러가 발생했다.
이 에러가 발생한 이유가 너무 의아했다. 분명히 데이터베이스에는 유저 테이블과 모든 칼럼들이 제대로 들어 있는걸 확인했지만, 이 문제가 계속 발생했다.
이 문제가 발생한 원인은 데이터베이스 시드를 실행하기 위한 데이터베이스 연결 옵션과 기존의 데이터베이스 연결 옵션이 달라서 발생했던 문제였다.
기존의 데이터베이스 연결 옵션 코드는 다음과 같다.
...
import { SnakeNamingStrategy } from 'typeorm-naming-strategies';
@Module({
imports: [
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: 'postgres',
host: configService.getOrThrow('POSTGRESQL_HOST'),
port: configService.getOrThrow('POSTGRESQL_PORT'),
username: configService.getOrThrow('POSTGRESQL_USER'),
password: configService.getOrThrow('POSTGRESQL_PASSWORD'),
database: configService.getOrThrow('POSTGRESQL_DATABASE'),
entities: [__dirname + '/../**/*.entity.*'],
synchronize: configService.getOrThrow('POSTGRESQL_SYNCHRONIZE'),
logging: configService.getOrThrow('POSTGRESQL_LOGGING'),
namingStrategy: new SnakeNamingStrategy(),
}),
}),
],
})
export class DatabaseModule {}
typeorm-naming-strategies
패키지의 SnakeNamingStrategy를 적용하여 모든 테이블의 칼럼 이름을 스네이크 케이스로 자동으로 변환하게 하였다.다음은 데이터베이스 시드를 실행하기 위한 DataSource 코드이다.
import { ConfigService } from '@nestjs/config';
import { config } from 'dotenv';
import { DataSource, DataSourceOptions } from 'typeorm';
import { SeederOptions } from 'typeorm-extension';
import { BaseEntity } from 'src/global';
import { User } from 'src/users';
import { MonthlyBudgetsFactory, MainSeeder, UsersFactory, CategoryBudgetsFactory } from 'src/database';
import { MonthlyBudget } from 'src/monthly-budgets';
import { CategoryBudget } from 'src/category-budgets';
import { Category } from 'src/categories';
config({
path: '.development.env',
});
const configService = new ConfigService();
const options: DataSourceOptions & SeederOptions = {
type: 'postgres',
host: 'localhost',
port: configService.getOrThrow<number>('POSTGRESQL_PORT'),
username: configService.getOrThrow('POSTGRESQL_USER'),
password: configService.getOrThrow('POSTGRESQL_PASSWORD'),
database: configService.getOrThrow('POSTGRESQL_DATABASE'),
synchronize: configService.getOrThrow<boolean>('POSTGRESQL_SYNCHRONIZE'),
entities: [BaseEntity, User, MonthlyBudget, CategoryBudget, Category],
factories: [UsersFactory, MonthlyBudgetsFactory, CategoryBudgetsFactory],
seeds: [MainSeeder],
};
export const dataSource = new DataSource(options);
typeorm-naming-strategies
패키지의 SnakeNamingStrategy를 적용하지 않았다.처음으로 서버를 실행하면 기존의 데이터베이스 연결 옵션을 따라 모든 테이블의 칼럼 이름들은 다음과 같이 스네이크 케이스로 변환된다.
서버 실행 이후 시드 스크립트를 실행하면 synchronize
옵션에 따라 엔티티 파일에 선언한 모든 칼럼들이 카멜 케이스로 다시 바뀌어 버린다.
하지만 서버에 API를 요청하면 기존의 데이터베이스 연결 옵션에 따라 스네이크 케이스로 쿼리를 보내게 된다. 여기서 이 차이 때문에 QueryFailedError: column 엔티티.칼럼명 does not exist 에러가 계속 발생했던 것이다.
데이터베이스 시드를 실행하기 위한 DataSource의 데이터베이스 연결 옵션을 수정하였다.
synchronize
옵션 제거 및 namingStrategy
옵션 동일화import { ConfigService } from '@nestjs/config';
import { config } from 'dotenv';
import { DataSource, DataSourceOptions } from 'typeorm';
import { SeederOptions } from 'typeorm-extension';
import { BaseEntity } from 'src/global';
import { User } from 'src/users';
import { MonthlyBudgetsFactory, MainSeeder, UsersFactory, CategoryBudgetsFactory } from 'src/database';
import { MonthlyBudget } from 'src/monthly-budgets';
import { CategoryBudget } from 'src/category-budgets';
import { Category } from 'src/categories';
import { SnakeNamingStrategy } from 'typeorm-naming-strategies';
config({
path: '.development.env',
});
const configService = new ConfigService();
const options: DataSourceOptions & SeederOptions = {
type: 'postgres',
host: 'localhost',
port: configService.getOrThrow<number>('POSTGRESQL_PORT'),
username: configService.getOrThrow('POSTGRESQL_USER'),
password: configService.getOrThrow('POSTGRESQL_PASSWORD'),
database: configService.getOrThrow('POSTGRESQL_DATABASE'),
entities: [BaseEntity, User, MonthlyBudget, CategoryBudget, Category],
namingStrategy: new SnakeNamingStrategy(),
factories: [UsersFactory, MonthlyBudgetsFactory, CategoryBudgetsFactory],
seeds: [MainSeeder],
};
export const dataSource = new DataSource(options);
몇시간 삽질하면서 구글링을 통해 문제 해결 방법을 찾을 수 없었지만, 에러 메세지를 통해 문제를 해결할 수 있었다.