신입개발자의 네번째 프로젝트 후기
시간이 다시 또 흘러 네번째 프로젝트가 마무리가 되었다.
3월에 끝나야 했을 세번째 프로젝트가 추가 개발로 인해서 6월까지 미뤄져 2개의 프로젝트를 동시에 진행하게 되었다.
그러다 보니 너무너무너무 바쁜 시간을 보내게 되었다.
프로젝트 막바지에 이르러서는 3달간 쌓인 피로로 인해 수술대에도 올라가 보았니 참… ㅋㅋㅋ

이번 프로젝트는 중고상품의 경매라는 주제였는데, 나름대로? 이커머스 경험도 해볼 수 있어서 좋았던것 같다.
돈과 관련된 중요한 로직도 있고 세세하게 신경쓸 부분도 많았다(푸시의 종류도 많고, 연계되어 있는것도 많고…).
혼자서 많은 use case를 처리하다 문득든 생각은 지금 처럼 혼자 server side를 전부 담당하는 것보다.
use case 별로 업무를 할당해서 하면 좀 더 실용적으로 일을 할 수 있지 않을까 생각이 들었다.
물론 큰 회사에서 이미 이렇게 하고 있겠지만! 담당 업무가 줄어드는건 덤이다
이번 프로젝트는 많은 것을 경험해 볼 수 있는 프로젝트라서 의미가 남달랐던것 같다.
각설하고 시작!
이슈
1. Local Server과 Real Server
고객사로부터 AWS계정을 받기 전 Docker를 Local로 띄워서 MySQL을 사용했다.
Real Server에서는 MariaDB를 사용하지만, MariaDB의 근본은 MySQL이고 옛날 버전의 MySQL을 사용하면 문제가 없을거라는 얄팍한 생각 때문이었다.
언제나 내 생각대로 개발이 된다면 참 개발은 쉽고 재미있었을 것이다.
문제는 어김없이 Local에서 Real로 넘어갈때 발생했다.
개발 후 정상적으로 동작되는 것 까지 확인한 API가 아예 동작이 안되는거다?
보아하니 Sequelize를 통해서 만들어진 Query와 직접 작성한 Sub Query가 혼용되었을때 문제가 되었다.
MySQL에서 작성된 Join문을 기반으로 작성된 Sub Query를 MariaDB에 맞춰 다시 작성하니 정상적으로 동작되게 되었는데,
아쉽게도 그때 당시 여러 일이 겹쳐서 정확히 원인이 무엇인지 파악하지 못했다. 이후 작업을 넘어가게 되었다.
그래도 어중간하게 알고 환경을 적용하려고 했다가 고생을 좀 했으니 다음에는 그렇지 않겠지 하하
2. SQL
이전에 작성해둔 Query가 한번 조회했을때랑 두번 조회했을때랑 값이 계속 달라지는 현상을 확인했다.
그리곤 1~2분뒤에 다시 조회하면 첫번째 값 다시 조회하면 두번째 값으로 나오는 이상한 형상이었는데,
결론 부터 말하자면 @ 변수를 사용하면서 초기화를 해주지 않아서 일어나는 일이었다.
DB에 접근할때 @를 이용한 변수는 해당 커넥션이 유효할때동안 값이 유지 되기 때문에 연속해서 조회를 하게 되면 값이 꼬일 수 밖에 없는 상황이 었던것이다.
뭔가 일정 시간을 주기로 현상이 발생하기에 커넥션에 연관된 문제이지 않을까 생각은 했는데 @ 변수 때문이라고 확정 지은건 여러 차례 Query를 쪼개고 실행 시킨 후의 일이다.
결국 FROM절 안의 Sub Query에 초기화 구문을 넣어서 해결했는데 들인 시간에 비해서 알고나니 별것 아닌 문제였다.

또 하나의 이슈는
각 관리 매장의 매출을 뽑아내는 통계를 작성할 때였다.
월 별로 있을 수도 있고 없을 수도 있는 고정 지출에 대해서 조회하는 월에 고정 지출이 없으면 지나간 달의 고정 지출을 가져와야 했는데,
내가 작성한 Query에서 SUM함수를 사용하게되면 Null이라는 값도 안나오고 그냥 Empty row가 나오는게 아닌가?
row자체가 나오지 않으니 IFNULL또한 제대로 작동하지 않게 되었고, 또 그러다 보니 값이 엉망으로 나오는 사태에 이르게 되었다.
해당문제를 해결한지금 LEFT JOIN이나 OUTER JOIN을 이용하면 더 깔끔하게 해결하지 않았을까 생각이 들지만
그때 당시에는 기존 Query를 전부 수정할 시간적 여유가 없었기 때문에 변경의 폭이 적은 상황에서 처리하고 싶은 마음이 앞섰다.
그래서 적용한 방법이 COUNT 함수를 이용하는것이었다.
COUNT함수는 값이 없으면 Empty한 row가 나오는게 아니라 0이라는 값이 나오기 때문에 COUNT와 CASE WHEN를 활용해 처리하게 되었다.
나중에는 업체 요구사항 변경으로 통계 계산방식이 변하게되서 전부 새로 작성하게 되었다 ㅠㅠ

비록 고생한 내용이 실제 프로젝트에 반영되지는 않았지만,
자칫 놓쳤다가는 더 많을 시간을 허비했을 해당 이슈들을 통해서, 어느때고 중요한 포인트는 침착함과 넓은 시야로 문제를 찾는거라는 생각 이 들었다.
급할수록 천천히 짜는게 중요하다!
난관
1. Socket 서버관리
client와 connection을 맺은 socket server 객체를 안전하게 전역적으로 사용하고 싶었다.
그러기 위해서는 채팅에 관련된 logic과 함께하는 scoket server 객체에 대해서 따로 처리를 해줘야했는데,
제일 먼저 고려한 방법은 global 객체 안에 넣어서 사용하는 것이었다.
장점으로는 손쉽게 전역객체를 만들 수 있고, 접근이 쉬웠다는것인데, 그만큼 해당객체를 수정하는것 또한 너무나 손쉬웠다.
// ==== in chat class
const global.socket = new Socket();
// ==== other class
const global.socket = null;
이런식으로 처리를 하면 다른 사람 또는 미래의 내가 이 code를 봤을때 아래의 의구심이 들지 않을까 생각이 들었다.
scoket에 관련해서 객체를 제거하거나 상태를 변경해주는 다른 method가 존재 할 수도 있겠다?
이런 생각이 들었을때 global을 이용하는 방법은 바로 포기하기로 했다. 크킄
다음으로 생각한 방법은 singleton pattern을 이용하는 것이었다.
객체의 생성과 변경을 제한해 전역적으로 같은 객체를 사용해도 상태가 변하지않는 안전한 객체 를 사용할 수 있을거라고 생각했기 때문이다.
전역 객체의 불변성을 확인했으니 이제 구현을 고민해야했는데, 해결책은 간단했다.
이번에 새로도입한 NestJS에서 객체를 singleton으로 생성하고 관리해주는 기능이 있으니 이를 사용하면 되는것이었다.

코드를 직접 분석해보지는 않지만 spring framework의 스프링 컨테이너와 비슷하리라 생각이 들어 어렵지 않게 적용할 수 있었다.
2. Validation
리팩토링(2판)을 읽고 validation에 대한 생각이 많아졌다.
코드의 목적 과 구현 을 잘 구분해서 처리하고 싶은 마음이 앞섰기 때문이라 생각한다.
주로 if문을 이용해서 validation을 처리하곤하는데
function create(type: string) {
if(type !== 'run') {
throw new Error('타입이 올바르지 않습니다!');
}
}
간단한 로직 또는 작업한지 얼마 되지않은 프로젝트에 대해서는 그깟(?) if문 따위야 별 문제가 되지 않는다고 생각한다.
하지만 그게 아니라면 이야기가 달라진다고 생각한다.
저 code를 보아하니 validation 작업인것 같기는 한데 어떤 validation인지 코드를 분석해야하고, 왜 그렇게 구현해야했는지 되짚어 올라가본 경험이 있다.
안그래도 복잡한 business logic안에서 한눈에 들어오지 않는 code들이 혼재되어 있으니 지금 다시 생각해도 스트레스를 받는 기분이다.

물론 책에서 아주 좋은 해결책을 제공해준다.
의미있는 이름을 가진 method로 분리해 validation이라는 관심사와 business 라는 관심사를 분리하는것인데,
문제는 이걸 내 프로젝트에 어떻게 적용시키냐는 것이었다.
class 안에 private 접근제어자를 이용해서 빼놓을까 생각을 했더니 business logic을 담당하는 method들과 시야에서 완전히 분리하고 싶고,
Java와 달리 package가 존재하지않아 protect 접근제어자로 use case에 제한을 둘수도 없었다.
또 js에서 protect 접근제어자가 유효하려면 해당 클래스를 상속 받아야하는데 validation method들과 business method의 관계를 해결하고자 상속을 쓰자니 상속이 옳은 해결책이라고 생각이 들지 않았다.
아주아주 총체적 난국이다 하하
그래서 validation class를 만들고 그안에 static method로 작성을 진행했다.
const user = uesrDao.getById(3);
UserValidation.checkUserEmpty(user);
작성하고 보니 함수의 모양이 마치 보통의 business method와 비슷한 모양새를 가지게 되어서 관심사가 분리되었다는 생각이 크게 들지 않았다.
그래서 class가 아닌 function 단위로 export해서 validation 하는 모양으로 프로젝트를 진행해보았다.
const user = uesrDao.getById(3);
checkUserEmpty(user);
또 막상 이렇게 작성하고 보니 특정 기능을 묶어 놓은 util 성질의 function인지 error를 유발할 수 있는 function인지 한눈에 구분이 가지 않아서 아래와 같이 코드를 수정했다.
const user = uesrDao.getById(3);
THROW_USER_EMPTY(user);
error를 유발할 수 있다는 것이 명확히 보이고, 내가 생각한 문제점들이 해결된 모습을 보여서 위와 같은 작업방식으로 프로젝트를 마무리지었는데,
이 부분에 있어서는 어떻게 처리하는게 제일 좋은 방법일까 지금도 의문이다.
기업, 또는 팀에서 정해놓은 규칙에 따르는게 제일 좋은 방법이지 않을까 내심 생각한다!
3. Test
프로젝트가 진행되면서 기능의 정의가 바뀌는 경우가 빈번하게 있다(ex. 요구사항 변경, 담당자와의 커뮤니케이션 부족).
그때마다 매번 해당 부분을 수정하고 test하는 과정들을 거치게 되는데,
한 기능에 대해서 많은 사전 작업이 요구되고 business logic의 복잡도가 높아질 수록 조그마한 수정도 어렵고 test하는 것에 대해서 부담이 커진다는걸 뼈저리게 느끼게 되었다.
test를 위한 사전작업을 준비하는것 부터 시나리오1, 시나리오2, … 동시에 여러 생각을 하니 머리에 부하가 너무 많이 걸리더라
내 코드도 잘 못믿겠는데, 하물며 내 머리는 어떻게 믿겠는가?
그러던 중에 스쳐 지나갔던 채용공고의 ‘TDD 유 경험자’, 오픈채팅에서의 TDD에 대한 이야기들이 문득 스쳐지나갔다.
현재 test를 하기 위해서는 controller => service 까지 전체에 걸쳐서 test를 해야했는데,
만약 내 프로젝트가 TDD기반으로 개발되었다면 좀 더 단위별로 테스트하기가 훨씬 더 수월하지 않았을까 생각이 들었다.
하지만
- 단순 게시판의 CRUD API개발이 하루 종일이 걸린다.
- 미경험자가 처음부터 하기에는 어려움이 많이 따른다.
- 등등…
개발 속도와 관련된 이슈들이 굉장히 마음에 걸렸다.

물론 한프로젝트를 긴~ 긴~ 시간 유지보수를 해야한다면 모를까.
si업무만 하고 있는 현상황에서는 맞지않는 개발 패러다임이라 생각이 들었다.
하지만 빠른시일 내에 TDD 관련 도서를 읽어야겠다는 새로운 목표가 문득 떠올랐다.
현재로서는 모든 method에 대해서 test 검증을 거칠 수 없겠지만,
중요한 핵심 logic에 대해서만 test를 도입하는건 충분히 고려해볼만하다고 생각했기 때문이다.
4. Name Server
이번에도 .kr 도메인을 사용하고 싶어하는 고객사의 요청에 의해서 aws의 ns를 카페24로 이관하는 작업을 진행했다.
저번에 작업했을 때는 막막했는데 한번 해봤다고 이걸 작업이라고 부르는게 맞나 싶을정도로 쉬워졌다!
하지만 언제나 내 마음대로 되는건 없었다.
어느날 고객사로 부터 사내 메일이 동작하지 않는다는 연락을 받게 되었다.
처음에는 이걸 왜 나한테 이야기하지? 이게 뭔가 싶었지만 곰곰히 생각해보니 확실한 이유는 해당 도메인의 설정을 내가 만졌기 때문이었다.
이유인 즉슨 .kr 도메인을 aws ns로 옮기면서 mx record의 설정이 존재하지않아 해당 도메인으로된 송-수신된 메일들이 정상적으로 동작(?)하지 않게 된것이었는데,
업무진행이 되지 않는다고 최대한 빨리 작업을 해달라고 요청이 들어왔을때 꽤나 진땀을 뺏던것 같다.
결국엔 route53에 mx record를 추가하고 daum mail과 연동해주니 되돌아 보니 쉬운 문제였다.

5. Svelte
front-end 개발자님의 퇴사로 진행하던 프로젝트를 내가 이어받아 관리자 페이지의 화면 개발을 내가 하게되었다.
평소에도 화면 개발에 관심이 있어서 좋은 기회가 오면 해보고 싶었지만, 담당자의 부재로 인해 내가 맡게 되었으니 부담감을 많이 느끼게 되었다.
강의라도 하나 보면서 작업을 진행했으면 좋았겠지만, 토이 프로젝트도 아니고 회사 업무이고 빠르게 작업을 진행해야하는 상황이었기때문에 모르는건 그때그때 찾아가면서(아는게 하나도 없지만) 작업을 진행해야했다.
우리 회사의 front는 svelte로 구성되어 있었는데,
나온지 얼마되지 않은 기술이라서 그런지 공식문서가 굉장히 잘 되있어서 엄청 큰~ 어려움은 겪지 않았던것 같다.

무엇보다도 jsp에서 el과 jstl을 이용해서 개발하는 느낌도 받아서 덜 낯설게 느껴졌다.
이전까지는 back-end만 담당하며 작업을 했기에 잘 느끼지 못했는데,
front와 back을 같은 언어로 운영한다는 것이 새삼 편리하다는게 느껴졌다.
java를 이용해서 서버를 구성할때는 그때마다 스위치가 딸깍딸깍 하고 바뀌어 가며 작업을 하는 느낌이었는데,
같은 언어를 함께 사용하니 그런 이질감 없이 작업을 할 수 있었다.
서버와 달리 front 작업을 할때 대부분 html, css, js를 이용하는데 이에 맞춰서 js로 서버도 함께 구성할 수 있다하니 참으로 실용적? 으로 느껴졌다.
그래서 노드가 인기를 얻을 수 있었던건가?
개선
1. NestJS
이번 프로젝트는 기존 express를 걷어내고 nestjs를 도입한 첫 프로젝트다.
처음에는 잘 도입할 수 있을까 고민이 많이 되기도 했는데, 만족스럽게 잘 마무리가 된것 같다.
작업을 하면서 좋았던 점을 몇가지 나열해보겠다.
1.framework에서 제공하는 심신이 편안해지는 프로젝트 구조.
express가 3D펜을 이용해서 프로젝트를 구성하는 느낌이라면 nest는 건담을 조립하는 느낌을 받았다.
그렇기에 nest를 이용해 구성한 프로젝트라면 어느정도 획일화된 모습을 가질 수 있다.
nest 처럼 구조를 잡아서 사용할거면 차라리 spring boot를 쓰라고 하는 사람들이 종종 있다.
그런데 단지 저 이유뿐만이라면 좀 억지스러운 주장이 아닌가 생각이 든다.
가장 큰 이유로 언어가 다르다는 것이다.
- 나는 구조적인 framework를 이용하고 싶은데 그러기 위해서 java를 배우고 다시 spring을 학습해라?
- front작업과 같이 진행하기에 언어의 전환 없이 작업을 하고 싶지만 spring을 꺼내와라?
상황에 맞춰서 기술 스택을 정해야지 무조건적으로 이거다 저거다 하는 모습들이 좋아 보이지 않았다.
위에서 기술했듯이 front와 back을 같은 언어로 작업하는것도 꽤나 멋지고 말이다.
그렇다면 구조를 framework에서 제공함으로 가질 수 있는 장점에는 뭐가 있을까?
큰 이점으로는 다른 사람이 나의 프로젝트를 봐도 이를 이해하기가 수월하다는게 아닐까 싶다.
지금이야 혼자 한 프로젝트를 책임지고 마무리를 짓지만, 내가 없을때나, 다른 사람과 협업을 할때 훨씬 더 효과를 발휘하리라 생각한다.
2.이마트 시식코너 처럼 골라 사용하는 다양한 library.
블록처럼 여러 오픈소스를 끌어다가 사용하는 것도 좋지만, 외부 라이브러리가 많아질 수록 그안에 무슨 code가 있는지 모르니 신뢰도가 떨어지고,
주기적으로 업데이트 되지 않는 라이브러리(typedi는 2016년 이후로 relase가 없다)를 사용하기는 찝찝하다 이말이야!
하여간 그렇다 여러분들도 5년이나 지난 휴대폰 사용할때면 답답하지 않겠는가?
필요한데 있을것 같다 싶은 것들은 왠만해서 다 지원한다.
공식 문서또한 너무 잘되어 있어서 적용이 수월한건 덤이다.
nest맛을 한번 보니 express로 다시 돌아가고 싶지 않다.
왜냐하면 express와 달리 nest는 개발자가 개발에만 집중 할 수 있게 해주는 종합공구상자라는 느낌을 받았기 때문이다.

작업 초반에는 내가 framework에 끌려다니면서 작업속도가 너무 안나오면 어떡하지 고민을 많이 했는데, 재미있게 잘 작업을 한것 같다.
framework가 발목잡는 다는 느낌은 전혀 받지 못하고 문제점은 언제나 다른곳에서 터져나왔다….
지금도 100% 활용하고 있다는 생각이 들지않는데 좀 더 능숙해지면 nest가 얼마나 더 powerful 해질지도 궁금해진다.
2. Dao
이번 프로젝트에서는 dao를 제거한 뒤 작업을 진행해보았다.
이유는 dao는 db에 접근 만 해야하지만,
작업을 거듭할 수록 service와 dao의 경계가 애매해지는걸 이전 프로젝트에서 경험했기 때문이다.
나름 신경을 썻는데도, 각자의 영역을 침범한다는 느낌을 지울 수 없었다.
기존 dao를 보아하니 dynamic query를 만드는 로직이 핵심으로 자리 잡은것 같아.
query를 만들어주는 method를 각 use case별로 묶어 class를 import해 service에서 사용하는 방법을 사용했다.
const query = ProductQuery.getById(3);
const result = Product.findOne(query);
처음에야 꽤나 괜찮은 처리 방법이라고 생각했지만 작업을 진행할 수록 query는 db와 관련된 것이지 business logic과는 연관이 없어 service가 query를 알 필요가 없다고 생각하게 되었다.
다음에는 다시 dao를 만들어 작업을 하되 관심사 분리를 더 철저히 하면서 작업을 진행할 예정이다.
결국 원복하는 수순이 되었지만 왜 dao가 필요한지 느끼게 되었으니 좋은 경험이 되었다고 생각한다.

3. RxJS
nest를 이용해 프로젝트를 진행하던 중에 신기한 library를 발견하게 된다.
rxjs라는 라이브러리인데 프로그램을 반응형으로 작성할 수 있게 도와주는데 nest가 이걸 기반으로 작성이 되었다나 뭐라나.
궁금증에 알아보다 보니 반응형 프로그래밍에 관련된 책을 2권이나 사버렸다…
rx에 관련된 내용은 front에 비교해서 비유가 많이 들었는데, 나는 server 개발을 하기때문에 엄청 와닿지는 않았다.
그래도 rx의 도입결과는 굉장히 만족스러웠다. 지저분하던 코드가 stream의 형태로 깔끔하게 정리 되니 정말 색다른 경험이었다.
물론 코드 작성에 시간이 많이 들었다는건…
stream이라는 이름 그대로 강물이 흘러가는것 처럼 code를 작성해 가니 business logic의 가독성이 확실히 올라가는걸 느꼈다.
하지만 모든 logic에 rx를 도입하는건 과하다는 생각이 들어서 복잡한 business logic에 선택적으로 적용해봤다.
const transaction = await setTransaction();
const createObject = await create(transaction);
const relationObject = getBulkObject(createObject.uniqueId);
if(!relationObject) {
throw new Error('알수 없는 에러가 발생했습니다.');
}
await bulkCreate(relationObject, transaction);
기존 코드는 더 요상하지만 여기서 차마 오픈할 수 없기에 최대한 공감할 수 있을만한 코드를 작성해 봤다.
const transaction = await setTransaction();
createObject(transaction)
.pipe(
pluck('uniqueId'),
map(id => geBulkObject(id)),
tap(bulkObject => THROW_OBJECT_NOT_EMPTY(bulkObject)),
switchMap(bulkObject => bulkCreate(bulkObject, transaction))
)
.toPromise();
실제 코드 변화를 보여주지 못하는게 안타까울 따름이다.
핵심 로직 2~3개 정도를 rx로 refactoring을 진행해봤는데, 이로 인한 큰 변화점은 비동기 처리였다(봐라! await이 몇개로 줄었는지!).
적용 전에는 await 키워드를 통해서 비동기 작업을 동기 작업 처럼 이해할 수 있게 해줬고. 비동기냐 아니냐에 대해서 계속 신경을 써줘야 했다.
하지만 예시 코드에서 보는것과 같이 rx의 stream안에서는 동기냐 비동기냐는 중요치 않고 하나의 흐름으로 취급하기 때문에 좀 더 business logic에 집중할 수 있어 좋았다.
놀라움에 연속 이후 이대로 가다간 rx에 종속될것만 같았다. 나중에 가면 rx없으면 coding도 하지 못하는것 아닌가 염려까지 되더라 ㅋㅋ
그래도 필요에 맞게 적재적소로 사용한다면 분명 좋은 기술이라 생각이 들고, 또 rx로 refactoring된 code를 볼때면 뿌듯해서 배도 안고프더라(?)
결론
이번 프로젝트는 나 스스로가 자신감을 많이 가질 수 있는 계기가 된 프로젝트이지 않을까 싶다.
자만하면 안되겠지만 프로젝트에 시간을 들이고 노력하면 어떡해서든 할 수 있겠다? 생각도 들었고,
작년 취업을 준비할때 바닥을 찍은 자신감이 조금씩 회복되는 느낌을 받았다.
관심사를 분리하고 method로 묶어 작업을 처리하다보니 생긴 문제가 있다.
여러 method로 참조형 변수를 넘기다 보니 어떤 method에서 어떤 값으로 변경될지 추적하기가 굉장히 어려워졌다는 것이다.
const 키워드로 객체 자체는 immutable한 속성을 가질 수 있지만 property는 그렇지 않기에 매번 얕은복사가 아닌 깊은 복사를 이용해서 객체 자체를 복사해주는 작업이 필요한데 굉장히 번거로운 작업이 되지 않을까 싶다(javaScript는 왜 불변성을… ㅋ;).
그래서 생각한것이 immutable.js라는 라이브러리를 이용해서 불변성을 지켜가면서 작업을 해볼까 고민중이다.
library를 적용하는것이야 공부하고 시간을 들인다면 충분히 가능하겠지만,
불변성을 위해서 method마다 새로운 object를 생성한다고 하면 resource소모가 너무 커지지 않을까 염려가 된다.
처음으로 서비스를 시작하는 고객사가 많은 내 프로젝트 특성상.
서비스를 유지하는 비용 하나하나가 신경쓰일거라고 생각이 드는데,
개발자의 편의를 위해서 resource를 더 많이 사용하는 작업방식을 선택해 서비스의 유지 비용이 증가하는게 과연 맞을까? 라는 생각이 뒤따르기에 망설여지기도 한다.

구체적으로 비용이 얼마나 증가할지 계산할 능력이 없는 내가 안타까울 뿐이다..
필요한 부분에만 적용하는 방법이 있겠지만, immutable하게 돌아가는 business logic과 그렇지 않은 logic이 혼재되어 있을때 이를 어떻게 구분할지도 중요 point같다.
연구가 많이 필요한 부분이라서 결론이 어떻게 날지 흥미진진하면서도 답답한 주제다. 하하
다음 프로젝트때는 Sequelize에서 벗어나 TypeORM이나 MikroORM으로 작업을 진행해볼 예정이다.
새로운 ORM에 대해 경험해보고 싶은 마음이 제일 크고, query builder를 사용해서도 개발해보고 싶었기 때문이다(TypeORM이나 MikroORM은 ORM과 동시에 query builder로 사용이 가능하다).
담당한 프로젝트의 특성상 복잡한 쿼리를 사용해야할 경우가 많이 있었는데, 그때마다 raw query로 처리하고는 했다.
이유인 즉슨 ORM으로 어떻게 처리할지 머리 싸매고 고민할 시간에 raw query로 해결하자는 생각 때문이었다.
어느 기업에서는 JPA(ORM)와 QueryDSL(Query Builder)를 병행해서 사용한다는 이야기가 떠올랐는데(통계쿼리도 QueryDSL로 처리한다고 한다),
뭐가 그렇게 좋아서 이 조합으로 운영들을 할까? 싶기도 하고,
아무리 전해들어도 직접 해보는게 훨씬 낫다고 생각하기에 새로운 도전을 하게 될것 같다.

Leave a comment