시안(Figma 디자인시스템)이 Pretendard를 지정하는데 앱 셸만 WantedSans를 쓰고 있어 한 화면에
두 서체가 섞여 있었다. 앱도 Pretendard로 맞춘다.
- layout.tsx: `next/font/local`의 wantedSans 선언을 걷어냈다. 앱 기본 서체는 이제 globals.scss의
`@font-face`가 공급한다 — @fox 토큰이 패밀리명을 리터럴 `Pretendard`로 못 박고 있어
next/font(패밀리명을 해시로 바꾼다)를 쓸 수 없기 때문이고, 같은 서체를 두 경로로 넣을 이유도
없다.
- globals.scss: `--app-font-sans: "Pretendard"`를 @font-face 옆에 정의했다. @fox README가 정의한
호스트 앱 계약의 실제 주입 지점이라, 나중에 서체를 갈 때 이 한 줄만 고치면 된다.
- weight 700(Bold) 추가. 토큰이 쓰는 400·600·800만으로는 어떤 CSS도 굵기를 지정하지 않는
자리(제목·th·strong 등 UA 기본값 700)가 800으로 올라가 굵어진다.
- public/fonts: WantedSans TTF 4종(9.4MB) 삭제. 참조가 layout.tsx 한 곳뿐이었고 그게 사라졌다.
검증 — `--app-font-sans`가 `"Pretendard"`, body 계산값이 `Pretendard, system-ui, sans-serif`,
document.fonts에 wantedSans가 아예 없다. 굵기별 문자열 폭이 400/600/700/800에서 각각
328.2 / 335.2 / 338.7 / 342.2px로 전부 달라, 700이 800으로 승격되지 않고 실제 Bold 페이스로
잡히는 것까지 확인했다. FoxCarouselIndicator는 59.69px로 종전과 같다(회귀 없음).
저장소 폰트 용량 11.6MB → 3.0MB.
Co-Authored-By: Claude Opus 5
@fox 토큰이 패밀리명을 리터럴 `Pretendard`로 지정하는데 프로젝트 어디에도 그 이름의 폰트
공급이 없었다. 그래서 모든 @fox 컴포넌트가 OS 기본 서체(맥 Apple SD Gothic Neo / 윈도
맑은 고딕)로 갈라져 그려졌고, 글자 폭이 시안과 어긋났다.
- public/fonts: Pretendard v1.3.9 woff2 400/600/800 반입(OFL 1.1). 토큰이 쓰는 weight가
정확히 이 셋이다 — 특히 800은 wantedSans에 없어 가짜 굵기로 합성되고 있었다.
- globals.scss: @font-face로 직접 선언. next/font/local은 패밀리명을 해시로 바꿔 토큰의
리터럴과 만나지 못해 이 용도로는 쓸 수 없다.
- globals.scss: body에 `--app-font-sans` 연결. 이 계약 변수를 읽는 곳이 없어 wantedSans가
로드만 되고 어디에도 적용되지 않았다. 이제 @fox 밖 텍스트가 wantedSans를 쓴다.
- next.config.ts: `/fonts/*`를 no-store에서 제외. public/ 자산이라 그대로 두면 페이지를
열 때마다 2.2MB를 다시 받는다.
- proxy.ts: 폰트 확장자를 matcher에서 제외. 세션 없는 방문자의 폰트 요청이 `/login`으로
리다이렉트돼 로그인 화면만 대체 서체로 그려졌다.
- @fox/README.md: "호스트 앱과의 계약"이 @fox 컴포넌트도 `--app-font-sans`를 읽는 것처럼
적혀 있었으나 사실이 아니다. 실제 요구사항(Pretendard @font-face·400/600/800)으로 교체.
FoxCarouselIndicator number형 56.92px → 59.69px. 시안 62px과의 잔여 2.31px은 Figma가 텍스트
상자 폭을 정수로 올리고(+1.57) 마지막 글자의 음수 자간을 빼지 않는(+0.75) 표기 차이다.
Co-Authored-By: Claude Opus 5
디자인 레이어가 React + CSS Modules 전용이던 문제를 푼다. 기존 클래스명은
`.button`·`.label`·`.icon`처럼 일반명사여서, CSS Modules 스코프 밖으로 나가면 소비
프로젝트의 동명 클래스와 전부 충돌했다. SCSS만 쓰는 프로젝트(Vue·Svelte·서버 템플릿)는
버튼을 다시 만들 수밖에 없었다.
`fox-` 접두사 + BEM(fox-button__label · fox-button--primary)으로 바꿔 이름을 전역
유일하게 만들고 CSS Modules를 걷어냈다. 충돌 방지는 도구가 아니라 접두사 규율이 담당한다.
React 컴포넌트는 이 클래스를 조립하는 얇은 래퍼가 되고, 래퍼 없이도 같은 디자인을 얻는다.
진입점을 둘 다 제공한다 — `@fox/styles/components`(전부)와 개별 파티셜
`@fox/styles/fox-button`(안 쓰는 CSS를 번들에서 뺀다). 둘을 같이 써도 Sass가 모듈을
한 번만 로드해 중복되지 않는다.
마크업 계약을 스타일 파일 상단 주석과 @fox/README.md에 적었다 — React 밖 소비자는
그것만 보고 DOM을 짤 수 있어야 한다.
앱 화면 스타일은 `.module.scss` 그대로다(앱 전용이라 스코프가 이득). 규약 문서도 그
구분이 드러나게 고쳤다.
Co-Authored-By: Claude Opus 5
globals는 @fox 로드와 앱 셸 구조만 담당하고 디자인 값은 갖지 않는다.
폰트는 앱이 소유하고 @fox는 --app-font-sans/--app-font-mono를 참조만 하므로,
@fox 폴더를 다른 프로젝트로 복사해도 그쪽 서체를 그대로 따른다.
Co-Authored-By: Claude Opus 5