(21.09.07) Moment.js의 moment는 mutable하다

도깨비젤리

·

2021. 9. 7. 23:03

작은 지식이라도, 하루에 하나씩.


 

한 줄 요약


🦄Moment.js의 method들은 원본 객체를 훼손시킨다.(moment 객체들이 mutable하다.)🦄

 

* mutable과 immutable에 대해서 궁금하다면 여기로 ⬇

 

 

 

불변객체 - 위키백과, 우리 모두의 백과사전

객체 지향 프로그래밍에 있어서 불변객체(immutable object)는 생성 후 그 상태를 바꿀 수 없는 객체를 말한다. 반대 개념으로는 가변(mutable) 객체로 생성 후에도 상태를 변경할 수 있다. 객체 전체가

ko.wikipedia.org

 

 

본문


글을 시작하기 앞서, 본인의 은사님이 알려주신 지식을 공유하겠습니다.

 

Eric 교수님 최고

 

moment 객체가 mutable 하기 때문에 사용하지 말라는 말씀을 하셨는데, 이 글을 볼 당시만 해도 나는 moment.js를 써본 적이 없기에 "아 그렇구나~"하고만 있었다.

 

근데 참 사람 일이라는게 기구하다. 회사에서는 moment.js를 핵심 라이브러리로 쓰고 있으니까 말이다.

 

그래서 moment.js를 어찌어찌 배워서 쓰고 있었는데, (아쉽게도 moment.js의 단점을 개발팀한테 피력할 기회는 가지지 못했다😁😁😁) 오늘 큰 사건이 하나 터졌다.

 

 

나는 지금 회사에서 월별로 정리된 데이터들을 화면에 출력하고, ant-design의 datepicker를 변경하면 mobx로 관리하는 currentMonth라는 moment 객체가 바뀌면서 새로운 데이터가 화면에 랜더링 되는 페이지를 만들고 있다.

 

근데 엥?? datepicker로 currentMonth를 바꾸니까, 찍은 날짜에서 -2月가 된 날짜가 선택되는 것이다!!

 

 

 

21/09 선택 --> 화면에는 21/07 출력

 

 

 

아주 미치고 팔짝 뛸 노릇이였다. mobx 개발자 도구도 켜보고, 콘솔 창도 켜서 이리 찍고 저리 찍고 몇 시간 동안 삽질을 한 결과, render 이전에는 정상적으로 currentMonth가 설정되다가, render 단계에서 갑자기 날짜가 -1月씩 변하는 것을 확인할 수 있었다!!

 

render 부를 좀 더 자세히 뜯어본 결과. 범인을 찾을 수 있었다. 범인은 바로, currentMonth 이전 달을 표시하기 위해 변수화 했던 currentMonth.subtract(1,"months")였다.

 

 

render(){
//...전략

const {currentMonth} = this.blurblurStore // moment.Moment

const lastMonth = currentMonth.subtract(1,'months') //여기서 currentMonth가 변형된다

//...후략
}

 

최초 랜더시에는 currentMonth가 정상적인 값을 가지고 있었으나, 랜더부가 실행됨과 동시에 currentMonth.subtract(1,'months')가 실행되어 currentMonth의 값을 바꾸게 된것이다. 자세한 연유는 모르지만, 컴포넌트를 불러오면서 render가 한번 더 실행되면서 또 한번 currentMonth.subtract(1,'months')가 실행되면서 화면에 보여지는 currentMonth는 실제 값보다 -2月이 된 값이 된것이다.

 

 

범인을 알았으니, 이제 체포만 하면 되겠다.

원본만 바꾸지 않으면 되므로, 원본과 동일한 값을 가진 moment 인스턴스를 생성하여 조작하면 되겠다.

 

render(){
//...전략

const {currentMonth} = this.blurblurStore // moment.Moment

const lastMonth = moment(currentMonth).subtract(1,'months') //여기서 currentMonth가 변형된다

//...후략
}

 

moment를 call할 때 params로 moment 객체 자체를 받을 수도 있는데, 이렇게 하면 params와 같은 값을 가진 새로운 moment 객체를 만들어준다. 

 

currentMonth는 mobx에 의해 관측되고 있고, 매 랜더마다 새로 할당되기 때문에, currentMonth가 바뀔 때마다 lastMonth도 currentMonth에 맞는 value를 가지게 된다.

 

 

해결하고 보니 엄청 사소한 문제인데, 이거 잡을라고 쓴 시간이 너무 길었다.

그래도 해결한게 어디냐만은....시간이 너무 아깝다는 생각이 드는 건 어쩔 수 없나보다. 계속해서 정진해야겠다