From e0f3ec6b08bba658ebbf9fdb67ca9e90a6c1060c Mon Sep 17 00:00:00 2001 From: mokjakA Date: Mon, 10 Aug 2026 01:12:33 +0900 Subject: [PATCH] =?UTF-8?q?feat(S15P11A705-432):=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EB=B8=8C=EB=9E=9C=EB=93=9C=20=EB=A1=9C=EA=B3=A0=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 5 +- .../home/components/HomeSheetPanels.test.tsx | 39 ++++++++++ .../home/components/HomeSheetPanels.tsx | 9 +++ src/pages/LoginPage.test.tsx | 78 +++++++++++++++++++ src/pages/LoginPage.tsx | 17 ++-- 5 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 src/features/home/components/HomeSheetPanels.test.tsx create mode 100644 src/pages/LoginPage.test.tsx diff --git a/index.html b/index.html index 6af003d..fc90aaa 100644 --- a/index.html +++ b/index.html @@ -18,9 +18,8 @@ 이어도 반드시 붙여야 캐시가 재사용된다). 나머지 셋은 일부러 preload하지 않는다 — 표제용 제주한라산(195K)·인용용 제주명조(241K)는 - 아직 적용 대상 컴포넌트가 없어 쓰이지 않고, 손글씨체(469K)는 포스트잇 전용이라 첫 화면에 - 없는 경우가 많다. 전부 preload하면 정작 필요한 본문 서체와 대역폭을 다투어 초기 렌더가 - 밀린다. + 쓰는 화면에서만 요청하고, 손글씨체(469K)는 포스트잇 전용이라 첫 화면에 없는 경우가 많다. + 전부 preload하면 정작 필요한 본문 서체와 대역폭을 다투어 초기 렌더가 밀린다. 380: 본문 서체가 잘난고딕(154K)에서 제주고딕(92K)으로 바뀌면서 이 preload 한 건의 전송량도 그만큼 줄었다. --> diff --git a/src/features/home/components/HomeSheetPanels.test.tsx b/src/features/home/components/HomeSheetPanels.test.tsx new file mode 100644 index 0000000..2c77838 --- /dev/null +++ b/src/features/home/components/HomeSheetPanels.test.tsx @@ -0,0 +1,39 @@ +import { act } from 'react'; +import { createRoot, type Root } from 'react-dom/client'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { PaperCoverFace } from './HomeSheetPanels'; + +const { preloadMock } = vi.hoisted(() => ({ preloadMock: vi.fn() })); + +vi.mock('react-dom', async (importOriginal) => ({ + ...(await importOriginal()), + preload: preloadMock, +})); + +let container: HTMLDivElement; +let root: Root; + +beforeEach(() => { + (globalThis as unknown as { IS_REACT_ACT_ENVIRONMENT: boolean }).IS_REACT_ACT_ENVIRONMENT = true; + container = document.createElement('div'); + document.body.appendChild(container); + root = createRoot(container); + preloadMock.mockClear(); +}); + +afterEach(() => { + act(() => root.unmount()); + container.remove(); +}); + +describe('PaperCoverFace', () => { + it('이동 책이 렌더될 때만 제주명조를 preload한다', () => { + act(() => root.render()); + + expect(preloadMock).toHaveBeenCalledExactlyOnceWith('/fonts/jeju-myeongjo.woff2', { + as: 'font', + type: 'font/woff2', + crossOrigin: 'anonymous', + }); + }); +}); diff --git a/src/features/home/components/HomeSheetPanels.tsx b/src/features/home/components/HomeSheetPanels.tsx index 4c49912..81fe86b 100644 --- a/src/features/home/components/HomeSheetPanels.tsx +++ b/src/features/home/components/HomeSheetPanels.tsx @@ -1,3 +1,4 @@ +import { preload } from 'react-dom'; import { Link } from '@tanstack/react-router'; import { usePlaceRecordSheet } from '@/contexts/usePlaceRecordSheet'; import { PaperNoteParts } from '@/shared/ui/PaperNoteParts'; @@ -152,6 +153,14 @@ export function HomeRightType() { * 표지 조판이 달라지면 "같은 시리즈의 책"이라는 인상이 깨진다. 그래서 복제하지 않고 내보낸다. */ export function PaperCoverFace({ title }: { title: string }) { + // 이 표지가 실제로 필요한 화면에서만 제주명조를 미리 요청한다. index.html에서 전역 + // preload하면 로그인·약관처럼 표지를 렌더하지 않는 진입도 241KB 폰트를 받게 된다. + preload('/fonts/jeju-myeongjo.woff2', { + as: 'font', + type: 'font/woff2', + crossOrigin: 'anonymous', + }); + return ( <>