외주 레거시로부터의 여정 4편

간만에 쓴다. 원래 4월 말에 적은 이후에 갑자기 너무 바빠져서 기억 저편에 사라져 있다가 갑자기 생각나서 이제서야 적는다. 원래 4월달에 적은 글인데, 이제야 퍼블리싱한다 : >

DB/Model

휴… 한숨이 먼저 나온다. 외주 코드가 엉망이라서가 아니라 이 안에는 굉장한 쿼리가 숨어있어서 반은 존경, 반은 어휴 이걸 어떻게 라는 한숨이 나왔던 것이었다. 1편에서 말한대로 외주 코드에서는 Model을 따로 정의했고 MySQL Driver로 Raw Query를 사용했다. 여기까지는 좋은데 테이블이 지나치게 많은 경향이 있었다.

예를 들어 컨테이너 종류를 따로 테이블로 만들었는데, 사실 20피트 드라이 컨테이너가 없어질 일도 없고 새로운 규격의 컨테이너가 나올 가능성은 굉장히 희박하다. 따라서 컨테이너 정보는 필요한 테이블에서 enum 으로 관리해서 넣어도 무방했다. 또한 파일정보 관련된 테이블만 10여개에 달했는데 기업별 로고 파일 정보를 저장한 테이블, 소개자료 정보를 저장한 테이블 등등. 테이블 컬럼도 거의 동일하기 때문에 하나로 통합하고 플래그로 구분하면 될 일이었다. 뭐 그 당시에는 다 계획된 일이 있어서 만들었기 때문에 절대 비난한 일은 아니지만 지금 보면 좀 아쉽긴 하다.

DB는 Sequelize ORM을 도입했다. 다만 모든 쿼리를 Sequelize Query로 짜진 못했는데 아래와 같은 무지막지한 쿼리 때문이었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
SELECT SQL_CALC_FOUND_ROWS DISTINCT
u1.id, f1.id AS column1, u1.company, isCertifiedBL, isBelieve, column4, column5, column6, column7, column8,
avgStars, reviewCount, fl1.src as logo,
(SELECT JSON_ARRAYAGG(JSON_OBJECT('name', c1.name)) AS SAMPLE8
FROM SAMPLE1 fj1
INNER JOIN SAMPLE8 c1 on fj1.cityId = c1.id
WHERE f1.id = fj1.column1) SAMPLE8,

(SELECT JSON_ARRAYAGG(JSON_OBJECT('name', si1.name)) AS services
FROM Services s1
INNER JOIN SAMPLE2 si1 on s1.column2 = si1.id
WHERE s1.userId = f1.userId) services,

(SELECT JSON_ARRAYAGG(JSON_OBJECT('name', fs1.name)) AS ffff
FROM SAMPLE3 fss1
INNER JOIN SAMPLE4 fs1 on fss1.column3 = fs1.id
WHERE fss1.column1 = f1.id) ffff, ffair1.price, ffair1.expiredAt
FROM Forwarders f1
INNER JOIN SAMPLE9 u1 on f1.userId = u1.id
LEFT JOIN SAMPLE10 s1 on s1.userId = u1.id
LEFT JOIN SAMPLE1 fj1 on f1.id = fj1.column1
LEFT JOIN SAMPLE8 c1 on fj1.cityId = c1.id
LEFT JOIN SAMPLE2 si1 on s1.column2 = si1.id
LEFT JOIN SAMPLE3 fss1 on fss1.column1 = f1.id
LEFT JOIN SAMPLE4 fs1 on fss1.column3 = fs1.id
INNER JOIN SAMPLE5 ff1 on f1.id = ff1.column1 AND ff1.column11 = blahblah
LEFT JOIN SAMPLE6 fl1 on u1.id = fl1.userId
INNER JOIN
(
SELECT ff2.column12, ff2.colume24 AS price, expiredAt
FROM SAMPLE5LCL fflcl1
WHERE column22 = 'blahblah' AND column23 = 'bbbb'
AND DATE_FORMAT(DATE_ADD(NOW(), INTERVAL 9 HOUR), '%Y-%m-%d') < expiredAt
)
fflcl1 on ff1.id = fflcl1.column24

중요 내용은 다 텍스트 대체했고 귀찮아서 뒤에 10줄은 다 적지 않아서 유효한 SQL문은 아니다. 다만 이런식의 쿼리를 만나니 정말 정신이 혼미했다… 여태까지 테이블 10개씩 조인하는 쿼리는 처음이었다. 자연의 위대함 앞에 선 인간의 심정이 이러할까 싶다. 이렇게 Join이 많은 쿼리는 그냥 그대로 Raw Query형태로 사용하기로 했고, 단순 findOne, findAll, Create, Update 정도만 Sequelize 를 사용하기로 결정했다. 이렇게 조인이 많으면 시퀄라이즈에서 쿼리 구성하는데 백 만년이 걸릴것 같았다. 중요한건 쿼리랑 그 타입 정보가 있는 결과값이지 그 형태가 중요한건 아니니까

TypeORM 도입도 생각했는데, 당시 백엔드 개발자가 나 혼자뿐이고 사용 경험이 없어서 그냥 익숙한 걸로 사용했다.

그 후

거의 90개의 테이블을 외주로부터 인수인계를 받았는데 받았는데 비즈니스 모델이 계속 변경됨에 따라 금방 100개가 넘어갔다. 솔직히 하는 일에 비해서 테이블 수가 너무 많았던지라, 얼마 전(11월 말)에 한 번 대대적인 리팩토링을 해서 현재는 70개선으로 유지 중이며 앞으로 20개를 살생부에 올려놓은 상황이다.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×