Sangil's blog

https://github.com/ChoiSangIl Admin

spring 개발자와 Express의 만남(회고) DEV / SEED

2021-10-25 posted by sang12


회사에서 백엔드 서버를 처음부터 끝까지 구축해야 하는 상황이 있어서 Spring, Express 서버를 고민하다 Express 서버로 Restful Api 서버를 구현을 한 적이 있다. Express 서버를 선택한 이유는 프로젝트가 그렇게 크지 않았고, 관련된 서비스의 백엔드도 Express로 설계되어있어서 참고하여 개발하면 크게 어려울 거 같지 않아서였다. (Spring 환경에서 개발하던 지겨움도 한몫 했던 거 같다)

현재 서비스는 무사히 운영 중에 있지만, 내가 만든 구조가 그게 최선일까? 라는 생각을 할때 가 많았다.

서버 구조를 간략히 설명하자면 express rotuer에서 get/post 형태의 url로 접근이 되면 xxx-controller.js쪽으로 넘겨주게 되고 해당 controller에서는 xxx-service.js 모듈로 넘겨주고 service에서는 최종 xxx-model(dao)를 호출하여 비지니스 로직을 수행하고 리턴해주는 형태의 서비스였다. 

나름 예쁜 프로젝트를 만들고 싶어서 Spring에서 사용하는 디렉토리(아키텍쳐) 구조를 따라갔고, Swagger를(완전 노가다지만..) 이용하여 해당 Resful Api를 호출하는 업체에게 제공하기도 했었다. 보안은 Jwt토큰 쿼리빌더는 knex을 사용했고 배포는 jenkins에서 pm2를 이용하여 처리 하였다. 

그래 그때는 그게 최선이였고 현재도 Express서버는 정상 가동 중이다. 하지만 머릿속에 이게 최선이였을까라는 생각이 메아리처럼 울렸고 어떤 부분이 부족했을까라는 고민을 하게 되었다. 

일단 개발하며 느낀 Express의 장점은 투박함? 이였다. Spring에서는 기본적으로 제공해주고 간단한 설정을 하면 할 수 있는 것들이 Express에서는 제공이 안되서, 제공해주는 기능들을 찾거나 thirdParty libray를 이용해야 했다. transaction이랄지...  anotation이랄지... vo나 obejct는 어떻게 활용하지 @valid는 없나? 와 같은 것들.. 그와 동시에 Spring에서 이런 것들(개발자의 고민, 철학)이 녹아져 만들어진 프레임워크 안에서 개발하는데도.. 나는 아무것도 모르고 개발만 했구나라는 창피함을 느끼기도 했다.

Express의 장점은 투박함에서 나오는 가벼움 같다. 항상 Spring을 이용해 개발할 때면 testCode를 작성하지 않거나 하면 local에서 tomcat 서버를 수십 번 내리고 올리는 모습을 볼 수 있다. 하지만 Express서버는 무진장 가볍다. 그래서 MSA 아키텍처에 많이 사용하지 않을까? (물론 모름) 이란 상상을 해봤다. 

그럼 본론으로 Express 서버로 프로젝트를 구현했을 때 나의 부족한 부분을 생각한다면 크게 3가지의 문제가 있었다고 생각이 든다.

1. 테스트코드의 부재

2. 소스간의 종속성

3. 도메인, Vo 객체의 부재

테스트 코드를 왜 만들지 않았을까? 사실 여태 테스트코드에 대해 내가 개발을 쉽게 하기 위해서라고 생각했던 게 큰 것 같다. 물론 내가 개발을 안정적으로 더욱 빠르게 하려는 것도 맞겠지만, 해당 프로젝트에 오류가 없는지? 다른 사람들이 내가 개발한 것을 수정 했을 때 어떻게 검증하면 되는지? 와 같은 생각들이 빠져 있었던 것 같다. (사실 Express와 Swagger를 사용하니 Express는 가볍고 Swagger호출 해서 콘솔로 찍고 확인하고 개발을 하며.... 테스트 코드 만들생각을 안...) 그러던 어느날 프로젝트가 끝마칠 무렵 다른 Express 서버를 수정해야 하는 이슈가 생겼었는데 하나의 로직에 Callback 형태로 많은 서비스로직들이 물고물고 물려있었고... 몇 시간의 삽질 끝에 수정한 기억이 있다.. 테스트코드라도 있었으면... 아니 콜백형태가 아니였더라면... 아니 심지어 주석이라도 있었으면.... 이렇게 테스트 코드에 대해서 생각하던 중 자연스럽게 2번의 소스 간의 종속성 생각을 안 할 수가 없었다.

종속성.. 이부분은 nodejs에서 require이 싱글톤이라는 생각에 뭐 이정도면 됐지 하고 넘어간 부분이다. 내가 가져온 객체가 싱글톤으로 관리되고 있으니 호출될때마다 여러 객체가 생기고 죽고 반복하지 않으니 좋구나~ 하고 넘어갔던 거 같다. 하지만 여기서 생각하지 못했던 부분은 해당 객체를 생성하는 주체가 해당 객체를 사용하는 객체라는 점 이였다. 뭐 흔하지는 않겠지만 있을 수도있는 것이 특정 종속되는 dao를 통째로 변경해야 된다거나 커넥션을 받아와야 하는 dao에서 어떤 경우에는 mariadb쪽을 어떤 경우에는 oracle쪽을 조회 해야 하는 경우가 생길 수 있다. 그렇다면 이 구조에서는 커넥션을 가져와야하는 소스의 모든 부분을 다 변경해줘야하는 일이 발생하게 된다. 생각만해도 끔찍하다.. 하지만 사실... 이런 부분은 경험해본 적이 없어서 내게 크게 와 닿지는 않았다.  그보다 내게 와 닿았던 부분은 di로 해당 부분을 개선하면 테스트 코드를 더욱 효율적으로 만들 수 있겠구나라는 부분 정도였다. 테스트를 할 때 의존성 주입을 함으로 써, 사실 사용하는 객체 입장에서는 똥이든 된장이든 내가원하는 것만 받아오면 크게 상관할 일이 없다. 그럼으로 내가 테스트 해야할 부분에 해당 객체가 원하는 데이터를 주입해줌으로써, 해당 부분만 손쉽게 테스트가 가능하다는 장점이 생긴다. 예를 들어 Express 서버의 서비스 로직에 회원 정보를 가져와 카카오메세지를 보내는 기능이 존재한다고 생각해보자. 그럼 서비스 로직에서는 회원 정보를 가져오는 부분이 테스트 범위에 포함될까? 물론 큰 관점에서의 테스트는 해당 부분도 포함이 되겠지만 일단 서비스로직 관점에서 보면 db가죽었건 살았건 회원 정보만 가져오면 된다. 그리고 카카오 메세지 보내는 부분도 메세지가 보내졌다는 리턴만 받으면 되지 카카오메세지 서버가 죽었거나 실제로 카카오메세지를 보내는 등의 테스트까지는 서비스로직의 관점에서는 필요하지 않을 것이다. 그러니 프로젝트간 종속성을 낮춘 상태에서는 서비스 로직이 원하는 객체를 moking을 통하여 전달하면, 디비가 죽었건 메세지 서버가 죽은 것과 상관 없이 서비스 로직이란 단위로부터의 테스트가 가능하다는 장점이 생긴다. 이게 di를 통한 이점이 아닐까...

물론 위의 생각들 중에 틀린 말도 많을 거 같다. 하나의 프로젝트를 마치고나서 흘러갔던 생각들과 그걸로 인해서 공부하게 됐던 부분들을 정리해 봤다. 3번 도메인, Vo 객체의 부재는 글을 적으면서 생각이 났다... 현재 업무를 하면서 사용하고 있는 Spring 어드민페이지는 모든 데이터들이 Map key value값으로 사용한다. 그러다 보니 어떤 데이터가 들어오는지를 대체 알 수가 없다. 기존에 개발되어있던 부분에서 수정을 하다가 어디선가 사용하고 있는 변수를 사용한다면..?  Validation 체크를 하는데 이런값이 어디서 들어오지? 안쓰는거아냐 하고 지웠다면? 이런 부분에 있어 수정이 쉽지 않다. 아니 수정하려면 앞 단에 있는 jsp에서 어떤 값을 던지는지 그리고 그게 jsp파일 1개인지 여러 개이면 여러 개의 값들을 다 확인 해야 한다... 그러다 보니 그냥 내버려두게 된다. 테스트도 쉽지 않다. 이런 생각을 몸소 체험하고 있었는데도 Express에서는 지원되는 라이브러리나 그런 것들이 있는지 확인해보지도 않았다. 회고라고 적고 반성문을 적는 기분이다 :)

REPLY