ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TypeORM 개념 및 설치 및 사용방법
    Server 2020. 6. 7. 23:58

    image


    👉 Typeorm 공식문서

    ORM 개요

    Object-relational mapping, 객체-관계 매핑

    객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해준다.

    • 객체 지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용한다.
    • 객체 모델과 관계형 모델 간에 불일치가 존재한다.
    • ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결한다.


    TypeORM 개요

    express와 관계형 데이터베이스를 조합할 때 자주 사용되는 ORM으로 Sequelize가 있다.

    그리고 요즘 Typescript의 인기와 함께 떠오르는 ORM으로 TypeORM 이 있다.

    Sequelize와 TypeORM 중 어떤 ORM을 사용할지 고민을 많이 했다.

    결국은 TypeORM 을 선택했다. 그 이유는 모델의 정의를 제대로 하면 타입을 정하는 메리트를 최대한으로 얻을 수 있고, 복잡한 모델간의 관계를 형성할 수 있다는 장점이 있기 때문이다. 그리고 TypeORM 을 선호하는 글이 더 많길래 사용해봤다.😜

    TypeORM 이라는 이름으로 인해 타입스크립트 전용의 ORM같이 느껴지지만, 자바스크립트(ES5, ES6, ES7)도 지원한다.

    TypeORM을 사용하여 개발을 하면 Python의 SQLAlchemy와 같은 Data Mapper 패턴과 Rails와 같은 Active Record 패턴으로 개발할 수 있다.



    👉Active Record vs Data Mapper

    Active Record 패턴

    TypeORM에서는 Active Record 패턴과 Data Mapper 패턴 두 종류의 패턴을 사용할 수 있다.

    Active Record 패턴은 모델 그 자체에 쿼리 메소드를 정의하고, 모델의 메소드를 사용하여 객체를 저장, 제거, 불러오는 방식이다.

    아래는 공식문서의 예제 코드이며 BaseEntity라는 클래스를 사용하여 새로운 클래스에 상속하게 한 후 사용할 수 있다. 이를 통해 BaseEntity가 갖고 있는 메소드와 static으로 만들어 내는 커스텀 메소드를 이용할 수 있다.

    import {BaseEntity, Entity, PrimaryGeneratedColumn, Column} from "typeorm";
    
    @Entity()
    export class User extends BaseEntity {
    
        @PrimaryGeneratedColumn()
        id: number;
    
        @Column()
        firstName: string;
    
        @Column()
        lastName: string;
    
        @Column()
        isActive: boolean;
    
        static findByName(firstName: string, lastName: string) {
            return this.createQueryBuilder("user")
                .where("user.firstName = :firstName", { firstName })
                .andWhere("user.lastName = :lastName", { lastName })
                .getMany();
        }
    }

    아래는 공식문서에 있는 Active Record 예제코드이다.
    아래와 같이 Acitve Record 패턴은 DB 엔티티에 직접 다룰 수 있도록 new 키워드를 이용하여 새로운 인스턴스를 만들어 사용하는 것이 가능하다.

    // example how to save AR entity
    const user = new User();
    user.firstName = "Timber";
    user.lastName = "Saw";
    user.isActive = true;
    await user.save();
    
    // example how to remove AR entity
    await user.remove();
    
    // example how to load AR entities
    const users = await User.find({ skip: 2, take: 5 });
    const newUsers = await User.find({ isActive: true });
    const timber = await User.findOne({ firstName: "Timber", lastName: "Saw" });
    const timber = await User.findByName("Timber", "Saw");


    Data Mapper 패턴

    Data Mapper 패턴은 분리된 클래스에 쿼리 메소드를 정의하는 방식이며, Repository를 이용하여 객체를 저장, 제거, 불러온다.
    Active Record 패턴과의 차이점은 모델에 접근하는 방식이 아닌 Repository에서 데이터에 접근한다는 것이다.

    아래는 공식문서의 예제 코드이다. 먼저 클래스를 정의한다.

    import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
    
    @Entity()
    export class User {
    
        @PrimaryGeneratedColumn()
        id: number;
    
        @Column()
        firstName: string;
    
        @Column()
        lastName: string;
    
        @Column()
        isActive: boolean;
    
    }

    정의한 클래스를 Generic 타입을 이용하여 상속하게 한다.

    import {EntityRepository, Repository} from "typeorm";
    import {User} from "../entity/User";
    
    @EntityRepository()
    export class UserRepository extends Repository<User> {
    
        findByName(firstName: string, lastName: string) {
            return this.createQueryBuilder("user")
                .where("user.firstName = :firstName", { firstName })
                .andWhere("user.lastName = :lastName", { lastName })
                .getMany();
        }
    
    }

    그리고 getRepository()를 사용하여 만들어진 모델을 사용한다.

    const userRepository = connection.getRepository(User);
    
    // example how to save DM entity
    const user = new User();
    user.firstName = "Timber";
    user.lastName = "Saw";
    user.isActive = true;
    await userRepository.save(user);
    
    // example how to remove DM entity
    await userRepository.remove(user);
    
    // example how to load DM entities
    const users = await userRepository.find({ skip: 2, take: 5 });
    const newUsers = await userRepository.find({ isActive: true });
    const timber = await userRepository.findOne({ firstName: "Timber", lastName: "Saw" });


    Active Record vs Data Mapper

    공식문서에 의하면 두 패턴은 각각의 장점이 있다고 한다. 아래 패턴별 특징을 고민하여 개발에 적용하면 좋을 듯하다.

    • Active Record: 규모가 작은 애플리케이션에서 적합하고 간단히 사용할 수 있다.
    • Data Mapper: 규모가 큰 애플리케이션에 적합하고 유지보수하는데 효과적이다.


    TypeORM 설치

    Installation

    npm install typeorm --save
    
    npm install reflect-metadata --save
    
    // global place 의 app.ts에 import 추가하기
    import "reflect-metadata";
    
    npm install @types/node --save
    
    // Install a database driver:
    npm install mysql --save 


    Quick start

    i. typeorm 설치 및 프로젝트 생성
    npm install typeorm -g
    typeorm init --name 프로젝트이름 --database mysql

    👉 프로젝트 디렉토리 구성

    프로젝트이름
    ├── src              // place of your TypeScript code
    │   ├── entity       // place where your entities (database models) are stored
    │   │   └── User.ts  // sample entity
    │   ├── migration    // place where your migrations are stored
    │   └── index.ts     // start point of your application
    ├── .gitignore       // standard gitignore file
    ├── ormconfig.json   // ORM and database connection configuration
    ├── package.json     // node module dependencies
    ├── README.md        // simple readme file
    └── tsconfig.json    // TypeScript compiler options

    ii. install new project dependencies
    cd 프로젝트이름
    npm install

    👉 ormconfig.json

    {
       "type": "mysql",
       "host": "localhost",
       "port": 3306,
       "username": "test",
       "password": "test",
       "database": "test",
       "synchronize": true,
       "logging": false,
       "entities": [
          "src/entity/**/*.ts"
       ],
       "migrations": [
          "src/migration/**/*.ts"
       ],
       "subscribers": [
          "src/subscriber/**/*.ts"
       ]
    }

    host, username, password, database and maybe port options.


    iii. 프로젝트 시작
    npm start



    🐥 참고

    https://github.com/typeorm/typeorm/blob/master/docs/active-record-data-mapper.md

    https://typeorm.io/#/

    https://velog.io/@josworks27/typeORM-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0

    반응형
Designed by Tistory.