외부 코드를 함부로 상속하지 마세요(feat. Sequelize)

손정우·2021년 3월 22일
0
post-thumbnail

상황

Node 기반의 프로젝트를 진행하던 중 DB에 접근해야하는 상황이 생겨서 ORM 라이브러리인 Sequelize를 사용했다.

그러던 중 DB에서 주는 값을 변형시켜 객체로 옮겨야 할 경우가 생겼다. 예를 들면 DB에서 시간을 저장하는데 이를 객체 단계에서는 Luxon과 같은 시간 관련 라이브러리에서 지원하는 객체로 변경시키고 싶을 때이다.

하지만 Sequelize에서 기본적으로 제공하는 모델의 생성자를 변경할 수는 없었다.

따라서 Repository 계층에서 쿼리 질의후 나온 Sequelize의 모델을 내가 정의한 모델로 변경하고자 했다.
예시로 아래와 같은 test 테이블로 코드를 짰다.

그리고 아래와 같이 호출했다.

오류

결과는 아래와 같다.

(node:2208) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'uuid' of undefined
    at Query._logQuery (C:\Users\user\Desktop\s\node_modules\sequelize\lib\dialects\abstract\query.js:348:32)
    at Query.run (C:\Users\user\Desktop\s\node_modules\sequelize\lib\dialects\mysql\query.js:36:27)
    at C:\Users\user\Desktop\s\node_modules\sequelize\lib\sequelize.js:619:28
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async MySQLQueryInterface.select (C:\Users\user\Desktop\s\node_modules\sequelize\lib\dialects\abstract\query-interface.js:938:12)
    at async Function.findAll (C:\Users\user\Desktop\s\node_modules\sequelize\lib\model.js:1753:21)
    at async Function.findAll (C:\Users\user\Desktop\s\app.js:40:33)
    at async Function.findOne (C:\Users\user\Desktop\s\node_modules\sequelize\lib\model.js:1917:12)
    at async Function.findByPk (C:\Users\user\Desktop\s\node_modules\sequelize\lib\model.js:1883:12)
    at async Function.findById (C:\Users\user\Desktop\s\app.js:45:32)

분석

이러한 오류가 난 것은 Sequelize에서는 내부적으로 findByPkfindOne을, 그리고 findOnefindAll을 호출한다.

그런데 내가 findAll을 오버라이딩해버렸기 때문에 Sequelize의 findAll이 아니라 내가 정의한 findAll이 호출됐다. 그 결과 코드가 정상적으로 작동하지 못하고 예외를 던진 것이다.

이를 알고 나서는 당황했고 어이가 없기도 했다. 솔직히 Sequelize 탓을 하기도 했다.

그러나 외부의 코드를 상속한 내 잘못이 큰 것도 사실이다.

외부의 코드를 함부로 상속해 그 기능을 바꾸는 것은 내가 그 외부의 코드를 잘 아는 것이 아니므로 예상치 못한 동작을 하도록 만들 수 있다. 또한 운좋게 그러한 점을 피해갔다고 해도 내 코드는 외부의 코드에 상당히 종속적이게 된다.

따라서 외부의 코드를 상속하는 것은 피해야하며 요즘은 그 대안으로 Component 방식을 사용하는 것을 권장한다.

0개의 댓글