1. 기술 스택 선정에 대한 고찰 -1편 개발 언어-

2023. 2. 17. 22:49프로젝트/8주차 실전 프로젝트

1. TypeScript(이하 TS)

앞서 두 프로젝트(미니 프로젝트/클론 코딩)의 경우에는 Node.js로 작성되었다.

JavaScript(이하 JS)를 이용하여 Node.js를 통해 서비스를 개발하면서 가장 많이 직면했던 문제점이 있었다.

타입 에러와 관련된 디버깅 시에 한 단계씩 다 찾아야 했다.

Type Error(타입 에러)는 기대했던 타입의 값이 아닐 때 발생하는 오류다.

종류는 다양했었다.

대상이 null이나 undefined일 때도 있었고, OO is not a function 이라던지 등이었다.

아직 배워나가는 중이라 그런 것일지 몰라도, API의 나름대로 로직을 작성하고 테스트 할 때 제일 많이 본 것 같다.

내가 구현하고 있는 기능에서 위의 문제가 생겼을 때는 대략적으로 어느 부분에서 문제가 생겼는지 알고 좁혀나가면서 문제를 찾았던 기억이 난다.(console.log의 악몽이..)

JS는 런타임에서 타입이 결정되는 동적 타입 언어기 때문에 타입을 선언하지 않아도 사용할 수 있어서 사용하기는 편했지만, 타입 결정과 관련되서 에러가 발생하면(항상 이런 문제는 런타임에서야 오류를 발견했다 ㅠㅠ) 에러를 찾고 수정하는데 시간을 잡아먹는다는 생각이 들었다.

이전의 두 프로젝트는 규모가 작은, 간단한(?) 프로젝트 였기 때문에 상관없었다고 생각했지만 실전 프로젝트는 그래도 나름대로 서비스!를 구현한다고 생각했기 때문에(이전의 프로젝트보다 규모가 더 크기 때문에) 디버깅이 점점 어려워진다는 것이 문제였다.

 

그래도 마침 이런 단점을 보완하기 위해 TS가 있다는 정보를 접하고 사용하게 되었다.

 

1-1. 장점

  • 코드 작성 단계에서부터 타입을 체크하고 오류를 확인 할 수 있다.(타입 에러 발생!)

막상 더 쓰려고 하니까 이게 끝인 것 같다. 물론 이 하나가 엄청난 장점이다! 내가 그동안 얼마나 구체적인 생각 없이 변수를 사용했는지를 다시 되돌아보는 계기가 되었다. 타입을 잘못 사용할 때마다 빨간 밑줄로 에러와 그 이유를 띄워주다 보니까 디버깅 수가 많이 줄었다는 것을 느꼈다.

물론 이것 말고도 수많은 기술적 장점들이 존재하겠지만, 초보자인 나의 시선에선 가장 크게 느껴졌던 장점이 저것이었다고 생각한다.

1-2. 단점

  • 개발 규모가 커지니 타입을 설정하게 되는 시간이 오래 걸렸다.
  • 코드가 너무 길어져서 가독성이 떨어졌다.
  • 어렵다!(당연히 지켜야하는 것이겠지만, JS를 사용하다가 TS사용하면서 느꼈다.)

까마득한 기억에서 배웠던 C언어를 생각해보면, 타입을 지정해서 사용하는 것이 당연했지만 JS를 사용하다보니 편안함에 익숙해져서 그런가..TS를 사용하니까 어렵게 느껴졌던 것도 사실이다. 엄격한? 형식? 으로 지정했다보니 익숙하지 않은 초반엔 이전에 쉽게 했던 작업들도 하나하나씩 부딪쳐가면서 개발했던 기억이 난다.

어느샌가 보니 코드 라인수가 길어졌다! 인식하지 못했는데 작성하고 보니까 코드 라인 수가 너무 길어져서 놀랐던 기억이 난다. 코드 라인 수가 길어지다보니 로직적으로 문제가 생겼을 때 코드 가독성이 조금 떨어져서 찾기 불편했던 기억이 난다.

이전 프로젝트보다 규모가 커지다보니 API 수도 많아지고, I/O에 대한 타입을 엄격하게 설정해야하다보니 익숙하지 않았을 때 프론트 분들과 작업할때 사소한(하지만 사소하지 않은) 타입 하나로 에러를 찾고, 수정했었다.

 

그래도 지금와서 생각해보면 TS를 쓴 것은 오히려 좋은 기회였던 것 같다. 생각만큼 기능 개발을 많이 한 것도 아니고, 완성도를 높게 한 것도 아니지만 이 부분은 차차 수정해나갈 것이고 이전에 JS를 쓰면서 물에 물탄듯, 술에 술탄듯 스무스하게(방만하게..) 변수를 사용하는 습관을 고쳤던 것 같다.

 

 

2. Nest.JS

어흥!

1번의 TS를 채택했다보니 자연스럽게 Nest 프레임워크의 사용을 고민하게 됬던 것 같다.

 

Nest.js는 Node.js에 기반을 둔 웹 API 프레임워크이다.

필요한 라이브러리를 쉽게 설치(npm, yarn)하여 기능을 확장할 수 있는 Node.js의 장점을 가지고 있으며, TS를 기본으로 사용하여 타입 시스템의 장점을 누릴 수 있다.

모듈/컴포넌트 기반으로 프로그램을 작성해 코드 재사용성을 높일 수 있다.

 

1. 장점

  • 모듈 기반으로 강제(?)한다.
  • TS기반으로 사용한다.
  • Node.js 기반으로 장점을 그대로 가져올 수 있다.
  • 데코레이터!

사실 Nest를 채택하게 된 것은 막 엄청난 장점이 있다! 라고 해서 사용한 것은 아니다.(라고 말하면 안되지만 그래도 포스팅인 만큼 솔직하게 적고 싶었다....)

Node.js로 서비스를 개발하면서 3 layered architecture(controller, service, repository)로 개발했었는데, 강제로 이것을 사용해야하는 것은 아니었지만, 필요성은 인지하고 사용했었다. 하지만 내가 이것을 올바르게 사용하고 있었는가에 대한 의문이 있었고, Nest.js에서는 모듈 기반으로 사용하는 것을 전제?강제? 했기 때문에 뭔가 매력적이었다.(이렇게 쓰는게 올바른 사용법이야!) 라고 하기엔 몬가 몬가 한 느낌이고, 모듈 사용하는 것을 가이드라인으로 제시한다는 것에 대해서 배울 것이 있다고 느껴졌다.

그리고 Node.js에서 controller, service, repository를 각각의 파일로 묶어서 사용했는데 동선이 불편했다.

좀 더 쉽게 설명하면. post에 대한 작업을 진행하는데 post-controller와 post-service를 오가는데 디렉토리를 찾으면서 왔다갔다 했던 것이 은근 거슬리고 불편했다.(마우스 동선은 중대사안이다...)

Nest.js에서는 post 모듈, comment 모듈 이렇게 작업했기 때문에 식별하기가 쉬웠고 해당 모듈의 개발이 편리했던 것 같다.

사용하면서 느낀점은 처음에 별 생각이 없었던 데코레이터가 굉장히 편리했다.

DTO의 @isString()이라던지, controller의 @Post/Get/Put/Delete 라던지, @가 달려있다보니 식별하기 쉽고, 함수를 명시적으로 수정하지 않아도 기능 확장을 시킬 수 있어서 매력적이었다. JS에서는 라우터에 들어가서 선언하고, controller에 가서 작성하다보니 가끔 헷갈려서 다시 한번 확인 해야 했던 적이 있었다. 같은 페이지에서 확인 가능하다보니 왔다갔다하는 동선이 압도적으로 줄어들었다.

 

2. 단점

  • 처음 사용해보는 프레임워크로 진입 장벽이..
  • TS도 처음해보다 보니 난이도가 곱절로 어려웠다.
  • 모듈끼리 얽히다보니 import 개념을 이해하는데 어려웠다...

개발자를 희망하기 때문에 앞으로 프레임워크를 익힐일이 당연히 많을 것이다. 이기 때문에 도전! 이라는 생각으로 시작했지만 중간에 후회를 많이 했던 것 같다.(내가 왜 사서 고생하고 있지..) 개발 기간도 당연히 한정되어있고, 처음 배우는 것이다보니 진행속도는 당연히 안나왔으며, 프론트 분들의 진행속도에 비해서 초반 설정 및 사용법 숙지하는데 너무 오랜 시간이 걸렸던 것 같다. 물론 지금와서는 후회하지 않고 좋은 경험이었다. 모듈에 대한 장점이나 응집도, 결합도에 대해서 좀 더 생각해보는 시간을 갖게 되었고, 다양한 경험이 나에게 더 좋지 않겠는가.

물론 TS도 처음하는 것이었기 때문에(C언어는 너무 과거의 기억이다) TS도 어려운데 Nest.js도 어렵다. 이 두가지가 초반 개발시에 가장 어려웠던 점이었다.

 

처음의 이유기도 했지만 모듈끼리 import하는 것을 잘 이해하지 못해서 관계를 설정?하는 것에 복병을 만나기도 했다.

이 문제를 해결하다보니 알게된 지식(역시 문제가 생기고 발등에 불똥이 떨어져야 깨닫게된다.)이었는데 Cyclic Dependency(의존성 순환) 문제였다.

기존의 Node.js에서는 폴더 구조(Controller, Service, Repository)로 작업했기 때문에 몰랐던 것인데, 모듈 구조로 작업하다보니 마주한 문제인 것이다.

문제를 인지하기는 했지만 아직 완벽하게 해결한 것은 아니고 일단 돌아가기만 하면 된다는 개발자의 격언(?)으로 땜질을 하긴 했지만 고쳐야될 숙제라고 생각하고 있다.

의존성 관계(import)는 순환이 없고 단방향이어야 한다. 즉, 어느 모듈에서 시작하더라도 의존성 관계를 따라가면서 최초의 모듈로 되돌아 갈 수 없다.

프로젝트를 진행하면서 User, Auth모듈이 있었다.(간단한 예시이다.)

Auth 모듈은 User,모듈에 import 되어있다.

User모듈은 Auth모듈에 import 되어있다.

Auth -> User -> Auth -> User .....

서로가 서로를 import하다보니 무한 참조하게 되는 문제이다. (최대한 쉽게 설명하려고 했지만 설계상의 문제나 다른 방법이 있을 수 있다.)

우선 이를 해결하기 위해 터미널 로그에서 추천했던 forwardRef로 어떻게든 기능이 정상적으로 작동하게는 했으나 뭔가 해결했다는 느낌은 들지 않는다.(혹시나 원래 그런가 싶어서 Nest로 개발한 다른 코드들을 보았으나 forwardRef의 향은 보이지 않았다...) 이 또한 앞으로 내가 해결해야하는 숙제인 것이다.

 

다음으로 부족했다고 느껴진 것은 응집도, 결합도 문제 였다.

이 부분은 정확하게 어느 부분이 문제인지 콕 집어서 말하기가 어렵고, 확실한 것은 내가 이 개념에 대해 잘 알고 코드를 작성했다는 것이 아니란 것이었다. 공부를 하고 정확한 문제점을 알게되면(혹은 내가 다행히 문제가 없게 작성했는지 확신을 가지게 되면) 추후 포스팅하게 될 것 같다.

 

원래 쓸 것이 적을 것 같았는데 사견이 들어가고 막상 적다보니 적을 내용이 많아서 내용상 1편 2편 이런식으로 적어야할 것 같다.

가장 베스트는 프로젝트를 진행하면서 느낀점을 적는 것이겠지만, 모종의 이유로(추후 포스팅하게 될듯..) 개발 일정이 촉박해지고 시간에 쫓기다보니 포스팅을 미루게 되었다. 그래도 끝나고 회고하면서 적다보니 다시 새록새록 생각도 들고, 어떤 점이 문제점인지 다시 생각해보게 되는 것도 나쁘지 않은 것 같다.