* Repository ?
이전 : service에서 memory repository 사용
개선 : db 관련일은 repository 에서 처리함
1. 리포지토리 클래스 생성
import { EntityRepository, Repository } from "typeorm";
import { Board } from "./board.entity";
@EntityRepository(Board) //Board를 컨트롤하는 db임을 선언
export class BoardRepository extends Repository<Board>{
}
2. 보드 모듈에 임포트 => 여러곳에서 사용
import { Module } from '@nestjs/common';
import { BoardsController } from './boards.controller';
import { BoardsService } from './boards.service';
import { TypeOrmModule } from "@nestjs/typeorm";
import { BoardRepository } from "./board.repository";
@Module({
imports: [
TypeOrmModule.forFeature([BoardRepository])
],
controllers: [BoardsController],
providers: [BoardsService]
})
export class BoardsModule {}
* @EntityRepository issue
결론 : 아래와같이 모델(설계도)에서 db에 직접접근함수를 만들어서 사용하라! (Active Record)
-> 잘안되서 typeorm 2.0으로 down grade && EntityRepository 사용함.
// User Entity
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number
@Column()
email: string
@Column()
password: string
@Column()
name: string
static async findOneByEmail(email: string): Promise<User> {
return this.findOne({ email })
}
}
// User Service
const user = await User.findOneByEmail(email)
https://imsoncod.tistory.com/40
@EntityRepository 가 사라진 이유
TypeORM 을 사용하는 대다수의 개발자들이 Service Layer 에는 비즈니스 로직만을 작성하고 Repository Layer 에는 쿼리 로직을 작성한다 (Data Mapper 패턴을 추구한다) 아마 단일 책임 원칙을 지키기 위해 or 단순히 파일간 역할을 분리해 코드를 작성하면 직관적이니깐 그러는 것 같다.
그러다보니... 아래와 같이 메소드를 불필요하게 생성해 사용하는 케이스가 생기기 시작했다.
// User Repository
@EntityRepository(User)
class UserRepository extends Repository<User> {
async getAllUsers() {
return this.find()
}
}
모든 User 를 조회하는 로직을 작성하는데, TypeORM 에서 표준으로 지원하는 find() 메소드가 있음에도 불구하고 동일한 역할을 하는 getAllUsers() 라는 메소드를 Repository 클래스 내부에 생성했다. 추상화 레벨이 올라가기는 하겠다만, 꼭 Repository Layer 에 이렇게 생성해야하는지는.. 잘 모르겠다 + 메소드명이 치환되어 코드 가독성이 더 올라간다? 흠.. 이것도 잘 모르겠다.
위와 관련하여 여러 개발자들이 엄격한 Data Mapper 패턴의 사용이 좋지 않다는 목소리를 냈고, 이에 TypeORM 관리팀은 @EntityRepository 데코레이터를 Deprecated 하며 Active Record 패턴을 권장하는 듯한 뉘앙스를 풍기는 메시지를 남겼다.
Active Record vs Data Mapper
두 패턴 모두 어플리케이션 서버의 코드 레벨에서 데이터베이스와 통신하는 방법에 대해 정의하고 있다. TypeORM 에서 각 패턴의 구현 방식과 특징을 살펴보자.
Active Record 패턴
Active Record 패턴은 모델 내에서 데이터베이스에 직접 접근하는 방식이다. 말이 어려우니 바로 코드 레벨로 들어가보자.
// User Entity
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number
@Column()
email: string
@Column()
password: string
@Column()
name: string
static async findOneByEmail(email: string): Promise<User> {
return this.findOne({ email })
}
}
// User Service
const user = await User.findOneByEmail(email)
TypeORM 에서 Active Record 패턴은 위처럼 구현할 수 있으며, 특징은 아래와 같다.
- Entity 클래스를 통해 데이터베이스에 직접 접근한다.
- BaseEntity 클래스를 상속 받아 TypeORM 에서 지원하는 표준 쿼리메소드를 사용할 수 있다.
- Custom 쿼리메소드를 Entity 클래스 내에 static 하게 정의한다.
추가적인 Layer 가 생기지 않아 단순하고 빠르게 코드를 작성할 수 있으며, 유지보수 난이도가 낮다는 장점이 있다. 반면에, 쿼리메소드와 비례하여 Entity 사이즈가 커질 수 있다는 단점도 있다.
* 잘안됨
강의를 듣던 도중 repository 에러로 반나절을 날려먹었다.
삽질의 연속이었다.
버전을 낮춰보기도 하고 강의의 소스코드를 비교해서 틀린그림찾기도 엄청 했었다.
하지만 해결하지 못했었다. 찾던 도중 nestjs doc의 database Typeorm 편을 찾게 되었다.
역시 doc부터 먼저 찾아 봐야한다는것을 다시 상기시키게 되었다.
우선 나의 에러는 아래와 같았다.
RepositoryNotFoundError: No repository for "BoardRepository" was found. Looks like this entity is not registered in current "default" connection?
at RepositoryNotFoundError.TypeORMError [as constructor] (/Users/wonjun/develop/workspace/nestjs-test/src/error/TypeORMError.ts:7:9)
at new RepositoryNotFoundError (/Users/wonjun/develop/workspace/nestjs-test/src/error/RepositoryNotFoundError.ts:10:9)
at EntityManager.getRepository (/Users/wonjun/develop/workspace/nestjs-test/src/entity-manager/EntityManager.ts:964:19)
at Connection.getRepository (/Users/wonjun/develop/workspace/nestjs-test/src/connection/Connection.ts:354:29)
at InstanceWrapper.useFactory [as metatype] (/Users/wonjun/develop/workspace/nestjs-test/node_modules/@nestjs/typeorm/dist/typeorm.providers.js:16:34)
at Injector.instantiateClass (/Users/wonjun/develop/workspace/nestjs-test/node_modules/@nestjs/core/injector/injector.js:343:55)
at callback (/Users/wonjun/develop/workspace/nestjs-test/node_modules/@nestjs/core/injector/injector.js:53:45)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Injector.resolveConstructorParams (/Users/wonjun/develop/workspace/nestjs-test/node_modules/@nestjs/core/injector/injector.js:132:24)
at Injector.loadInstance (/Users/wonjun/develop/workspace/nestjs-test/node_modules/@nestjs/core/injector/injector.js:57:13)
열받았다.
해결방법은 아래와 같다.
boards.module.ts
import 부분의 forfeature 안에를 BoardRepository가 아닌 Board(Entity)로 변경해주고
boards.service.ts
@InjectRepository 어노테이션을 BoardRepository에서 Board로 변경해주면 되는 것이었다....
Doc을 보면 너무나도 쉽게 해결할 수 있던 것을 반나절을 삽질했다. 이 해결방법이 많은 사람들에게 도움이 되길 기도하며...
남은 강의 더 들으러 간다...
- 유튭 댓글
'JS > Nest.js' 카테고리의 다른 글
[Nest JS] 게시글생성 db / typeOrm 3.0 issued 해결 / @EntityRepository 해결 (0) | 2024.08.17 |
---|---|
[Nest JS] memory repository 2 DB repository / 게시글 조회 / (0) | 2024.08.17 |
[Nest JS] Postgres SQL 설치, type ORM, 엔티티(테이블) 생성 (0) | 2024.08.17 |
[Nest JS] 커스텀 파이프 구현 => 유효성 체크 (0) | 2024.08.17 |
[Nest JS] 없는 게시물 지울때 예외처리 (0) | 2024.08.17 |