문제 상황
[Nest] 2657 - 11/30/2022, 8:07:31 PM ERROR [ExceptionHandler] Nest can't resolve dependencies of the UserEntityRepository (?). Please make sure that the argument DataSource at index [0] is available in the TypeOrmModule context.
Potential solutions:
- If DataSource is a provider, is it part of the current TypeOrmModule?
- If DataSource is exported from a separate @Module, is that module imported within TypeOrmModule?
@Module({
imports: [ /* the Module containing DataSource */ ]
})
entity 테이블 만들고, app.module과 user.module, user.service에 import, injection을 다 세팅해주었는데 자꾸 에러가 발생했다.
공식문서 코드와 비교해봐도 해결책을 찾을 수 없었다.
문제 코드
app.module.ts
@Module({
imports: [
TypeOrmModule.forRoot({
name: 'databaseA',
type: 'postgres',
host: '127.0.0.1',
port: 5432,
username: 'wintinue',
password: '',
...
user.module.ts
@Module({
imports: [TypeOrmModule.forFeature([UserRegistrationEntity])],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
user.service.ts
@Injectable()
export class UserService {
constructor(
@InjectRepository(UserEntity)
private readonly usernRepository: Repository<UserEntity>,
) {}
해결 과정
에러 메시지가 고유명사만 달라지고 항상 같은 형태로 나와서 계속 검색을 해보니 결국은 제대로 의존성 주입을 하지 않았거나 뭘 빼먹었던 등의 문제가 원인이었다.
뭘 빼먹었는지는 모르겠지만 계속 찾아봤고, orm을 import하거나 inject할 때, 두번째 인자로 dataSource를 넣어줄 수 있다는 것을 발견했다. 혹시나 싶어서 Root name으로 설정했던 databaseA를 기재해주었다.
typeorm을 처음 써보다 보니 이런 기초적인 부분이 원인으로 에러가 난 것이다.
문제 원인
TypeOrmModel.forRoot()로 app.module에 orm을 초기화해줄 때, option으로 name을 넣어줬을 경우에는, 해당 이름을 import하거나 inject할 때 함께 dataSource로 명시해주어야 한다. 특정 데이터베이스의 테이블 또는 컬럼으로 매핑해주고 이 구분을 name으로 하기 때문이다.
해결 방법
- name을 모두 명시하는 방법
user.module과 user.service에 데이터베이스 이름을 명시해주었다.
user.module.ts
@Injectable()
export class UserService {
constructor(
@InjectRepository(UserEntity, 'databaseA')
private readonly usernRepository: Repository<UserEntity>,
) {}
user.service.ts
@Module({
imports: [TypeOrmModule.forFeature([UserRegistrationEntity], 'databaseA')],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
- name 명시 안 하는 방법
혹은 굳이 이름을 달아줄 필요가 없다면 아예 안 쓰는 것도 방법이다.
app.module.ts
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: '127.0.0.1',
port: 5432,
username: 'wintinue',
password: '',
...
user.module.ts
@Module({
imports: [TypeOrmModule.forFeature([UserRegistrationEntity])],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
user.service.ts
@Injectable()
export class UserService {
constructor(
@InjectRepository(UserEntity)
private readonly usernRepository: Repository<UserEntity>,
) {}
피드백
해결하고 다른 작업을 하면서 복기해보니, 당시에 공식문서와 비교해보며 코드에 다른 점이 없다고 생각했었지만, 결국 name: ‘databaseA’ 부분이 달랐단 것을 깨달았다. 뭔가를 대조해볼 땐 토씨 하나도 놓치지 말고 비교해야겠다. 어차피 몇 시간동안 에러 붙잡고 있게 되면 눈으로 확인할 때 빠트릴 수 있으니, 복붙으로 확인하는게 나을 것 같다.