230419(수)
🎄 성장일지 4.0
책 행복한 이기주의자(웨인 다이어)
의 내용에 자극받아 시작하는 소박한 성장기록
살아있는 꽃과 죽은 꽃은 어떻게 구별하는가?<br/> 성장하고 있는 것이 살아 있는 것이다.<br/> 생명의 유일한 증거는 성장이다!
🌳 (1.0)키워드<br/> 최대한 간단하게 정리, 추후에 보면서 스스로 설명<br/> 🍉 (2.0)경험 위주로<br/> 단순 정보를 전달하기보다 무엇을 배웠고 어떻게 해결했는지 짧고 간단하게 작성<br/> ❄️ (3.0)정해진 템플릿에 맞춰서<br/> 키워드, 경험 모두 좋다. 다만 매일 작성하기로 마음 먹은만큼 핵심만 간결하게 정리할 수 있게 템플릿을 작성<br/> (3.1)230102부터 시작되는 학습에 관한 내용 추가<br/> (3.2)230313부터 좀더 경험, 감정 위주의 내용도 담기!<br/> 🌾 (4.0)학습 키워드에서 최대한 간단한 정보 제공, 고민에서 내 경험을 자세히 적자!<br/>
🧐 고민 사항
1. 프로젝트에서 전역으로 관리할 필요가 있는 상태들만 flux 아키텍쳐 적용할지.
기존에 내가 생각했던 방향은 컴포넌트 별로 구성하되 각각의 컴포넌트가 MVC, 옵저버, Flux 패턴으로 구현되는 것이었다. MVC와 옵저버까지는 그렇게 해도 되지만, Flux의 경우 굳이..? 라는 생각이 든다. 왜냐하면 Flux 아키텍쳐로 구현된 리덕스의 경우에도 리액트의 props drilling을 막기 위해서 상태를 전역으로 관리하게 해주는 역할이기 때문이다. 작은 컴포넌트 단위에서 Flux 패턴으로 구현하는 건 조금 소모적인 일같다. 해서 일단 MVC, 옵저버로 구현 후 전역으로 빼고 싶은 상태들만 Flux로 리팩토링하는 식으로 가도 좋을 것 같다.
2. 리팩토링을 할지 말지(구독 기능은 일단 keep)
지금 내가 구현한 컴포넌트들은 setState를 할 때, 새로운 html을 할당하고 event를 붙이는 방식이 아니다. 기존 tamplate html을 유지하면서 거기서 작은 dom 조작을 하는 느낌이라서 진짜 cra 느낌의 component가 아닌 것 같다. 해서 마침 리팩토링, 테스트 코드가 주제인만큼 이를 작성하면서 코드 전반적으로 리팩토링을 진행해보려 한다.
3. TS에서 jest 사용 시 import 문제(번들러 없음)
번들러 없이 ts를 사용할 때, esm을 사용하기 위해서는 import from 뒤의 파일에 반드시 컴파일되고 난 후의 js 파일을 가져와야만 했다. 여기까지는 크게 문제가 안되는데, ts config에서 path 설정을 해준 경우 마찬가지로 jest에서도 이 경로 단축 사실을 알려주어야 한다. 해서 이렇게 처리해주면 기존의 ts file에서는 esm 사용을 위해 끝에 '.js'를 붙이는데, jest 입장에서는 해당 경로에는 js 파일이 없으니 계속 에러가 발생했다. 그래서 결국엔 ts에 대한 테스트를 실행하지 않고 컴파일된 js 파일에 대해서 test를 진행하도록 하여 일단은 해결..!(근데 뭔가 찝찝...)
🔑 오늘의 학습 키워드
- flux 아키텍처
- 리팩토링과 테스트 코드
🥳 학습 내용
리팩토링을 위한 테스트 코드 작성(feat. Jest)
기존의 MVC, Observer pattern에서 Flux pattern으로 리팩토링하기에 앞서 테스트 코드부터 작성하고 연습해보았다.(고난길 가기 전 그나마 심적 대비ㅠㅋㅋ)
예시1) 한국 날짜 표기에 맞게 변경해주는 함수
import { KR_DAYS } from '@src/constants/constants.js'; export const getKrDate = (locale: string, todayDate: Date) => { const date = todayDate; const localeDate = date.toLocaleDateString(locale); const day = date.getDay(); return `${localeDate} ${KR_DAYS[day]}요일`; };
그에 대한 테스트코드<br/>
매일 변화하는 new Date()
때문에 하루가 지나면 테스트가 실패하게 된다. 이를 해결하기 위해서 mockDate를 잡아주고 이에 대해서 테스트를 진행토록 하였다.
import { getKrDate } from '@utils/date.js'; describe('Get date', () => { it('korean date', () => { const mockDate = new Date('2023.04.19'); expect(getKrDate('ko-KR', mockDate)).toEqual('2023. 4. 19. 수요일'); }); });
예시2) DOM 조작하는 함수(querySelector, querySelectorAll)
export const $ = ( selector: string, baseElement: Document | HTMLElement = document, ) => baseElement.querySelector(selector); export const $$ = ( selector: string, baseElement: Document | HTMLElement = document, ) => baseElement.querySelectorAll(selector);
import { $, $$ } from '@utils/dom.js'; import { JSDOM } from 'jsdom'; describe('Select DOM node', () => { const mockDom = new JSDOM(); global.document = mockDom.window.document; global.document.body.innerHTML = ` <div id="first" class="mock-element"></div> <div id="second" class="mock-element"></div> `; it('Select One - querySelector', () => { expect( ($('#first', global.document.body) as HTMLElement).outerHTML, ).toEqual(`<div id="first" class="mock-element"></div>`); }); it('Select All - querySelectorAll', () => { let mockHtml = ``; ($$('.mock-element', global.document.body) as NodeList).forEach((node) => { mockHtml += (node as HTMLElement).outerHTML; }); expect(mockHtml).toEqual( `<div id="first" class="mock-element"></div><div id="second" class="mock-element"></div>`, ); }); });
DOM과 관련한 테스트코드가 인상 깊었다. 먼저 jsdom 라이브러리를 통해 mocking된 dom을 만들 수 있다. mocking된 dom에서의 window나 document 등을 node의 global 객체 내부에 할당해준다. 그리고 우리가 브라우저에서 node(혹은 element)를 선택하여 다루듯 사용해주면 된다!
undefined