본문 바로가기
개발 공부

원티드x위코드 프리온보딩 두번째 기업과제 (Mapia Company) 회고록

by 부지런한 배짱이 2021. 11. 8.

이번에는 두가지의 과제 중 한가지를 선택 해야 했다.

프레시코드의 과제는 첫번째 과제와 비슷한 상품 데이터 CRUD API 구현이었고

마피아 컴퍼니의 과제는 graphql과 neo4j를 이용한 CRUD API 구현이었다.

 

우리 팀원들은 어떤 과제를 하고싶어 할까?

프레시코드 기업의 과제는 다들 이전 과제때문에 지친 상태여서

조금 더 수월하게 진행 될거같은 것이 메리트였고

마피아 컴퍼니의 과제는 처음 접하는 생소한 것을 사용해볼수 있다는 메리트가 있었다.

 

우리는 모두 조금 더 새롭고 도전적인 과제를 선택했다.

이유는 아마도 그게 더 재밌어보였기 때문인 것 같다.

 

하지만 프레시코드의 과제를 선택했어도 의미가 있었을거라 생각한다.

프레시코드의 과제는 실무에서 다룰법한 상품에 대한 데이터를 처리하는 과제였고

여섯명이서 함께 진행하는 첫 과제였기 때문에 합을 맞추기 좀더 수월 할 것이라 생각했다.

그리고 같은 기능이지만 컨밴션과 코드, 등 개선할 여지가 많이 있었다.

 

만장일치로 선택된 마피아 컴퍼니의 과제 내용은 대략 이러했다.

 

  • neo4j GraphDB 필수 사용
  • CUD는 Rest API Read는 GraphQL로 구현

프레임워크는 NestJS를 사용했다.

 

먼저 우리 팀 다수는 graphql과 neo4j에 대해 알지 못하는 상태였기 때문에 30분정도 각자 공부하는 시간을 가졌다.

 

개인적으로 NestJS를 2개월정도 포트폴리오용 웹사이트를 만들며 사용해왔지만

계속 한가지 프로젝트로 진행을 해왔기 때문에 처음부터 다시 만들어 볼 기회가 별로 없었다.

그래서 이번에는 프로젝트를 처음부터 만들고 neo4j 까지 셋팅하는 것을 맡았다.

 

NestJS에 neoj4 셋팅하는 강의 영상

단순히 보며 따라 친 것 밖에 없었지만 사실 이런 경험이 나에게는 의미가 있었다.

프로그래밍 학습법에 대한 자료를 몇번 본적이 있는데, 내가 자주 보았던 학습법은

그것에 대해 공부하기 전에 일단 사용해보라는 것이었다.

하지만 나는 그게 남들보다 잘 안되는 것 같다.

 

뭔가를 처음 배울 때 강의나 문서를 보며 사용방식이나 컨밴션 등,

디테일한 부분까지 안내받기 전에는 그것을 실제로 사용하는 것을 어려워한다.

처음 시작할때 제대로 만들지 못하면 처음부터 다시 만들어야 할수도 있다는 생각이 들어서일까?

무언가를 학습하는데 시간이 적지않게 걸리기 때문에 학습 방법을 바꿔보고 싶었지만 생각보다 쉽지 않았던 것 같다.

 

하지만 이번에는 혼자 공부하는 것이 아니었고 팀원들이 기다리는 상황이었기에

최대한 빨리 셋팅을 완료하는 것이 중요하다고 생각됐다.

그래서 호기심은 접어두고 무작정 강의 영상을 보며 코드를 작성했다.

이런것도 가끔은 필요하다고 느낀다.

 

셋팅하는 과정에서 neo4j에 대한 폴더와 모듈을 생성했다.

내가 그동안 봤던 데코레이터 안에서 생성자를 주입하던 모듈과는 다른 형태였다.

 

글을 작성하며 알아보니, 동적 모듈을 생성하는 것이었다. : )

NestJS는 모듈이라는 것을 이용해서 의존성에 대한 제어를 런타임 시스템 위임할 수 있는데 (IoC)

간단하게 말해, 유저 모듈에서 Service 파일을 내보내고(export) 게시글 모듈에서 가져오면(import)

내가 따로 인스턴스를 생성하지 않아도 NestJS가 자동으로 인스턴스를 생성해주는 방식이다.

 

그동안 내가 생성한 모듈들은 단순히 import, export만 해서 사용하는 방식이었는데

동적 모듈은, 모듈을 가져올 때 인자에 값을 넣어서

import된 모듈이 인자 값에 따라 커스텀하게 결정되는 방식이다.

 

import { DynamicModule, Global, Module } from "@nestjs/common";
import { Neo4jService } from "./neo4j.service";
import { Neo4jConfig } from "src/neo4j-config.interface";
import { NEO4J_CONFIG, NEO4J_DRIVER } from "./neo4j.constants";
import { createDriver } from "./neo4j.util";

@Global()
@Module({})
export class Neo4jModule {
	// eslint-disable-next-line @typescript-eslint/ban-types
	static forRoot(config: Neo4jConfig): DynamicModule { // (1) 모듈을 생성할때 인자를 받음
		return {
			module: Neo4jModule,
			providers: [
				Neo4jService,
				{
					provide: NEO4J_CONFIG,
					useValue: config
				},
				{
					provide: NEO4J_DRIVER,
					inject: [NEO4J_CONFIG],
					useFactory: async (config: Neo4jConfig) =>
						createDriver(config)
				}
			],
			exports: [Neo4jService]
		};
	}
}

 

내가 셋팅을 하는 동안 팀원들은 graphql과 cypher(neo4j의 문법)에 대해서 파악하고 api 기능을 개발하고 있었다.

 

아쉬웠던 점은, 내가 직접 neo4j나 graphql의 쿼리를 작성하는 시간을 가져보지 못했다는 것이다. 😅

한가지 모델에 대한 생성 API를 만들기는 했지만 이미 있는 코드를 가져온것에 불과했다.

그래도 그 과정에서 repository 패턴을 적용하자는 의견을 내서 기존 계층 구조를 변경했기 때문에 의미가 없지는 않았다 :)

(db 영속성과 쿼리문을 따로 두고 service에서는 도메인 핵심 비즈니스로직만 작성하기 위해!)

 

 

그리고 repository 파일을 추가하면서 모듈에서 의존성 주입을 하는 방법을 좀더 확실하게 아는 계기가 되었다.

 

- Typeorm을 사용할 때 repository 의존성을 주입하는 코드

TypeOrmModule.forFeature([LectureRepository]),

- 일반적인 repository 의존성 주입 코드

@Module({
	controllers: [MusicianController],
	providers: [MusicianService, MusicianRepository]
})

 

typeorm 없이 다른 db 모듈을 import하고 내가 만든 repository에 주입한 다음 또 내 repository를 등록해야하는데

한번도 해본적이 없는 과정이기도 했지만..

부끄럽지만 사실 모듈에 대해서 제대로 이해 하지 못했다고 말하는게 맞는 것 같다.  😂

 

그래도 셋팅 과정에서의 실수들과 포스팅을 하며 공부를 한 덕분에 모듈에 대한 이해가 좀더 명확해졌다 :)

 

간단하게 설명하자면, 도메인에서 사용되는 모든 의존성은 provider에 명시를 해줘야한다.

그리고 모듈에서는 다른 모듈에게 제공 할 provider를 export에 명시해놓으면
사용하는 모듈에서는 providers에 따로 명시해줄 필요가 없이 import만 해오면 된다.

 

셋팅을 마치고 나는 테스트코드 작성을 맡았다.

이번 과제에서는 유닛테스트 퀄리티에 좀더 신경을 쓰고 싶었는데

내가 테스트 코드를 작성해야 할 때 구현된 기능들은

service는 repository 데이터를 전달하는 코드만 있고, repository에는 간단한 쿼리밖에 없어서

컨트롤러의 유효성 검사에 대한 테스트코드외에는 딱히 작성할게 없을 것 같았다.

 

NestJS에서는 컨트롤러에서 유효성 검사를 할 때

pipe라는 미들웨어에 class-validator 모듈을 적용시켜 유효성 검사를 하는데

컨트롤러 테스트코드에서 적용하는 법을 찾지 못하기도 했고,

유효성 검사는 e2e 테스트로 검증하는 것이 적합하다는 정보가 있었기에 e2e 테스트 코드를 작성했다.

 

테스트 코드를 작성하며 어떻게 해야 가독성이 좋을까 고민을 해보았지만

파이썬의 가독성을 따라잡기에는 내 실력으로는 무리가 있었던 것 같다.. 하하

e2e 테스트 코드

 

테스트 코드를 작성하기 위해서는 각 계층의 역할에 대해 이해를 해야한다.

 

첫번째 프로젝트를 진행 할 때 테스트 코드 작성법과

repository 패턴의 적용 이유에 대해 명확히 기억이 나지 않았었는데

이번 프로젝트를 하며 회귀하는 시간을 가졌다.

 

e2e테스트를 하며 버그를 잡은 경험은 새로웠다.

 

계획된 기능이 거의 다 구현 된 뒤에 프로젝트의 가독성을 위해

팀원들과 모여 전체 프로젝트 코드를 보며 상의 후 파일명부터 리턴 방식까지

코드 컨벤션을 하나하나 맞춰갔다.

 

함께 논의하며 코드를 수정하는 과정이 재밌었고

그 과정에서도 버그를 찾아 낼 수 있었다는게 또 새로웠다. ㅎㅎ

 

평소에 나는 내 의견을 많이 피력하지 않는 타입이었는데

프리온보딩 코스에서 내 의견을 적극적으로 내는 훈련을 해볼 수 있어서 좋았다.

물론 성격 좋은 팀원들 덕분인 것 같다. 😇

 

저번 프로젝트 보다 완성도가 올라간 것 같아서 좋다.

 

다음 과제에서 좀더 개선하고 싶은 것은

git rebase를 사용해서 커밋 기록에서 merge 메시지를 없애는 것과

테스트 코드를 먼저 작성해보고 기능을 개발하는 TDD 방식을 적용해 보는 것이다.

(다음 과제를 보니 TDD를 적용해보기에는 시간상 무리가 있을수도...?)

 

하나의 과제는 40시간이 주어진다. 그 사이 5시간정도의 수면과 식사시간을 제외하면

총 30시간 정도 함께 과제를 진행하는데, 그 시간동안 탈 없이 잘 진행되어 동료들에게 감사한다. 🙌

 

 

결과물

https://github.com/preOnboarding-Team13/Assignment_2_MAPIA

리드미 참 이쁘게 잘 작성해주신 것 같다. 🥺