Commit graph

12 commits

Author SHA1 Message Date
Yun Chan
7ef9106723 fix(site): add explicit not-found page
All checks were successful
ci / build (push) Successful in 41s
2026-08-30 18:24:48 +09:00
Yun Chan
13dd160c16 feat(site): redesign promotion experience 2026-08-30 17:52:54 +09:00
Yun Chan
72337b7ee0 feat(skill): 자율 검증 폐쇄 루프 내재화 — 0.6.0
Some checks failed
ci / build (push) Failing after 5s
- 핵심 규칙 6: 완료의 정의는 게이트 통과. 사용자를 QA로 쓰지 않는다
- 5단계 기계 검사 4번째: design-gate 실행 의무화
- references/audit-gate.md: 사고-검사 매핑, SEO/meta 체크리스트, OS/브라우저 특성, 하니스 규칙
- tools/design-gate.mjs: 범용 게이트(메타/SEO·대비·수축·리듬·트랙·스케일×폭 + 옵션 L0/L3/L4, checks 깊은 병합)
- 리듬·트랙 불변식: 숫자 라벨 등폭·빈 셀 트랙 균일·등간격 — 시간표 자동배치 결함 재현 픽스처 검출, 앱 15뷰 통과(오탐 0)

feat(site): 관리 앱 2종 프로덕션 콘솔(v6→v18)

- 가온 학적부 9뷰·두레 수강신청 6뷰: shadcn 문법, Pretendard/Noto Serif/IBM Plex 폰트 전략, 볼드 금지(400/500/600), WCAG AA 대비 전면 교정, 한글 keep-all 조판
- LMS 필수 요소(알림 센터·공지·진도·평가 유형·출결 사유·학점 경고), 12명 기준 데이터 정합, SEO 구조(h1 유일·OG/twitter·og.png)
- 시간표 자동배치 결함 수리(명시적 격자 좌표)
- QA 게이트: L0 stylelint/html-validate · L1 단위 30 · L2 감사 61+불변식 · L3 시각회귀 30화면 · L4 WebKit · L5 키보드 탐색 — npm run verify 실패 시 배포 금지 체인
2026-08-22 21:22:05 +09:00
Yun Chan
ae2980872b feat(site): 재료 섹션을 실무 필터 3종으로 다시 만들고 푸터를 제거
Some checks are pending
ci / build (push) Waiting to run
푸터를 없애라는 지시가 반영돼 있지 않았다. .install-colophon 이 사실상
푸터였고, .install-grid 밖에 있어 padding-inline 을 못 받아 화면 왼쪽 끝에
붙어 있기까지 했다. 제거하고 저장소 링크는 헤더 nav 로 옮겼다.

재료 섹션은 "필터로 질감 만들기"(그레인/굴절/듀오톤)였고 화면에서 아무 말도
하지 않았다. 실무에서 손이 줄어드는 자리로 바꾼다.

- 글자 모양대로 생기는 스크림 — 흰 글자 대비 1.70:1 → 4.79:1 (AA 통과)
- 색각 이상 시뮬레이션 — 상태 배지 셋의 최소 색거리 82 → 2
- 구이(gooey) — 가로로 세어 덩어리 3개 → 1개

세 값 모두 화면을 캡처해 잰 것이다. 처음에는 데모보다 카피를 먼저 썼고,
그 결과 "2.1:1 → 12.4:1" 같은 재지 않은 숫자가 페이지에 실렸다. 전부 교체했다.

backdrop-filter 굴절 데모는 뺐다. feTurbulence 를 변위 지도로 써서 지도가
중립값(128)으로 수렴했고, scale 을 120 까지 올려도 채널차 2.96 이었다.
svg-filters.md 에 "변위 지도는 노이즈가 아니다" 라고 이미 적혀 있었는데
쓰기 전에 읽지 않았다.

섹션 끝의 note 도 삭제했다. color-interpolation-filters 를 명시했다는
문장은 방문자가 그것으로 할 수 있는 일이 없는 내부 자랑이었다.

스킬 내재화:
- svg-filters.md  실무 레시피 3종(스크림/색각/구이) + 구이가 붙는 문턱 계산
                  + feTurbulence 변위 지도 실패 기록
- antipatterns.md 데모를 만들기 전에 카피부터 쓰지 마라
                  + Playwright animations:'disabled' 가 끝 프레임을 찍는 함정
2026-08-20 23:23:24 +09:00
Yun Chan
8ed45008a0 배포 환경을 실측해 .env.example 에 남긴다
Some checks failed
ci / build (push) Failing after 5s
나스를 찾았다 — Tailscale 의 yunchan-nas (100.116.83.60 / LAN 192.168.0.39),
Synology DS420+. SSH 키(id_ed25519)로 이미 붙어서 비밀번호가 필요 없다.

Forgejo 구성
  컨테이너 kd-forgejo (codeberg.org/forgejo/forgejo:11) + postgres:16-alpine
  웹 3000 -> Cloudflare 프록시로 https://git.chanpaca.net
  git SSH 2222 -> 컨테이너 내부 22

  중요: git.chanpaca.net 은 Cloudflare 뒤라 22/2222 가 둘 다 막혀 있다.
  오리진 IP 를 감추는 정상 구성이고, 그래서 git push 는 도메인이 아니라
  Tailscale 주소로 해야 한다. remote 를 그렇게 걸었다.

  SSH 키가 이미 Forgejo 에 등록돼 있다(encep-win, yunchan 계정).
  push 에 토큰도 비밀번호도 필요 없다.

배포 전 검증
  전체 빌드 통과 · 테스트 22개 통과
  tarball 114.5KB / 22개 파일, 스킬 19개 포함
  실제 npx 설치 왕복: install 19개 -> doctor 정상 -> 드리프트 감지 ->
  update 가 수정 파일 보존 -> uninstall 후 잔여 0

  배포 직전에 결함 하나를 잡았다. Windows 에서 작업해 스킬이 전부 CRLF 로
  저장돼 있었고, 그대로 tarball 에 들어가면 SKILL.md 의 YAML 프론트매터를
  파서에 따라 못 읽는다. 번들 스크립트에서 LF 로 정규화하고
  .gitattributes 도 넣었다. 배포물은 어느 OS 에서 만들든 같아야 한다.

푸터 제거
  출처가 사라지지 않게 설치 섹션 끝에 한 줄만 남겼다(저장소 · MIT).
2026-08-20 16:58:24 +09:00
Yun Chan
8267905c0c 테두리 광을 회전시키고 three.js 모바일 대응을 고친다
회전 테두리
  conic 의 각도를 @property 로 돌리면 매 프레임 배경을 다시 칠한다 —
  컴포지터에서 못 돌고 메인 스레드가 페인트한다(하드 게이트 8).
  정사각형 원뿔 레이어를 마스크 안에서 rotate 시켰다. transform 만 움직인다.
  aspect-ratio: 1 이라야 회전 중 밝기가 일정하고,
  width: 200% 라야 1178x52 헤더에서 모서리까지 닿는다. 주기 11초.

three.js 모바일
  세로 화면에서 게이트가 통째로 안 보이고 있었다.
  수직 시야는 화면 비율과 무관하지만 수평 시야는 aspect 에 비례한다.
  데스크톱(2.5:1)에서 정한 판 폭 15 가 세로 화면(0.45:1)의 수평 시야
  2.5 에 비해 여섯 배라, 첫 판이 화면을 완전히 덮었다.
  fit() 에서 camera.aspect 를 갱신할 때 판의 scale.x 도 같이 잡는다.

  저사양 판정도 고쳤다. hardwareConcurrency <= 4 만 보면 요즘 폰이 전부
  고사양으로 잡힌다(8코어가 흔하다). innerWidth < 760 을 함께 본다.
  DPR 1.5 -> 1.25, 캔버스 불투명도 0.7 -> 0.45(세로는 화면 전체를 덮는다).

스킬
  svg-filters.md  테두리 광 회전은 각도가 아니라 정사각형 레이어 rotate
  three.md        지오메트리를 화면 비율에 맞춰 다시 잡아라
                  저사양 판정에 화면 폭을 넣어라
2026-08-20 16:37:49 +09:00
Yun Chan
9c9ab2de7e 디자인 SSOT 를 세우고 3D 를 배경 재질로 되돌린다
지적받은 것: 모바일 마진·패딩, 폰트 웨이트, 버튼 스타일 불일치, SSOT,
스크롤바, 모바일 메뉴, 그리고 3D 를 왜 상자에 넣었는지.

3D 의 역할을 잘못 잡았다
  lusion.co 의 "3D 는 액자 안"은 3D 자체가 상품일 때의 규칙이다.
  우리는 절차를 파는데 액자에 넣을 상품이 없어 "저 상자는 뭐냐"가 됐고,
  의미를 게이트 판독기가 자막으로 설명하고 있었다.
  이 씬의 역할은 재질이다. 배경으로 되돌리고 값을 전부 낮췄다 —
  테두리 광 0.85->0.42, 알파 0.72->0.34, UV 경계 0.05->0.17, 이동 60%
  ResizeObserver 로 캔버스를 따라가게 했다. window.resize 만 듣는 동안
  히어로 높이 변화를 놓쳐 배경이 화면의 3분의 2만 덮었다

SSOT
  웨이트 6종(400/500/560/600/620/660) -> 3종. 셋은 토큰에 없던 값이었다
  .btn + btn-solid/btn-quiet. 두 버튼이 높이 36 vs 44, 패딩 16 vs 8,
    테두리 1px vs 0, 웨이트 400 vs 500 이었다
  --header-h. 간격을 clamp 로 바꾸자 관계가 끊겨 h1 이 헤더 뒤로 들어갔다
  --space-5~8 과 --gutter 를 clamp 로. 고정이면 모바일 여백이 화면의 26%
  scrollbar-color 지정

모바일
  좌우 여백 24 -> 32px, 섹션 상하 112 -> 56px
  헤더에 섹션 앵커 4개. 900px 미만은 details 기반 메뉴(JS 0바이트)

패럴랙스는 섹션마다 다른 말을 한다
  히어로   글자 상승 / 배경 하강 — 반대 방향이라야 시차가 보인다
  파이프라인 단계명 고정, 산출물만 지연 — 인과
  재료     타일이 서로 다른 깊이 — 표면은 한 겹이 아니다
  프리플라이트 뒤 항목일수록 늦게 — 로그는 흐른다
  수치     없음. 의도적 정지 — 계기판의 바늘은 떨지 않는다

스킬
  three.md  §0-A 를 역할별로 갈랐다. "액자 안"만 적어둔 것이 잘못된
            일반화였고 내가 거기 그대로 걸렸다. 재질일 때의 값 교정을 실측으로 남김
  tokens.md 웨이트·컨트롤·헤더 높이·반응형 간격 — 토큰이 아예 없던 네 축
  motion.md 섹션별 패럴랙스 배정표. 움직이지 않는 것도 결정이다

390px 실렌더: 가로 스크롤 0, 대비 실패 0, 웨이트 3종, radius 2종. 테스트 22개 통과
2026-08-20 14:15:30 +09:00
Yun Chan
9648d1d82a 소개 페이지를 스킬 전체 경로로 다시 만들고, 배운 것을 스킬에 반영
방향을 글래스로 바꿀 때 2단계 재결정을 하고도 전체 경로로 올리지 않았다.
레퍼런스 없이 재질만 갈아끼운 결과가 스위스 미니멀 뼈대에 유리를 바른
페이지였고, design.md 는 초판 결정을 그대로 담고 있었다. 0단계부터 다시 돌았다.

1단계 — 레퍼런스 3개를 computed style 까지 실측
  R1 zed.dev      컨테이너 1120px 과 전체폭이 교대 · radius 2px 621회
  R2 lusion.co    3D 는 액자 안, 텍스트는 액자 밖 · 배경 흰색 · h1 36px
  R3 Codrops      DOM 이 구조를 소유하고 WebGL 은 uniform 만 만진다

2단계 — 프리셋 swiss-minimal → dark-instrument, 컨셉 "검사대 위의 물체"
        유리는 액자에만 남긴다(헤더 · 검사대 · 명령창)

4단계 — 히어로 재구성. 캔버스를 배경에서 빼 액자 안으로, 텍스트는 밖으로
        판독기가 통과한 게이트를 표시한다(값이 바뀔 때만 DOM 을 쓴다)
        파이프라인을 2열로 열어 625px → 1113px

5단계에서 실제로 걸린 것
  게이트 3  radius 4종 → 2종 (3px / 14px, pill 제거)
  게이트 1  base.css 토큰 밖 rgb() 7곳 → 토큰
  게이트 7  헤더 English 2.59:1 → ink 로 상향
  카운트    히어로 h1 4줄 → 2줄
  셰이더    판이 정면이라 프레넬이 구조적으로 0. 법선을 굽히고 UV 로 테두리
  셰이더    gl_FragCoord 를 렌더 타겟 크기로 나눠 UV 가 1 을 넘고 있었다
  수치      페이지가 실은 "타입 단계 5단계"가 실측 9종이었다. lang 속성이
            스케일을 재정의해 링크 하나가 16px 로 새고 있었다
  측정      대비 스크립트가 반투명 배경을 불투명으로 계산했다. 알파 합성으로 교정

스킬 반영
  three.md    §0-A 배치 원리(3D 는 액자 안) · 프레넬 0 함정 · gl_FragCoord 함정
  preflight.md 대비 측정 시 알파 합성. 검사 도구가 틀리면 통과도 의미가 없다

최종: 하드 게이트 12/12, 대비 실패 0, 320px 오버플로 0, 테스트 22개 통과
2026-08-20 13:33:28 +09:00
Yun Chan
eb3ca69b5d 타이포그래피 스킬 신설 + 폴백 메트릭 보정
'폰트 관련된 것도 스킬이 좀 잘 해줘야 하는데 그렇지 못한 것 같다'는 지적.
점검해보니 size-adjust, ascent-override, unicode-range, OpenType 기능,
FOUT/FOIT, 폰트 라이선스가 스킬 어디에도 없었다. font-display 와 서브셋은
tokens.md 에 한 줄씩뿐이었다.

references/typography.md 신설
- 고르는 절차: 개수를 먼저 정하고, 성격을 브리프에서 끌어내고,
  x-height·대비·웨이트 범위·숫자 형태를 실제로 재서 검증한다
- 가변 폰트: 축, 표준 속성 우선, 가변 축 애니메이션이 왜 게이트 8 위반인지
- 로딩: font-display 값별 선택 기준, preload 조건, unicode-range
- 폴백 메트릭: size-adjust 와 override 3종. 재는 코드 포함
- OpenType: tabular-nums 등. font-variant-* 를 font-feature-settings 보다 먼저
- 한글: 동적 서브셋 원리, 웨이트가 라틴과 다르게 보이는 이유, 스택 순서
- 라이선스: 웹 임베딩 허용 여부가 상업 이용 허용과 다르다는 것

그리고 이 페이지가 그 규칙을 어기고 있었다
- 실측: 맑은 고딕이 Pretendard 보다 13.0% 넓다. 교체 순간 줄바꿈이 다시 잡힌다
- fonts.css 신설. OS 별로 폴백을 따로 정의하고 size-adjust 로 맞췄다
- 실측 차이 13.0% -> 0.0%

preflight.md 에 폰트 검사 6개를 추가했다. 지금까지 하나도 없었다.
2026-08-20 12:42:59 +09:00
Yun Chan
85be000704 헤더 상단 검은 띠 제거 · 패럴랙스 · 히어로 3D 유리 씬
헤더가 문서 흐름에 있어서 그 위 공간이 히어로 광원 밖으로 남았다.
화면에서 검은 띠로 보였다. 헤더를 띄우고 히어로가 최상단부터 차오르게 했다.

패럴랙스는 scroll-driven animation 으로만 만든다. scroll 리스너를 쓰지 않고
transform 만 움직이므로 미지원 브라우저에서는 제자리에 그대로 있다.

히어로 3D 는 배경을 렌더 타겟에 굽고 유리 판이 그 텍스처를 왜곡 샘플링한다.
transmission 재질이 매 프레임 씬을 재렌더하는 비용을 피한 구조다.
2026-08-20 12:17:02 +09:00
Yun Chan
be343cdab5 소개 페이지 전면 재디자인 — Ethereal Glass
design-taste-frontend, high-end-visual-design, redesign-existing-projects 를
로드해 리디자인 모드로 진행했다. 이전 페이지는 디자인 스킬을 파는 자리가
문서처럼 생겼다는 지적을 받았다.

Design Read
- redesign-overhaul / 개발자 대상 / 정밀기기 언어
- DESIGN_VARIANCE 8 · MOTION_INTENSITY 6 · VISUAL_DENSITY 3

방향
- 다크 잉크 바탕에 three.js 셰이더 광원. 유리 패널이 그 위에 뜬다
- 리퀴드 글래스는 이 브리프에서 장식이 아니라 제품 시연이다.
  SVG 필터와 three.js 의 결합 그 자체이기 때문이다
- 밝은 밴드는 조판 섹션 하나뿐. 한글이 종이 위에 있어야 하는 자리다

제품 증명
- 히어로 배경에 셰이더(초기 번들 밖, 첫 페인트 후 지연 로드)
- 재료 섹션에 SVG 필터 3종을 실제로 먹인 타일: 그레인, 굴절, 듀오톤
- 도그푸딩 산출물 2개를 실제 스크린샷으로. 가짜 목업이 아니다

감사에서 걸려 고친 것
- backdrop-filter 에 SVG 를 얹으면 Chrome 이 선언 전체를 버린다.
  CSS.supports 는 참을 주면서 computed 는 none 이 된다
- main 에서 그리드 클래스가 빠져 subgrid 가 붕괴, 가로 444px 오버플로
- 진입 연출이 두 번 콘텐츠를 삼켰다. opacity 를 버리고 transform 만 남겼다
- eyebrow 4개, 제목 em-dash 2건

수치는 불리해진 것도 그대로 싣는다
- 반투명 패널 1개 -> 29개. 유리가 주제가 됐으므로
- three.js 185KB(gzip). 데모라서 JS 예산을 올렸고 그 사실을 페이지에 적었다
2026-08-20 11:45:38 +09:00
Yun Chan
6103700d38 소개 페이지 — 스킬을 스스로 적용해 만든 첫 사례
designpaca 파이프라인 0~6단계를 실제로 돌려 만들었다. 근거는 research/site-brief.md,
결정 기록은 apps/site/design.md 에 있다.

한 문장 컨셉
- 이 페이지는 designpaca 를 거쳐 만들어졌고, 절차와 형태 수치를 한국어 기준으로 전부 공개한다

번호 없이 순서 표현 (C-07 회피)
- 파이프라인 6단계를 번호로 매기면 검출률 3위 슬롭 지문에 걸린다
- 시각: 스파인 위 위치가 순서를 만든다 / 내용: 같은 브리프가 단계마다 변한다
- 의미: <ol role="list"> — 화면에 번호 0개, 보조기술에는 "6개 중 n번째"

멀티링구얼
- / = 한국어, /en/ = 영어. 번역이 아니라 각 판을 따로 썼다
- 언어별 레이아웃이 자기 폰트만 로드한다 (판당 2개)
- 조판 섹션은 한국어판에서 주장이고 영어판에서 사례다

실측
- JS 314B (gzip, 예산 50KB) / CSS 3.0KB / HTML 4.4~4.8KB
- radius 2종 · backdrop-filter 0개 · 타입 5단계 · 강조색 1개
- 슬롭 지문 grep 9패턴 0건, 정적 하드 게이트 8개 전부 통과

감사에서 걸려 고친 것
- eyebrow 6개 → 상한 ceil(7/3)=3 위반 → 3개로
- clip-path 리빌 → 게이트 #8 위반 → transform 으로 교정
- 구분선 대비 1.30:1 → 입력 테두리용 별칭 분리 (WCAG 1.4.11)
- 본문 컬럼 960px → --measure 로. layout.md 예시 코드도 같이 수정
2026-08-20 11:00:38 +09:00