πŸŽ„ μ„±μž₯일지 4.0

μ±… ν–‰λ³΅ν•œ 이기주의자(웨인 닀이어)의 λ‚΄μš©μ— μžκ·Ήλ°›μ•„ μ‹œμž‘ν•˜λŠ” μ†Œλ°•ν•œ μ„±μž₯기둝

μ‚΄μ•„μžˆλŠ” 꽃과 죽은 꽃은 μ–΄λ–»κ²Œ κ΅¬λ³„ν•˜λŠ”κ°€?
μ„±μž₯ν•˜κ³  μžˆλŠ” 것이 μ‚΄μ•„ μžˆλŠ” 것이닀.
생λͺ…μ˜ μœ μΌν•œ μ¦κ±°λŠ” μ„±μž₯이닀!

🌳 (1.0)ν‚€μ›Œλ“œ
μ΅œλŒ€ν•œ κ°„λ‹¨ν•˜κ²Œ 정리, 좔후에 λ³΄λ©΄μ„œ 슀슀둜 μ„€λͺ…
πŸ‰ (2.0)κ²½ν—˜ μœ„μ£Όλ‘œ
λ‹¨μˆœ 정보λ₯Ό μ „λ‹¬ν•˜κΈ°λ³΄λ‹€ 무엇을 λ°°μ› κ³  μ–΄λ–»κ²Œ ν•΄κ²°ν–ˆλŠ”μ§€ 짧고 κ°„λ‹¨ν•˜κ²Œ μž‘μ„±
❄️ (3.0)정해진 ν…œν”Œλ¦Ώμ— λ§žμΆ°μ„œ
ν‚€μ›Œλ“œ, κ²½ν—˜ λͺ¨λ‘ μ’‹λ‹€. λ‹€λ§Œ 맀일 μž‘μ„±ν•˜κΈ°λ‘œ 마음 λ¨Ήμ€λ§ŒνΌ ν•΅μ‹¬λ§Œ κ°„κ²°ν•˜κ²Œ 정리할 수 있게 ν…œν”Œλ¦Ώμ„ μž‘μ„±
(3.1)230102λΆ€ν„° μ‹œμž‘λ˜λŠ” ν•™μŠ΅μ— κ΄€ν•œ λ‚΄μš© μΆ”κ°€
(3.2)230313λΆ€ν„° 쒀더 κ²½ν—˜, 감정 μœ„μ£Όμ˜ λ‚΄μš©λ„ λ‹΄κΈ°!
🌾 (4.0)ν•™μŠ΅ ν‚€μ›Œλ“œμ—μ„œ μ΅œλŒ€ν•œ κ°„λ‹¨ν•œ 정보 제곡, κ³ λ―Όμ—μ„œ λ‚΄ κ²½ν—˜μ„ μžμ„Ένžˆ 적자!

🧐 κ³ λ―Ό 사항

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]}μš”μΌ`;
};

그에 λŒ€ν•œ ν…ŒμŠ€νŠΈμ½”λ“œ
맀일 λ³€ν™”ν•˜λŠ” 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)λ₯Ό μ„ νƒν•˜μ—¬ 닀루듯 μ‚¬μš©ν•΄μ£Όλ©΄ λœλ‹€!