ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Nest.js] TypeORM, Repository Pattern
    Backend/Nest.js 2023. 10. 2. 18:59
    728x90

    TypeORM

    Type ORM은 TypeScript를 기반으로 한 ORM(Object-Relational Mapping) 라이브러리로, 데이터베이스와의 상호작용을 추상화하여 개발자가 SQL 쿼리 대신 객체 지향적인 방식으로 데이터베이스를 다룰 수 있도록 도와줍니다.

    즉, Typescript를 사용해 DB에 접근하고, DB를 다룰 수 있게 합니다.

    ORM(Object Relational Mapping) : ORM은 객체와 관계형 DB의 데이터를 자동으로 변형 및 연결하는 작업을 담당합니다. ORM을 이용하게 되면 객체와 DB의 변형을 유연하게 다룰 수 있습니다.

     

    TypeORM 주요 기능

    1. Entity, Repository

    TypeORM은 엔티티 클래스를 통해 데이터베이스 테이블과의 매핑을 정의합니다. 엔티티 클래스의 속성은 데이터베이스의 칼럼과 매핑되며, 이를 통해 데이터베이스 레코드를 객체로 다룰 수 있습니다. 또한, 리포지토리를 통해 엔티티에 대한 CRUD 작업을 수행할 수 있습니다.

    2. 마이그레이션(Migration)

    TypeORM은 데이터베이스 스키마의 변경을 관리하기 위해 마이그레이션 기능을 제공합니다. 마이그레이션은 스키마 변경 내용을 버전 관리하고, 데이터베이스의 현재 상태와 버전을 일치시키는 역할을 수행합니다. 이를 통해 팀 작업 환경에서 스키마 변경을 관리하고 배포할 때 문제를 최소화할 수 있습니다.

    3. 쿼리 빌더(Query Builder)

    TypeORM은 SQL 쿼리를 직접 작성하지 않고도, 쿼리 빌더를 사용하여 데이터베이스 쿼리를 생성할 수 있습니다. 이는 타입 안전한 방식으로 쿼리를 작성할 수 있게 해 주며, 데이터베이스 종속성을 최소화하여 코드 유지보수성을 높여줍니다

    4. 트랜잭션(Transactions)

    TypeORM은 트랜잭션을 지원하여 여러 쿼리를 하나의 트랜잭션으로 묶어 데이터 일관성을 유지할 수 있습니다. 이는 복잡한 작업을 수행할 때 중요한 기능으로, 안정적인 데이터 조작을 보장해 줍니다.

     

    Repository Design Pattern?

    비지니스 로직이 있는 Service Layer와 Data Source Layer 사이에서 중재자 역할을 하는 또다른 하나의 Layer입니다. 간단하게 말하면 비지니스 로직을 처리할 때 DB와 관련된 로직을 처리합니다.

    Service Layer에는 서비스의 핵심이 되는 로직이 존재합니다. 만약 Repository Pattern을 적용하지 않는다면, 비지니스 로직에서 데이터 베이스에 직접 접근을 하게 됩니다.

    이렇게 되면 문제점이 발생합니다.

    이 이미지는 Repository Pattern을 적용하지 않은 흐름입니다.

    클라이언트가 Data를 컨트롤러에 보내면, 클라이언트로부터 DTO 객체를 넘겨받은 컨트롤러는 DTO 객체를 서비스단으로 넘겨줍니다. 서비스는 구현된 비지니스 로직을 통해 컨트롤러에 받은 DTO 객체를 사용해서 DB에 접근하여 저장합니다. 이때 서비스에서 Data Source에 직접 접근을 하게 됩니다.

    이런 방식의 문제점은 다음과 같습니다.

    1. 비지니스 로직에만 집중하기가 어렵습니다.

    만약 서비스단에서 DB에 접근할 때 더 복잡한 로직이 필요하다면 결국 서비스는 비지니스 로직에만 온전히 집중하기 어려워집니다.

    또한 비지니스 로직을 Test 하기 어려워지고 코드 중복이 발생하여 가독성이 떨어집니다.

     

    2. 순환 참조 현상이 발생할 수 있습니다.

    만약 A라는 서비스에서 B라는 서비스의 일부를 참조하고 있고, 마찬가지로 B라는 서비스에서도 A의 일부를 참조하고 있는 경우, 순환 참조의 경우가 생길 수 있습니다.

    해결은 가능하지만, 코드의 중복과 가독성이 떨어질 수 있는 문제점이 있습니다.

     

    Repository Design Pattern의 장점?

    이 이미지는 Repository Pattern을 적용한 모습입니다.

    서비스와 DB 사이에 하나의 Layer가 더 추가되었고, Repository Layer에서만 DB Source에 접근이 가능하게 됩니다.

    @Injectable()
    export class CommentService {
      constructor(
        @InjectRepository(Comment)
        private readonly commentRepository: Repository<Comment>,
    		private readonly commentMapper: CommentMapper,
      ) {}
    
      async createComment(
        boardId: number,
        userId: string,
        createCommentDto: CreateCommentDto,
      ): Promise<Comment> {
        const convertedUserId = Number(userId);
        const user = await this.userService.findUserById(convertedUserId);
        const userNickname = user.nickname;
        const comment = this.commentMapper.DtoToEntity(
          createCommentDto,
          boardId,
          convertedUserId,
          userNickname,
        );
        return await this.commentRepository.save(comment);
      }
    }
    

    이렇게 DB작업을 Repository가 담당한 걸 확인할 수 있다.

     

    Repository Pattern의 핵심?

    서비스 단에서 데이터의 출저와 관계없이 동일한 방식으로 데이터를 접근할 수 있도록 할 수 있습니다.

    만약 하나의 어플리케이션에서 MySQL, PostgresSQL, mongoDB 등 여러 개의 DB source를 사용한다고 하겠습니다. 이때 Repository Layer가 없다면 사용해야 하는 DB의 Source가 달라져 모든 서비스의 쿼리문을 수정해야 하는 엄청난 비용이 드는 작업을 해야합니다.

    하지만 Repository Layer를 적용한다면 DB의 Source가 달라져도 서비스 Layer에서 DB를 직접적으로 접근하지 않기 때문에 쿼리를 사용하는 Respository Layer에서만 해당하는 쿼리로 수정하기만 하면 됩니다. 즉, DB의 캡슐화입니다.

     

    REF

    https://tasddc.tistory.com/124

    https://stack94.tistory.com/entry/NestJS-NestJS와-TypeORM을-활용한-데이터베이스-연동-1#4.

    728x90

    'Backend > Nest.js' 카테고리의 다른 글

    [Nest.js] Guards  (0) 2024.04.04
    [Nest.js] Test Code  (0) 2023.11.25
    Nest.js  (0) 2023.09.18
Designed by Tistory.