Amelia-Shin ๋‹˜์˜ ์ƒ์„ธํŽ˜์ด์ง€ ๏ผž [1ํŒ€ ์‹ ํฌ์›] Chapter ๐Ÿงฆ 3-1. ํ”„๋ก ํŠธ์—”๋“œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๐Ÿงฆ

Medium

7์ฃผ์ฐจ ๊ณผ์ œ ์ฒดํฌํฌ์ธํŠธ

๊ธฐ๋ณธ๊ณผ์ œ

Medium

  • ์ด 11๊ฐœ์˜ ํŒŒ์ผ, 115๊ฐœ์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ๋ฌด์‚ฌํžˆ ์ž‘์„ฑํ•˜๊ณ  ํ†ต๊ณผ์‹œํ‚จ๋‹ค.

์งˆ๋ฌธ

Q. medium.useEventOperations.spec.tsx > ์•„๋ž˜ toastFn๊ณผ mock๊ณผ ์ด fn์€ ๋ฌด์—‡์„ ํ•ด์ค„๊นŒ์š”?

toastFn : ์‹ค์ œ ํ† ์ŠคํŠธ๋ฅผ ํ‘œ์‹œํ•˜์ง€ ์•Š๊ณ , ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€๋งŒ ๊ธฐ๋ก mock (notistack) : ์‹ค์ œ notistack ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—†์–ด๋„ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ const enqueueSnackbarFn = vi.fn(); : ๊ฐ€์งœ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ์„ ์ถ”์ ํ•˜๊ณ  ๊ธฐ๋ก

Q. medium.integration.spec.tsx > ์—ฌ๊ธฐ์„œ ChakraProvider๋กœ ๋ฌถ์–ด์ฃผ๋Š” ๋™์ž‘์€ ์˜๋ฏธ์žˆ์„๊นŒ์š”? ์žˆ๋‹ค๋ฉด ์–ด๋–ค ์˜๋ฏธ์ผ๊นŒ์š”?

ThemeProvider (ํ…Œ๋งˆ ์ œ๊ณต) SnackbarProvider (ํ† ์ŠคํŠธ ์‹œ์Šคํ…œ) CssBaseline (๊ธฐ๋ณธ ์Šคํƒ€์ผ ์ดˆ๊ธฐํ™”)

์ปดํฌ๋„ŒํŠธ๋“ค์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๊ธฐ ์œ„ํ•จ (Provider๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋ง์ด ๋˜์ง€๋งŒ ๊ธฐ๋Šฅ์€ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Œ)

Q. handlersUtils > ์•„๋ž˜ ์—ฌ๋Ÿฌ๊ฐ€์ง€ use ํ•จ์ˆ˜๋Š” ์–ด๋–ค ์—ญํ• ์„ ํ• ๊นŒ์š”? ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์„๊นŒ์š”?

๊ฐ ์ด๋ฒคํŠธ ์ƒ์„ฑ/์ˆ˜์ •/์‚ญ์ œ๋ฅผ ์œ„ํ•œ mock API๋ฅผ ์„ค์ •ํ•˜์—ฌ, ํ…Œ์ŠคํŠธ ์‹œ์ž‘ ์ „์— ํ•„์š”ํ•œ mock ํ™˜๊ฒฝ์„ ๊ตฌ์„ฑํ• ์ˆ˜์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ์งœ์—ฌ์ ธ ์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ๋‹ค ์“ฐ๋Š”๊ฑฐ์˜€์ง€๋งŒ ๋ฏธ๋””์›€์—์„œ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.. ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ ์‹ค์ œ API๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ์— ๋„ˆ๋ฌด ๋งŽ์€ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค๊ณ , ์‹ค์ œ ์„œ๋ฒ„ ๋Œ€์‹  ๊ฐ€์งœ ์„œ๋ฒ„์™€ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ๋” ๋น ๋ฅธ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

Q. setupTests.ts > ์™œ ์ด ์‹œ๊ฐ„์„ ์„ค์ •ํ•ด์ฃผ๋Š” ๊ฑธ๊นŒ์š”?

vi.setSystemTime์œผ๋กœ ๊ณ ์ •๋œ ์‹œ๊ฐ„์„ ์„ค์ •ํ•˜์—ฌ ๋‚ ์งœ/์‹œ๊ฐ„ ์˜์กด ๋กœ์ง์ด ํ•ญ์ƒ ์ผ๊ด€๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด์„œ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์žฅ์  : ํ…Œ์ŠคํŠธ์˜ ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ๊ณผ ์žฌํ˜„์„ฑ์„ ๋ณด์žฅ!

์‹ฌํ™” ๊ณผ์ œ

  • App ์ปดํฌ๋„ŒํŠธ ์ ์ ˆํ•œ ๋‹จ์œ„์˜ ์ปดํฌ๋„ŒํŠธ, ํ›…, ์œ ํ‹ธ ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ–ˆ๋Š”๊ฐ€?
  • ํ•ด๋‹น ๋ชจ๋“ˆ๋“ค์— ๋Œ€ํ•œ ์ ์ ˆํ•œ ํ…Œ์ŠคํŠธ๋ฅผ 5๊ฐœ ์ด์ƒ ์ž‘์„ฑํ–ˆ๋Š”๊ฐ€?

๊ณผ์ œ ์…€ํ”„ํšŒ๊ณ 

TMI. Hard ์ง„ํ–‰ํ•˜๋‹ค๊ฐ€ ์ปค๋ฐ‹ํ•˜์ง€ ์•Š์€ ํŒŒ์ผ๋“ค์ด ๋‹ค ๋‚ ๋ผ๊ฐ”์–ด์š”.. ์™œ ๋‚ ๋ผ๊ฐ”๋ƒ๋ฉด.... ํ‘ธ์‰ฌ๋ฅผ ํ–ˆ๋”๋‹ˆ off์ฝ”์น˜๋‹˜ ์ฝ”๋“œ์— ํ‘ธ์‰ฌ๊ฐ€ ๋˜์—ˆ๊ณ , ์•„๋ž˜ ๋ช…๋ น์–ด ์‹คํ–‰ํ–ˆ๋”๋‹ˆ ์ˆ˜์ •ํ•œ ํŒŒ์ผ๋“ค์ด ๋‹ค ๋‚ ๋ผ๊ฐ”์–ด์š” ^0^ ์Šคํ…Œ์ด์ง•์— ์•ˆ์˜ฌ๋ ค๋‘” ์ œ ์ž˜๋ชป.... ์•ž์œผ๋กœ reset ์กฐ์‹ฌํ•˜์ž....

# 1. ๋กœ์ปฌ์—์„œ ๋งˆ์ง€๋ง‰ ์ปค๋ฐ‹๊ณผ ๋ณ€๊ฒฝ์‚ฌํ•ญ ๋ชจ๋‘ ์‚ญ์ œ (hard reset)
git reset --hard HEAD~1

# 2. ์›๊ฒฉ์—์„œ๋„ ์‚ญ์ œ
git push origin +HEAD

๊ฐ‘์ž๊ธฐ ์˜์š• ๋‹ค ๊บพ์ด๊ณ  ์‹œ๊ฐ„๋ฌธ์ œ๋กœ ๋ฏธ๋””์›€์œผ๋กœ ๋‚ด๋ ค์™”์Šต๋‹ˆ๋‹ค... (๊ทธ๋ž˜๋„...๊ณผ์ œ 2๋ฒˆ ๋ฐ˜๋ณตํ•™์Šตํ• ์ˆ˜์žˆ์–ด์„œ ์ข‹-์•„- ^o^)

๊ธฐ์ˆ ์  ์„ฑ์žฅ

  • ์—๋Ÿฌ ๋‚œ๋‹ค๊ณ  AIํ•œํ…Œ๋งŒ ์˜์กดํ•˜์ง€๋ง์ž...

MUI Icons ๊ฐ„๋‹จ ๋ชจํ‚น ์ด ๋ถ€๋ถ„์„ AI๊ฐ€ ๊ณ ์ณ์คฌ๋Š”๋ฐ, ์™œ ์ €๊ฒŒ ํ•„์š”ํ•œ์ง€ ์ง„์งœ ์ดํ•ดํ•  ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋„ˆ๋ฌด ์“ฐ๊ธฐ ์‹ซ์—ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‚˜๋Š” ๊ตฌ๊ธ€๋ง์„ ํ•ด์•ผ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์„ ํ•˜์ง€์•Š๊ณ  AIํ•œํ…Œ ์—๋Ÿฌ๋ฅผ ๊ณ ์ณ๋‹ฌ๋ผ๊ณ  ํ–ˆ์ง€๋งŒ ๊ณ ์น˜๋ฉด ๊ณ ์น ์ˆ˜๋ก ์ด์ƒํ•˜๊ณ  ์—ฌ์ „ํžˆ ์—๋Ÿฌ๋Š” ์‚ฌ๋ผ์ง€์ง€ ์•Š์•˜๋‹ค.

์ฒ˜์Œ์— ์ง  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

import { render, screen } from '@testing-library/react';

/* ์ด๊ฑฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ EMFILE ์—๋Ÿฌ ๋ฐœ์ƒ X
// MUI Icons ๊ฐ„๋‹จ ๋ชจํ‚น
vi.mock('@mui/icons-material', () => ({
  ChevronLeft: () => null,
  ChevronRight: () => null,
  Notifications: () => null,
}));
*/

import { CalendarView } from '../../components/calendar/CalendarView';
import { createMockEvents } from '../utils';

const renderCalendarView = (props: Parameters<typeof CalendarView>[0]) =>
  render(<CalendarView {...props} />);

describe('CalendarView', () => {
  const mockEvents = createMockEvents();

  const mockHolidays = {
    '2025-01-01': '์‹ ์ •',
    '2025-01-15': '์„ค๋‚ ',
  };

  const mockSetView = vi.fn();
  const mockNavigate = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
  });
  it('Week์ด ์„ ํƒ๋˜์—ˆ์„ ๋•Œ ํ•ด๋‹น ๋‚ ์งœ์˜ ์ฃผ๊ฐ„ ์ผ์ •์ด ๋ Œ๋”๋ง๋œ๋‹ค', () => {
    renderCalendarView({
      view: 'week',
      setView: mockSetView,
      currentDate: new Date('2025-01-15'),
      navigate: mockNavigate,
      filteredEvents: mockEvents,
      notifiedEvents: [],
      holidays: mockHolidays,
    });

    expect(screen.getByTestId('week-view')).toBeInTheDocument();
    expect(screen.queryByTestId('month-view')).not.toBeInTheDocument();
  });

๊ฒฐ๊ตญ ๊ตฌ๊ธ€๋ง์„ ํ•ด์„œ ์ฐพ์€ ๋ฐฉ๋ฒ•!!! https://github.com/mui/material-ui/issues/46324

-import { LocationCity } from "@mui/icons-material";
+import LocationCity from "@mui/icons-material/LocationCity";

๋ช‡์‹œ๊ฐ„๋™์•ˆ ์‚ฝ์งˆํ–ˆ๋Š”๋ฐ.... ๋‹ค์Œ๋ถ€ํ„ฐ ์ ˆ๋Œ€ ๋˜‘๊ฐ™์€ ์—๋Ÿฌ๋ฅผ ๋ณด๋”๋ผ๋„ AIํ•œํ…Œ ๊ณ ์ณ๋‹ฌ๋ผ๋Š”๋‘ฅ ์‹œ๊ฐ„๋‚ญ๋น„ํ•˜์ง€๋ง์ž.

์ฝ”๋“œ ํ’ˆ์งˆ

์—†์Šต๋‹ˆ๋‹ค.

ํ•™์Šต ํšจ๊ณผ ๋ถ„์„

  • act ์™€ waitFor act, waitFor ๊ฐ™์€ ๋„๊ตฌ๊ฐ€ ๋น„๋™๊ธฐ ๋กœ์ง๊ณผ UI ์—…๋ฐ์ดํŠธ๋ฅผ ์ œ์–ดํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

act ์™€ waitFor์˜ ์ฐจ์ด์ 

act๋Š” ๋™๊ธฐ, ๋น„๋™๊ธฐ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ waitFor์€ ํ•ญ์ƒ ๋น„๋™๊ธฐ

act์™€ waitFor์€ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ข‹์„๊นŒ?

// ๋™๊ธฐ act - ํƒ€์ด๋จธ ์ฆ‰์‹œ ์ง„ํ–‰
act(() => {
   vi.advanceTImersByTime(1000);
});

// waitFor - ์‹ค์ œ๋กœ ์‹œ๊ฐ„์ด ํ˜๋Ÿฌ์•ผ ํ•จ
  await waitFor(() => {
    expect(screen.getByText('1์ดˆ ์ง€๋‚จ')).toBeInTheDocument();
  }, { timeout: 2000 });

๊ณผ์ œ ํ”ผ๋“œ๋ฐฑ

easy ํ…Œ์ŠคํŠธ ์ž‘์„ฑ๋„ ์žฌ๋ฐŒ์—ˆ๊ณ , ํ†ตํ•ฉํ…Œ์ŠคํŠธ๋Š” ์ฒ˜์Œ์— ์ข€ ๋ง‰๋ง‰ํ–ˆ์ง€๋งŒ ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ํ•˜๋‚˜์”ฉ ํ•ด๋ณด๋‹ˆ ์˜คํžˆ๋ ค easy๋ณด๋‹ค ๋” ์žฌ๋ฐŒ์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ๋ทฐ ๋ฐ›๊ณ  ์‹ถ์€ ๋‚ด์šฉ

Q1. ์ €๋Š” ์•„๋ž˜ ์ฝ”๋“œ์—์„œ 2๋ฒˆ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™”๋Š”๋ฐ์š”. ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ๋ฒ• ์ค‘์— ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•๋„ ์žˆ๋Š”๋ฐ ๋ณดํ†ต 1๋ฒˆ ๋ฐฉ๋ฒ•์€ ์–ธ์ œ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

it('์ €์žฅ๋˜์–ด์žˆ๋Š” ์ดˆ๊ธฐ ์ด๋ฒคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ๋ถˆ๋Ÿฌ์˜จ๋‹ค', async () => {
  setupMockHandlerCreation(events);
  const { result } = renderHook(() => useEventOperations(false));
 
//  1๋ฒˆ ๋ฐฉ๋ฒ•
   await act(async () => {
     await new Promise((resolve) => setTimeout(resolve, 0));
   });

// 2๋ฒˆ ๋ฐฉ๋ฒ•
  await act(async () => {
    await result.current.fetchEvents();
  });

  expect(result.current.events).toEqual(events);
  expect(enqueueSnackbarFn).toHaveBeenCalledWith('์ผ์ • ๋กœ๋”ฉ ์™„๋ฃŒ!', { variant: 'info' });
});

Q2. ์˜๋ฏธ์žˆ๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ์ค€์ด ์–ด๋–ค๊ฒƒ์ธ์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ผ ํ…Œ์ŠคํŠธ์—์„œ ๊ตณ์ด ์ด๋Ÿฐ ๋‚ด์šฉ๊นŒ์ง€ ํ…Œ์ŠคํŠธ์— ๋„ฃ์–ด์•ผํ•˜๋‚˜? ์‹ถ์—ˆ๋˜๊ฒŒ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ)

  it.skip('์œ ํšจํ•˜์ง€ ์•Š์€ ์›”์— ๋Œ€ํ•ด ์ ์ ˆํžˆ ์ฒ˜๋ฆฌํ•œ๋‹ค', () => {
    expect(getDaysInMonth(2025, 13)).toBe(31);
  });

it.skip('size ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ƒ๋žตํ•˜๋ฉด ๊ธฐ๋ณธ๊ฐ’ 2๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค', () => {
    expect(fillZero(1)).toBe('01');
  });

๊ทธ๋ฆฌ๊ณ  ์˜๋ฏธ์žˆ๋Š” ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„  ์–ด๋–ค๊ฑธ ํ•˜๋ฉด ์ข‹์„๊นŒ์š”?

๊ณผ์ œ ํ”ผ๋“œ๋ฐฑ

์ˆ˜๊ณ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ณผ์ œ๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•๋“ค์„ ์ ‘ํ•˜๋ฉด์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ผ๋Š” ๊ทธ ์‹ฌ๋ฆฌ์  ์žฅ๋ฒฝ์„ ํ—ˆ๋ฌผ๊ณ  ์นœ์ˆ™ํ•ด์ง€๋Š”๋ฐ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

"Hard ์ง„ํ–‰ํ•˜๋‹ค๊ฐ€ ์ปค๋ฐ‹ํ•˜์ง€ ์•Š์€ ํŒŒ์ผ๋“ค์ด ๋‹ค ๋‚ ๋ผ๊ฐ”์–ด์š”.. ^0^" ... ๋‚ด๊ฐ€ ์›ƒ๋Š”๊ฒŒ ์›ƒ๋Š”๊ฒŒ ์•„๋‹ˆ์•ผ.. ใ…  ์•„์ด๊ณ ... ์ •๋ง ๊ณ ์ƒ ๋งŽ์œผ์…จ๋„ค์š”. git reset --hard๋Š” ์ •๋ง ์กฐ์‹ฌํ•ด์•ผ ํ•˜๋Š” ๋ช…๋ น์–ด์ธ๋ฐ ใ… ใ…  ๊ทธ๋ž˜๋„ ๋ฏธ๋””์›€์œผ๋กœ ๋‹ค์‹œ ํ•ด๋ณด๋ฉด์„œ ๋ฐ˜๋ณตํ•™์Šตํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ข‹์•˜๋‹ค๊ณ  ํ•˜๋‹ˆ ๊ธ์ •์ ์œผ๋กœ ์ƒ๊ฐํ•˜๋Š” ๋ชจ์Šต์ด ๋Œ€๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋ฉ‹์ง‘๋‹ˆ๋‹ค!!

"๊ฒฐ๊ตญ ๊ตฌ๊ธ€๋ง์„ ํ•ด์„œ ์ฐพ์€ ๋ฐฉ๋ฒ•!!! ๋ช‡์‹œ๊ฐ„๋™์•ˆ ์‚ฝ์งˆํ–ˆ๋Š”๋ฐ.... ๋‹ค์Œ๋ถ€ํ„ฐ ์ ˆ๋Œ€ ๋˜‘๊ฐ™์€ ์—๋Ÿฌ๋ฅผ ๋ณด๋”๋ผ๋„ AIํ•œํ…Œ ๊ณ ์ณ๋‹ฌ๋ผ๋Š”๋‘ฅ ์‹œ๊ฐ„๋‚ญ๋น„ํ•˜์ง€๋ง์ž" ์•„์ฃผ ์†Œ์ค‘ํ•œ ๊ฒฝํ—˜์ด์—ˆ๋„ค์š”! AI๋„ ์ข‹์€ ๋„๊ตฌ์ง€๋งŒ ๊ฒฐ๊ตญ ๋ณธ์งˆ์ ์ธ ๋ฌธ์ œ ํ•ด๊ฒฐ ๋Šฅ๋ ฅ์€ ์ง์ ‘ ์ฐพ์•„๋ณด๊ณ  ์ดํ•ดํ•˜๋Š” ๊ณผ์ •์—์„œ ๋‚˜์˜ค๋Š” ๊ฑฐ์ฃ . ์ด๋Ÿฐ ์‚ฝ์งˆ ๊ฒฝํ—˜์ด ์‹ค๋ ฅ ํ–ฅ์ƒ์— ๋” ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ์ตœ๊ทผ์— ๋А๋‚€ ํ•˜๋‚˜์˜ ํŒ์ด ์žˆ๋‹ค๋ฉด ๋‚ด๊ฐ€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ AI๋ฅผ ์ผ์„๋•Œ ๋‹ต์ด ์ˆ˜๋ ด๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด AI๊ฐ€ ๋ฐฉํ–ฅ์„ฑ์„ ์ œ๋Œ€๋กœ ์งš์ง€ ๋ชปํ•œ๊ฑฐ๊ตฌ๋‚˜ ํ•˜๋Š” ์ง•์กฐ๋กœ ๋А๋‚„ ์ˆ˜ ์žˆ๋”๋ผ๊ตฌ์š”. ใ…Ž

"easy ํ…Œ์ŠคํŠธ ์ž‘์„ฑ๋„ ์žฌ๋ฐŒ์—ˆ๊ณ , ํ†ตํ•ฉํ…Œ์ŠคํŠธ๋Š” ์ฒ˜์Œ์— ์ข€ ๋ง‰๋ง‰ํ–ˆ์ง€๋งŒ ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ํ•˜๋‚˜์”ฉ ํ•ด๋ณด๋‹ˆ ์˜คํžˆ๋ ค easy๋ณด๋‹ค ๋” ์žฌ๋ฐŒ์—ˆ์Šต๋‹ˆ๋‹ค" ๋งž์Šต๋‹ˆ๋‹ค. ์œ ๋‹›ํ…Œ์ŠคํŠธ๋Š” ๋‚ด๊ฐ€ ํ•จ์ˆ˜๋งŒ ์ž˜ ๋งŒ๋“ค์–ด ๋‘๋ฉด ์ด์ œ AI๊ฐ€ ๋š๋”ฑ ๋งŒ๋“ค์–ด์ค„ ์ •๋„๋กœ ์‰ฌ์šด ์˜์—ญ์ด์ฃ . ํ†ตํ•ฉํ…Œ์ŠคํŠธ๋Š” ์ƒํƒœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ธฐํš์„œ์™€ ์ฝ”๋”ฉ์„ ๋งž์ถฐ๊ฐ€๋Š” ์žฌ๋ฏธ๊ฐ€ ์žˆ์ง€์š”!

Q1) ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ๋ฒ• ์ค‘์— 1๋ฒˆ ๋ฐฉ๋ฒ•์€ ์–ธ์ œ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

=> 1๋ฒˆ ๋ฐฉ๋ฒ•(setTimeout(resolve, 0))์€ "๋‹ค์Œ ์ด๋ฒคํŠธ ๋ฃจํ”„"๋กœ ๋„˜์–ด๊ฐ€๋ฉด์„œ pending ์ƒํƒœ์˜ Promise๋“ค์ด resolve๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฐฉ์‹์ด์—์š”. ์ฃผ๋กœ useEffect๋‚˜ ๋น„๋™๊ธฐ ์ž‘์—…์ด ์ž๋™์œผ๋กœ ์‹คํ–‰๋˜๋Š” ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

=> 2๋ฒˆ ๋ฐฉ๋ฒ•์€ ๋ช…์‹œ์ ์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฑฐ๊ณ ์š”. ๋” ๋ช…ํ™•ํ•˜๊ณ  ์˜๋„๊ฐ€ ๋ถ„๋ช…ํ•˜๊ธฐ ๋•Œ๋ฌธ์— 2๋ฒˆ ๋ฐฉ๋ฒ•์ด ์ผ๋ฐ˜์ ์œผ๋กœ ๋” ์ข‹์•„์š”. 1๋ฒˆ ๋ฐฉ๋ฒ•์€ "๋ญ”๊ฐ€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋  ๊ฒƒ ๊ฐ™์€๋ฐ ์ •ํ™•ํžˆ ์–ธ์ œ ์‹คํ–‰๋ ์ง€ ๋ชจ๋ฅผ ๋•Œ" ์‚ฌ์šฉํ•˜๋Š” ์ผ์ข…์˜ ํ•ดํ‚น ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค.

Q2) ์˜๋ฏธ์žˆ๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ์ค€์ด ์–ด๋–ค๊ฒƒ์ธ์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

=> ์ œ์ผ ์ค‘์š”ํ•œ๊ฑด desc์— ์“ฐ๋Š” ํ…Œ์ŠคํŠธ์˜ ์˜๋„, ์ฆ‰ ์š”๊ตฌ์‚ฌํ•ญ์— ๊ธฐ๋ฐ˜ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐํš์„œ์— ํ•ด๋‹นํ•˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ์ด ์žˆ์—ˆ๋‹ค๋ฉด ๋„ˆ๋ฌด ๋ป”ํ•˜๋‹ค๊ณ  ํ• ์ง€๋ผ๋„ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋Š”๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค.

=> ์ด๋ฒˆ์— ๋ณด์—ฌ์ค€ ์˜ˆ์‹œ์—์„œ๋Š” ๊ฒฝ๊ณ„๊ฐ’์˜ ํ…Œ์ŠคํŠธ์ธ๋ฐ ๋‹ฌ๋ ฅ์œผ๋กœ ์ž…๋ ฅ์„ ๋ฐ›๋Š” Form์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์‚ฌ์‹ค ๊ฒฝ๊ณ„๊ฐ’๋“ฑ์€ ํฌ๊ฒŒ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๊ฒ ์ง€๋งŒ, ์ฝ”๋“œ๋กœ ์ž…๋ ฅํ•˜๋Š” ์—‘์…€๊ฐ™์€๊ฑฐ์˜€๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ๊ฒ€์ฆ์„ ํ•ด์•ผ๊ฒ ์ง€์š”. ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ ํ•ด๋‹น ์š”๊ตฌ์‚ฌํ•ญ์ด ํ‹€๋ฆด ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์ธ์ง€ ์•„๋‹Œ์ง€, ๊ทธ๋ž˜์„œ ๊ธฐํš์ƒ์—์„œ ์š”๊ตฌ์‚ฌํ•ญ์— ๋ช…์„ธ๋ฅผ ๋‹ด์•„ํ•  ์ •๋„๋ผ๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋Š”๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค.

=> ๊ทธ๋ž˜์„œ ์ •๋ฆฌํ•˜์ž๋ฉด 1) ๊ธฐํš๊ด€์ ์—์„œ ์š”๊ตฌ์‚ฌํ•ญ ๊ด€์ ์—์„œ ์ค‘์š”ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์ธ๊ฐ€? 2) ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๋กœ ์ธํ•ด์„œ ์‹ค์ œ๋กœ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์ธ๊ฐ€? 3) ์ด ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๋ฉด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š”๊ฐ€? ํ˜น์€ ๋ฌด์–ธ๊ฐ€ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ๊ฐ€? ์ด๋Ÿฐ ๊ธฐ์ค€์œผ๋กœ ํŒ๋‹จํ•ด๋ณด์„ธ์š”.

๊ณ ์ƒ ๋งŽ์œผ์…จ๊ณ , ์ด๋Ÿฐ ์‹œํ–‰์ฐฉ์˜ค ๊ฒฝํ—˜๋“ค์ด ๋‚˜์ค‘์— ๋” ํฐ ์ž์‚ฐ์ด ๋  ๊ฑฐ์˜ˆ์š”. ๋‹ค์Œ์ฃผ ๊ณผ์ œ๋„ ํ™”์ดํŒ…์ž…๋‹ˆ๋‹ค!