관리 메뉴

공부 기록장 💻

[Database Modeling] 채용 사이트 데이터 모델링 수정, Converting database to TypeORM Entities (Reverse Engineering Tool, typeorm-model-generator) 본문

# CS Study/Database

[Database Modeling] 채용 사이트 데이터 모델링 수정, Converting database to TypeORM Entities (Reverse Engineering Tool, typeorm-model-generator)

dream_for 2022. 11. 11. 00:27


이전에 원티드 채용 플랫폼을 분석해보면서, 채용 사이트의 Database 모델링을 위한 준비 단계를 거쳐보았다. (https://dream-and-develop.tistory.com/263)
본격적으로 DB 모델링을 시작하기 전, 이전에 설계했던 모델링의 결함을 고쳐 수정해 보고,
이전부터 써보고 싶었던 typeorm-model-generator이라는 reverse engineer 도구를 사용해보고자 한다.

결함이 있었던 요구사항 분석 과정


이전에 채용 사이트의 간단한 API를 만드는 과제를 진행하였다.
데이터베이스 스키마를 설계한 후, NestJS 프레임워크에서 Entities 생성 후, TypeORM을 이용해 MySQL 데이터베이스에 객체 매핑을 진행하였다.
사용자가 채용 공고에 지원하는 API를 설계하는 부분이 있었는데, 이 요구사항을 잘못 해석하여 분석을 했음을 나중에 깨달았고, 이를 보완해 보고자 한다.

 


잘못 분석한 부분은, 사용자가 1회만 지원 가능하다는 요구 사항을
어떠한 채용 공고에 1회 지원이 가능다고 해석한 것이 아니라,
사용자가 이 채용 사이트에서 딱 한 번 뿐의 지원 기회가 있다는 것으로 분석을 해버린 것이다.
결국 유저 테이블에 is_applied 라는 boolean 칼럼을 포함시켜, 지원을 한번 한 경우 false였던 값일 true로 변경시켜
더 이상 어떠한 공고에도 지원이 불가능하도록 API를 설계한 것이 큰 실수였다.

 

요구 사항 분석 오류로 인해 적절하지 않은 DB 스키마가 설계된 결과..


기존의 typescript 코드는 다음과 같다.

우선 controller 코드는 다음과 같다.
사용자가 recruitId 번 공고에 지원하기를 누르게 되면, :recruitid/apply 로 POST 전송이 요청된다.

// 해당 공고에 지원하기
  @Post(':recruitId/apply')
  @UseGuards(UserAuthGuard)
  apply(
    @Param('recruitId') recruitId: number,
    @GetUser() user: Users,
  ): Promise<Application> {
    return this.recruitService.apply(recruitId, user);
  }
}


service 로직은 다음과 같았다.
recruitId와 user의 정보를 받아, user의 isApplied 값이 true인 경우에는 더 이상 지원 불가하다는 메세지와 함께 BadRequestException 이 던져지고, 지원 자체가 불가능한 상황이 된다.
아직 isApplied 값이 false인 경우라면, 유저의 isApplied 값을 true로 변경하는 repository update문이 실행된 후에 user과 recruit 정보를 담는 application 객체를 생성하게 된다.

 

  // 채용 공고 지원
  async apply(
    recruitId: number,
    userApplied: Users,
  ): Promise<Application | undefined> {
    console.log(recruitId, userApplied);

    if (userApplied.isApplied == true) {
      throw new BadRequestException('더이상 지원 불가합니다.');
    }
    const recruitApplied = await this.recruitRepository.findOne({
      where: { id: recruitId },
    });
    if (!recruitApplied) {
      throw new NotFoundException(`${recruitId} 번 공고를 찾을 수 없습니다.`);
    }

    this.userRepository.update(userApplied.id, {
      isApplied: true,
    });

    return await this.applyRepository.save({
      user: userApplied,
      recruit: recruitApplied,
    });
  }

 

 


기존의 Application 데이터 모델링 수정


결국 전체 DB 스키마를 수정하였다. 도출한 ER 다이어그램은 다음과 같다.
기존에 각각 독립적인 auth 역할을 하던 users와 company 는 users 도메인으로 통일하였다,
채용 담당자의 경우, is_recruiter 값을 통해 해당 유저가 어떠한 기업의 채용 담당자로 활동하고 있는 유저인지 표현하고자 했다.
recruiters 모델을 추가함으로써, 회사에서도 채용 담당자로 활동하고 있는 유저를 관리할 수 있게끔 확장한 것이다.

그리고 채용 공고 모델인 recruitment의 경우에도, 회사 와 연결될 뿐 아니라 해당 공고를 작성한 recruiters 모델과도 연결되어 있다. Company라는 객체를 유저의 역할과 분리함으로써, Company는 회사의 정보를 표현하는 모델로만 남겨두고, 지원자들을 관리하거나 채용 공고들을 관리하는 역할의 책임은 recruiters 모델에게 위임을 하도록 변경한 바이다.

(객체 지향 디자인 패턴을 학습해야 이에 대한 원리를 더 잘 파악할 수 있지 않을까 싶다.)



 


 

Converting Database to TypeORM Entities


이전에는 전체적인 데이터베이스 스키마를 설계하고, NestJS 프레임워크 내에서 Entities를 설계하여 TypeORM을 이용해 Database로 converting하는 방향이었다면,
이번에는 MySQL Database에서 모델링한 값을 TypeORM으로 역 매핑하는 Reverse Engineering 과정을 거쳐보자.

적절한 도구를 찾아보니, typeorm 공식 github 문서 Issues 부분에 누군가 이에 대해 처음으로 언급한 적이 있었다.
( https://github.com/typeorm/typeorm/issues/540 )

 

2017년 어떤 사용자가 database에서 typeorm entities로 전환하는 reverse engineering 도구의 개발 계획을 물어본 적이 있다. 실제 도구로 사용하기보다는 장난감처럼 사용할 수 있겠다는 결론이 답으로 도출이 되어서 아쉽다고 생각했는데...

 

 

 

아래를 좀 더 살펴보니, 다른 유저가 3달 뒤 typeorm-model-generator 를 소개하였고,
꽤나 강력한 도구라는 답변 또한 달려서 이 도구를 사용해서 db 상에서 설계한 모델을 entities로 변환해보는 작업을 진행해보기로 하였다.

 

 

 


 

Reverse Engineer 도구인 typeorm-model-generator

( https://github.com/Kononnable/typeorm-model-generator )

typeorm-model-generator 도구를 사용해보자.
(큰 제목으로, 현재 이 프로젝트는 유지 보수 단계에 있다고 쓰여져 있다. 이에 대한 세부사항은 아래에 작성해보았다.)

Postgres, Mysql, mariadb 등의 db engine들을 지원한다고 한다.

 

 


위에 작성되어 있는 설치 방법대로 npm i typeorm-model-generator@no-engines 명령어로, 해당 모듈을 설치해주었다.
아래 npx 명령어를 통해 lolcalhost, database name, port number, username, password, db engine을 차례대로 써주면
원하는 데이터베이스의 전체 모델들이 entities로 생성된다.

 


아래와 같이 recruit_site라는 데이터베이스 내에 설계한 모델들이 entities로 변경된 것을 확인할 수 있다.
(jobcategory, position, tag 와 같은 모델들은 아직 연결을 하지 않은 상태..!)

 

 

생성된 Entities 

 


각 모델을 쭉 살펴 보며, 각 테이블과의 연관 관계가 잘 설정되었는지, 컬럼의 제약 사항들도 잘 생성이 되었는지 확인해보자.

 

Users 모델


unique로 설정한 email 칼럼이 인덱스가 생성된 것,
primary key로 설정한 id 값에 primary 값이 true로 설정되어 있는 것,
is_recruiter 칼럼 (기존 snake_case로 작성한 것이 entities로 변경 후 자동적으로 camelCase로 변경된 것까지 확인 가능) 의 default 값이 0인 것 (false),
그리고 applications 모델과 one-to-many relation,
reecruiters 모델과 one-to-many relation (user와 recruiter은 one-to-one 관계로 설정되어야 하는게 맞다.. 이건 릴레이션 관계 수정이 필요할 것 같다),
resumes 모델과 one-to-many relation까지 잘 설정이 되어 있음을 확인하였다.

 

 

Company 모델

 

Recruiters 모델


Recruitment 모델


Resumes 모델


Application 모델


Reverse되어 도출된 Entities 모델이 생각보다 정교함을 알아차릴 수 있었다.
기존에 내가 직접 프레임워크 내에서 설계한 것보다, 훨씬 더 제약 사항과 설정들을 정확하게 적용된 것을 보고 많이 놀라웠다.


이번에는 아까 유지 보수 단계라고 명시하면서, #329 Issue 부분의 상세 사항을 살펴보기로 하자.

 


현재 TypeORM은 유지 보수 단계라고 한다.
2021년 초 기준 마지막으로 작성된 이슈는 다음과 같다.

typeorm-model-generator에 더이상 다른 기능들이 추가될 계획은 없다고 한다.
PR의 사소한 작은 기능들은 추가될지 몰라도, 복잡한 기능들은 아마 거절될 것이라고 한다.
덧붙여 typeorm-model-generator은 꽤나 좋은 상태에 있으며, 몇 개의 버그가 존재하긴 하지만, 대부분은 잘 작동한다고 한다. 기본적인 기능들은 모두 포함되어 있고, 더 원하는 기능들이 있으면 본인이 알아서 추가해서 사용하면 된다고 한다.

그런데 여기서 typeorm은 앞으로 진행될 새로운 프로젝트에서 고려되지 않을 것이라 한다.
Typeorm은 ORM으로서 적절한고 best practice를 보여주는 도구는 아니라는 뜻 같다.
새로운 누군가가 ORM을 사용하려고 한다면, 많은 ORM 중 Typeorm을 선택하기 전에는 조금 더 신중히 고민해보라고 쓰여 있다.

 


그리고 많은 유저들은 TypeORM이 아닌 prisma나 sequelize 등 다른 ORM 도구들을 추천해주었다.

 

 

TypeORM이 추천할만한 ORM이아니라니..


며칠 전에는, QueryBuilder이라는 도구를 사용해보면서 ORM 이라는 도구만을 의존해서는 안 된 다는 것을 깨달으며
SQL query 문을 직접 작성할 수 있어야 한다는 것을 배웠고, ((https://dream-and-develop.tistory.com/270))
이번 기회를 통해서는 TypeORM이라는 도구보다는 다른 sequelize, prisma 등의 ORM을 사용해야 함을 깨달으면서
어떠한 프레임워크와 개발 도구에 의존하기 보다, 내부 동작의 원리를 잘 이해하고 파악해야 하면서, 개발의 본질을 잃지 않아야 함을 느꼈다.
TypeORM이 왜 ORM으로써 적절한 도구가 아닌지는 추후에 더 조사해 보고자 한다.


최근 우테코 프리코스 과정에서도 프레임워크에 너무 의존하게 되면 본질적인 프로그래밍 실력, 설계 역량을 기르는데 방해가 될 수 도 있다는 코치분의 말씀을 들었는데, ORM이라는 도구도 마찬가지 않을까 하는 생각을 하게 되었다.

이 기회로 SQL문을 다시 복습해야 될 것 같다.


다음번에는, 더욱 세밀한 채용 사이트 db 모델링에 본격적으로 들어간 후에 nestjs 상에서 controller 설계와 service 로직 개발을 진행해볼 계획이다.

728x90
반응형
Comments