- Set cache: 'no-store' in lib/api.ts to trigger real-time REST API requests on every page load - Add export const dynamic = 'force-dynamic' across all 6 app pages (/home, /members, /publications, /lectures, /standardization) - Update REQUIREMENTS.md and E2E test runner to validate live server routes and dynamic runtime fetching - Pass all 12 quality gates cleanly
148 KiB
📐 요구사항 명세서 (Requirements Specification)
경북대학교 AI 에이전트 네트워크 연구실 (ANL) 공식 홈페이지
| 항목 | 내용 |
|---|---|
| 문서 ID | REQ-ANL-WEB-001 |
| 버전 | 2.0 |
| 작성일 | 2026-08-24 |
| 작성자 | agy (herdr:creator-agy-01) / claude (herdr:planner-reviewer-claude-01) · Role: worker / planner |
| 상태 | 승인 (Approved) — v2.0에서 DM-03 및 AC-17 개정(Go/Gin 백엔드 REST API 연동 및 force-dynamic + cache: 'no-store' 기반 실시간 동적 런타임 페칭 도입, 6개 데이터 라우트 ƒ Dynamic 및 4개 프레임워크 라우트 ○ Static 분리 확정). |
| 대상 독자 | General Manager, Developer Team Leader(Agy), Reviewer Team Leader(Cline), 지도교수 |
| 선행 문서 | README.md, .agents/MULTI_AGENT_RULES.md, refer_landing_page/docs/DESIGN.md |
| 적용 범위 | refer_landing_page/ (Next.js 14 App Router 애플리케이션) 전체 |
본 문서의 성격: 코드를 포함하지 않는 명세 문서입니다. 데이터 스키마와 인터페이스 정의에 한해 TypeScript 타입 표기를 사용하나, 이는 계약(contract) 기술을 위한 것이며 구현 코드가 아닙니다.
1. 원본 요구사항 (사용자 제공 · 정본)
아래는 사용자가 직접 작성한 요구사항 원문이며, 본 명세서 전체의 정본(normative source) 이다. 이하 모든 절은 이 원문을 구체화한 것이며, 원문과 충돌하는 서술이 있다면 원문이 우선한다.
- 홈페이지 상단 탭은 다음과 같음
- Home: 연구실 소개, 연구실 주요 연구 분야 소개, 오시는길
- Members: 기존 정보 그대로 보존되어야 함
- Publications: 기존 정보 그대로 보존되어야 하며, 다음 카테고리로 구분되어야 함
- International Conference
- International Journal & Conference
- Domestic Journal & Conference
- Patent
- Lectures: 기존 정보 그대로 보존되어야 함
- Standardization: 기존 정보 그대로 보존되어야 함
1.1 원문에서 도출되는 최상위 원칙
| ID | 원칙 | 근거 문구 |
|---|---|---|
| PR-01 | 무손실 보존 (Lossless Preservation) — 레거시 ISL-2026/의 레코드는 한 건도 누락되지 않고, 문구·표기·순서가 임의로 변형되지 않은 채 이관되어야 한다 |
"기존 정보 그대로 보존되어야 함" (4회 반복) |
| PR-02 | 상단 탭 5종 고정 — Home / Members / Publications / Lectures / Standardization | "홈페이지 상단 탭은 다음과 같음" |
| PR-03 | Home 3구성 — 연구실 소개 · 주요 연구 분야 소개 · 오시는 길 | Home 항목 |
| PR-04 | Publications 분류 — 원문에 명시된 4개 카테고리 라벨을 출발점으로 삼는다. (v1.5: 원문 1번 International Conference는 §12.1 D-01 확정에 따라 폐기되어 최종 3분류로 확정. 원문 문구 자체는 §1에 정본 그대로 보존하며, 이 축소는 해당 라벨에 배정된 레코드가 0건이므로 PR-01 무손실 원칙과 충돌하지 않는다) |
Publications 항목 |
⚠️ PR-01의 해석: "그대로 보존"은 데이터의 무손실을 의미하며, 레거시의 시각적 표현을 그대로 복제하라는 뜻이 아니다. 표현은 신규 디자인 시스템(§8)을 따르되, 레코드 단위의 정보량은 100% 보존한다. 점진적 노출(더 보기·접기)은 전체 레코드가 접근 가능한 한 허용된다(§9.4 참조).
2. 개요 및 배경 (Overview & Background)
2.1 목적
경북대학교 컴퓨터학부 연구실이 사물인터넷 표준 연구실 (IoT Standards Laboratory, ISL) 에서 AI 에이전트 네트워크 연구실 (AI Agent Networking Laboratory, ANL) 로 연구 정체성을 전환함에 따라, 공식 홈페이지를 다음 두 축으로 재구축한다.
- 정체성 전환 (Identity Transformation) — 연구실 명칭·연구 서사·시각 언어를 ANL 및 5대 핵심 연구 기둥 기준으로 전면 교체한다.
- 실데이터 마이그레이션 (Data Migration) — 레거시 사이트
ISL-2026/에 축적된 실측 연구 실적 총 223건(국제 논문 68 · 국내 논문 80 · 특허 75)과 표준화 문서 약 55건을 신규 애플리케이션의 타입 안전한 데이터 구조로 무손실 이관한다(PR-01).
2.2 현재 상태 (As-Is)
| 자산 | 경로 | 상태 |
|---|---|---|
| 레거시 공식 홈페이지 | ISL-2026/ |
정적 HTML. 실데이터 원본(Single Source of Truth) |
| 신규 프로토타입 | refer_landing_page/ |
Next.js 14.2.35 / React 18 / TS 5 / Tailwind 3. 라우트 5종 구현, 콘텐츠는 대부분 placeholder |
| 연구 자산 | multi-agent-orchestration/ |
5대 연구 기둥의 근거 자료 (SLIDE.md, chapters/, lecture_summary.md) |
완료된 선행 작업 (커밋 e35b46d → 315ba9e → cdd0db3, 3차 교차 리뷰 [VERDICT: PASS])
- 연구실 명칭 ANL 전환: Header / Footer /
metadata/package.json(anl-landing) /docs/DESIGN.md/tailwind.config.ts /intro커버 스프레드를 5대 연구 기둥 3+2 매거진 조판으로 재구성- 강조색 시맨틱 계약 재정의:
vermillion= Agent Eng / Orchestration (홀수),cobalt= MCP / A2A Protocol (짝수) - 빌드 게이트 정비:
.eslintrc.json도입, lint / tsc / build 3종 통과
미해결 상태
/(루트) 라우트 부재 —app/page.tsx가 없어 사이트 루트 직접 접근 시 404. PR-02의Home탭이 존재하지 않는다./members,/publications,/lectures,/standardization본문이 전부 가상의 placeholder (연구원 A (placeholder), 가상 논문, 실재하지 않는 oneM2M/OMA LwM2M 기여 내역)- 레거시 실데이터 223건 + 표준 문서 약 55건 전량 미이관 — PR-01 미충족
3. 이해관계자 및 역할 (Stakeholders & Roles)
| 주체 | 역할 | 본 명세서에 대한 책임 |
|---|---|---|
| 지도교수 (고석주 교수) | 콘텐츠 소유자 | 실데이터 정확성 최종 확인, §12 D-02·D-03·D-05 결정 (D-01은 v1.5에서 확정) |
| General Manager | 오케스트레이터 | 잡 분배, 마일스톤 게이팅, 미결 결정 에스컬레이션 |
Agy (creator) |
개발 팀장 | §6·§7 구현, 데이터 추출·이관, 컴포넌트 개발 |
Cline (reviewer) |
리뷰어 팀장 | §9 비기능 요구사항 검수 (UI/UX 반응형, SEO, 접근성) |
Claude (planner and reviewer) |
기획·리뷰어 팀장 | 본 명세서 작성·유지, 데이터 무결성 교차 검증, 최종 Verdict |
4. 정보 구조 (Information Architecture)
4.1 사이트맵
/ Home [🆕 신규] 연구실 소개 · 주요 연구 분야(5대 기둥) · 오시는 길
├── /members Members 지도교수 · 재학 연구원 16명 · 졸업생 60명
├── /publications Publications 개요 · 카테고리 분류 · Top 10 (총 223건)
│ ├── /publications/intl-journal-conf International Journal & Conference (68)
│ ├── /publications/domestic-journal-conf Domestic Journal & Conference (80)
│ └── /publications/patent Patent (75)
├── /lectures Lectures 2004 Spring ~ 2026 Spring, 45개 학기
└── /standardization Standardization 표준화 기구 6곳 · 표준 문서 44건
4.2 IA 설계 결정
| ID | 결정 | 근거 |
|---|---|---|
| IA-01 | 현행 /intro의 커버 스프레드를 /(Home)으로 승격한다 |
PR-02가 상단 탭에 Intro를 포함하지 않으며, PR-03의 "연구실 소개"가 Home의 구성 요소로 명시되어 있다. /intro를 별도 유지하면 Home과 콘텐츠가 중복된다. 부수 효과로 기존 / 404 결함이 해소된다. |
| IA-02 | /intro는 /로 308 영구 리다이렉트한다 |
3차에 걸친 리뷰 리포트·문서가 /intro를 참조하고 있어 링크 안정성이 필요하다. next.config.js의 redirects()로 처리하며 별도 페이지 파일을 남기지 않는다. |
| IA-03 (v1.1 개정 · v1.5 수치 갱신 · v1.9 개정 · v1.10 재개정) | Publications 카테고리는 라우트 세그먼트 /publications/[category] + generateStaticParams() 로 구현한다. /publications는 redirect()가 아니라 자체 콘텐츠를 렌더하는 실체 라우트로 유지하며, 그 콘텐츠는 하위 카테고리 어느 것과도 중복되지 않는 Overview 뷰(카테고리별 집계 + 최신 실적 하이라이트)로 한다 — D-09 재확정(v1.10). redirect() 전용 라우트는 산출 HTML에 <main>·container-content가 존재하지 않아 AC-25를 구조적으로 위반하므로 금지하고, 첫 카테고리 본문을 그대로 재렌더하는 방식은 동일 DOM 정적 HTML 2본을 생성해 R-8.25를 위반하므로 금지한다. 상단 CategoryNav는 3개 카테고리 탭만 노출하며 All/전체 탭을 두지 않는다(commit 22a31ff 결정 존중) — Overview에서는 활성 탭이 없는 것이 정상 상태다 |
v1.0에서 "단일 라우트 + ?cat= 쿼리"였으나 §8.5의 실측 검증 결과에 따라 개정. 세그먼트 방식은 카테고리별 완전한 정적 HTML 3개(D-01 확정 전 4개)를 빌드 타임에 생성해 공유 링크가 필터 상태를 포함한 문서를 그대로 제공하며(AC-05 취지 충족), 뒤로/앞으로 가기·프리페치·스크롤 복원이 Next 라우터에서 기본 제공된다. 슬러그를 카테고리 레지스트리에서 도출하므로 라벨 변경이 레지스트리 한 곳 수정으로 끝난다는 v1.0의 근거는 그대로 유지된다(→ D-01 리스크 완화 불변). 상단 탭은 5종 그대로이므로 PR-02와 충돌하지 않는다(하위 라우트일 뿐 최상위 탭이 아니다). |
| IA-04 | 내비게이션 항목은 PR-02의 5개로 고정한다 | components/Header.tsx의 데스크톱 내비가 5개 항목 기준으로 조판되어 있다. 항목 증감 시 헤더 레이아웃 재설계가 선행되어야 한다. |
5. 콘텐츠 정본: 핵심 연구 분야
PR-03의 "연구실 주요 연구 분야 소개"에 해당하는 콘텐츠다. README.md §2를 정본(canonical) 으로 하며, UI의 모든 연구 서술은 여기서 파생되어야 한다. 어휘를 임의로 변형하지 않는다.
| # | 분야 (KO) | 분야 (EN) | 핵심 키워드 | 강조색 |
|---|---|---|---|---|
| 1 | AI Agent 기능 확장 프로토콜 | Extensibility & Protocol | MCP, SKILL, CLI 코딩 에이전트 | vermillion |
| 2 | 멀티 에이전트 협업 및 오케스트레이션 | Multi-Agent Systems | HERDR, crewAI, LangGraph | cobalt |
| 3 | 에이전트 상호운용성 개방형 표준 | Interoperability Standards | A2A, ACP, Agent Card | vermillion |
| 4 | AIoT & 고성능 통신 백본 | High-Performance Backbone | gRPC/QUIC, Protobuf, MQTT/CoAP | cobalt |
R-5.1 강조색은 §8.3의 홀수/짝수 규칙을 따른다. 분야 순서를 변경하면 색 배정도 함께 갱신해야 한다.
R-5.2 핵심 연구 분야 서술 전문(全文)은 Home에만 두고, 타 페이지에는 요약 키워드만 노출한다. 동일 문장을 여러 페이지에 중복 하드코딩하지 않는다.
R-5.3 레거시 introduction.html의 구 연구 분야(QUIC, CoAP, IVI, VLC/OWC, mSCTP, SCTP, Mobility Management, Tabu Search 등)는 Home의 연구 분야 소개에서 제외한다. 단, 이들 주제로 산출된 논문·특허·표준은 PR-01에 따라 실적 페이지에 전량 보존된다.
6. 페이지별 상세 요구사항
각 항목의
[MUST]/[SHOULD]/[MAY]는 RFC 2119 수준을 따른다.
6.1 Home (/) — 🆕 신규 라우트
PR-03에 따라 연구실 소개 · 주요 연구 분야 소개 · 오시는 길 3개 블록을 필수 포함한다.
| ID | 요구사항 | 수준 |
|---|---|---|
| H-01 | app/page.tsx를 신규 생성하고, 현행 app/intro/page.tsx의 섹션 구성(커버 스프레드 → 지표 카운터 → Mission 풀쿼트 → 핵심 연구 분야 → Focus Areas)을 이관한다 |
MUST |
| H-02 (v1.7 개정) | 킥커 경북대학교 컴퓨터학부 · AI Agent Networking Lab (ANL)는 유지한다. 슬로건 헤드라인(에이전트 네트워크의 / 미래를 짓다, 디스플레이 Agents / in Motion)은 §6.1.2 Research Project PageView로 교체할 수 있다. 단 교체 시에도 H-03(연구실 소개 서술 블록) · H-04(주요 연구 분야 그리드) · H-05(오시는 길) · H-06·H-07(지표 카운터) · H-10(HeroComposition)은 반드시 존속한다 — 히어로 재구성 중 이들이 유실되면 AC-02가 즉시 실패한다 |
MUST |
| H-03 | [연구실 소개] 연구실 개요·지도교수·비전을 서술하는 블록을 배치하고, 상세는 /members로 연결한다 |
MUST |
| H-04 | [주요 연구 분야] §5의 핵심 연구 분야 전문을 매거진 조판으로 노출한다 | MUST |
| H-05 | [오시는 길] 아래 §6.1.1 요구사항을 충족하는 블록을 배치한다 | MUST |
| H-06 | 지표 카운터는 데이터 배열에서 도출된 값만 사용한다. 근거 없는 홍보성 수치(가동률·만족도 등) 게시 금지 | MUST |
| H-07 | H-06의 권장 지표: 연구 분야 = 4, 누적 연구 실적 = 논문+특허 합계(223), Issue · 발행 = 2026(static) |
SHOULD |
| H-08 | 대표 실적 하이라이트 — 최신 국제 저널 3건을 /publications로 연결 |
SHOULD |
| H-09 | 표준화 기여 요약 밴드 — 기구 6곳 약칭 Marquee + /standardization 연결 |
SHOULD |
| H-10 | HeroComposition SVG는 현행(A2A 노드 메시 × QUIC/gRPC 스트림)을 그대로 재사용한다 |
MUST |
| H-11 | /intro → / 308 리다이렉트를 next.config.js에 등록한다 (IA-02) |
MUST |
| H-12 | components/Header.tsx의 브랜드 링크 href를 /intro → /로 바꾸고, 내비 배열 첫 항목을 Home(/)으로 교체한다 |
MUST |
6.1.1 오시는 길 (Directions) 세부 요구사항
레거시 index.html에 주소가 HTML 주석 처리된 상태로 존재한다. 이를 복원해 사용한다.
| ID | 요구사항 | 수준 |
|---|---|---|
| H-13 | 소재지를 표기한다: 경북대학교 IT대학 5호관(415동) 527호 / School of Computer Science and Engineering, Kyungpook National University | MUST |
| H-14 | 연락처를 표기한다: sjkoh@knu.ac.kr (지도교수). 전화·팩스는 레거시에 존재하지 않으므로 창작하지 않는다 |
MUST |
| H-15 | 소속 기관 링크를 제공한다: KNU(knu.ac.kr), 컴퓨터학부(cse.knu.ac.kr), IT대학(it.knu.ac.kr) |
MUST |
| H-16 | 지도 표현 방식은 §12 D-03의 결정을 따른다. 외부 지도 스크립트를 임의로 도입하지 않는다(R-9.13 최소 의존성 원칙과 충돌) | MUST |
| H-17 | 주소는 시맨틱 <address> 요소로 마크업한다 |
MUST |
| H-18 | 대중교통·주차 안내는 레거시에 데이터가 없으므로 이번 범위에서 제외한다. 필요 시 지도교수 확인 후 별도 잡으로 추가 | MUST |
6.1.2 Research Project PageView (v1.7 신설)
Home의 슬로건 히어로를 실제 연구 프로젝트 카드 뷰로 전환한다(H-02 개정).
레거시 실측 — 실재하는 프로젝트 3건: ISL-2026/index.html <section class="portfolio-block skills">의 card-title/card-text 및 이어지는 확장 섹션 2개가 유일한 원본이다. (projects-cards 클래스는 표준화 기구 로고 그리드이며 연구 프로젝트가 아니다 — 오독 주의.)
| # | Title | 확장 정보 |
|---|---|---|
| 1 | IoT Standards |
— |
| 2 | CCIS |
"This project is developing a series of standards in IEC/TC 100/TA 17" |
| 3 | VLC-IoT |
"This project is purposed to develop a series of standards in ITU-T SG20." |
| ID | 요구사항 | 수준 |
|---|---|---|
| PJ-01 | 데이터는 content/projects.ts에 두고, 타입은 ResearchProject 로 명명한다. StandardsBody.projects(WG 단위 표준화 프로젝트)와 의미가 다르므로 이름을 재사용하지 않는다 |
MUST |
| PJ-02 | content/projects.ts는 scripts/extract/generate_all.py의 parse_projects()로 자동 생성한다. 수작업 편집 금지(기존 AUTO-GENERATED 규약 · AC-24) |
MUST |
| PJ-03 | abstract는 레거시 원문을 바이트 동일하게 보존한다(PR-01). 요약·재작성·line-clamp로 인한 정보 손실 금지 |
MUST |
| PJ-04 | period는 content/standards.ts standardsBodies[].period를 조인해 도출한다. 교차 검증 출처는 ISL-2026/sjkoh/index.html의 Project Editor 이력이다 |
MUST |
| PJ-05 | deliverables는 content/standards.ts projects[].documents[]를 조인해 도출한다. 임의 생성 금지 |
MUST |
| PJ-06 | keywords[]의 모든 원소는 해당 프로젝트 abstract 원문에 부분문자열로 실제 등장해야 한다. 키워드 창작을 기계적으로 차단하기 위한 규칙이다 (→ AC-30) |
MUST |
| PJ-07 | funder는 옵셔널이며 현재 전건 미확보다(§12.1 D-07). 값이 없으면 UI에 해당 행·라벨·자리표시자를 렌더하지 않는다(R-9.18). 레거시가 실제로 명시하는 표준화 트랙은 Funder가 아닌 Standards Track 라벨로 노출한다 |
MUST |
| PJ-08 [금지] | 활성 슬라이드만 마운트하는 캐러셀을 구현하지 않는다. 프로젝트 전건이 항상 DOM에 존재해 정적 HTML에 포함되어야 한다(R-8.15 · AC-27) | MUST |
| PJ-09 [금지] | 슬라이드·페이지 상태를 URL에 동기화하지 않는다. searchParams prop은 라우트를 ƒ Dynamic으로 전환시키고(R-8.11), useSearchParams()는 <Suspense> 경계를 요구하며 경계 안쪽 콘텐츠가 정적 HTML에서 누락된다(R-8.12·R-8.13). 상태는 컴포넌트 로컬로 유지한다 |
MUST |
| PJ-10 [금지] | 캐러셀·슬라이더 외부 라이브러리를 도입하지 않는다(swiper·embla 등). 현행 런타임 의존성 3종(next/react/react-dom)을 유지한다(R-9.13) |
MUST |
| PJ-11 | 트랙은 CSS scroll-snap + 컨테이너 내부 overflow-x-auto 로 구현해 JS 비활성 상태에서도 전건 열람이 가능해야 한다. 페이지 레벨 가로 스크롤을 유발해서는 안 되며(R-9.15·AC-19), full-bleed를 위해 w-screen을 쓰지 않는다(R-8.18) |
MUST |
| PJ-12 | 데이터 렌더는 서버 컴포넌트, 인터랙션(버튼·인디케이터)만 "use client" 로 분리한다. 페이지네이션 인디케이터는 <a href="#project-…"> 앵커로 두어 JS 없이도 동작하게 한다. 스크롤 애니메이션은 prefers-reduced-motion 존중(components/Counter.tsx·globals.css 선례) |
MUST |
| PJ-13 (v1.8 개정) | 반응형 카드 노출: 360 px 1장 / md 2장(w-[calc(50%-12px)] — 2×(50%−12px)+24px = 100%로 대수적 정확값) / desktop(1240 px)에서는 스크롤 트랙이 아니라 desktop:grid desktop:grid-cols-3 desktop:overflow-visible 정적 3열로 전환하고 카드는 desktop:w-full로 둔다. 데스크톱 카드 폭에 퍼센트 연산을 사용하지 않는다. 근거: Tailwind grid-cols-3은 repeat(3, minmax(0, 1fr))로 전개되어 min-content 넘침을 구조적으로 차단하며, overflow-visible이 해당 요소를 스크롤 컨테이너에서 해제해 스크롤 잔재·불필요한 포커스 가능 스크롤 영역을 함께 제거한다(→ AC-34). 브레이크포인트는 desktop 토큰만 사용한다(R-8.20 · AC-26) |
MUST |
| PJ-14 | 접근성: 트랙 role="group" + aria-roledescription="carousel", 카드 aria-roledescription="slide" + aria-label="N개 중 M번째", 버튼 aria-label 및 aria-controls, 카드 제목은 <h3> |
MUST |
| PJ-15 (v1.8 신설) | 카드에 min-w-0 과 텍스트 줄바꿈(break-words, 국문은 R-9.16 break-keep)을 적용한다. flex-shrink: 0인 플렉스 아이템은 콘텐츠의 min-content 폭 이하로 줄지 않으므로, standardsTrack(IEC/TC 100/TA 17)·deliverables[].ref(ISO/IEC TR 30189)처럼 /를 포함해 기본 줄바꿈 기회가 없는 문자열이 폭 수식과 무관하게 트랙을 넘치게 할 수 있다. PJ-13의 그리드 전환은 데스크톱만 보호하므로, 모바일·태블릿 구간은 이 규칙으로 보호한다 |
MUST |
| PJ-16 (v1.8 신설) | 스크롤바를 숨기는 경우([scrollbar-width:none] 등) 잔여 넘침이 시각적 단서 없이 은폐되므로, AC-34 검증을 반드시 동반한다 |
MUST |
6.2 Members (/members) — PR-01 적용
레거시 실측: 재학 16명(교수 1 · Ph.D. 1 · Ph.D. Candidate 4 · Ph.D. Student 5 · M.S. Candidate 3 · M.S. Student 2), 졸업생 60명(2007~2026).
| ID | 요구사항 | 수준 |
|---|---|---|
| M-01 | 현행 placeholder(연구원 A~G) 전량을 ISL-2026/member.html 실데이터로 교체한다. 재학 16명 + 졸업생 60명 = 76명 전원 보존 |
MUST |
| M-02 | 지도교수 피처 스프레드: 고석주 교수 / Prof. Seok-Joo Koh, 이메일 sjkoh@knu.ac.kr, 개인 홈페이지(ISL-2026/sjkoh/) 및 GitHub(github.com/sjkoh12) 링크 |
MUST |
| M-03 | 재학 연구원을 학위 과정별로 그룹핑하고, 레거시의 Candidate/Student 구분을 보존한다 |
MUST |
| M-04 | 소속 학과가 컴퓨터학부와 다른 연구원(정보보호학과·정보과학과·과학기술학과·ICT융합학과·컴퓨터학부 등 8명)은 소속 표기를 함께 노출한다 | MUST |
| M-05 | 졸업생 60명을 졸업 연도 역순으로 게시하고, 학위·졸업시점·전공·현 소속을 표기한다 | MUST |
| M-06 | 졸업생 목록은 최근 3년을 기본 노출하고 나머지는 더 보기로 확장한다. 확장 시 60명 전원이 노출되어야 한다 (PR-01) |
SHOULD |
| M-07 | 이름 표기 형식을 통일한다: 한글명 (Romanized Name). 외국인 연구원(Hoang Anh Dang 등)은 원문 그대로 표기 |
MUST |
| M-08 | 인원 통계 카운터는 배열 길이에서 도출한다 (H-06 원칙 동일 적용) | MUST |
| M-09 | 개인 이메일·연락처는 지도교수 외 게시하지 않는다 | MUST |
| M-10 | 졸업생의 현 소속 문구(He is now with ...)는 레거시 원문 정보를 보존하되, 국문 페이지 맥락에 맞게 소속명만 추출해 표기해도 무방하다 |
SHOULD |
6.3 Publications (/publications) — PR-01 + PR-04 적용
레거시 실측: paper-international.html 68건(저널 67 + 학술대회 1) · paper-domestic.html 80건(KCI 등재 48) · patent.html 75건 = 총 223건.
| ID | 요구사항 | 수준 |
|---|---|---|
| P-01 (v1.5 개정) | 3개 카테고리를 사용한다: International Journal & Conference / Domestic Journal & Conference / Patent. D-01 확정(v1.5): PR-04의 1번 라벨 International Conference는 대응 레거시 원본이 없어 실측 0건이었고, 2번 라벨의 부분집합으로 범위가 중첩되므로 단독 카테고리를 폐기한다. 국제 학술대회 논문(실측 1건)은 International Journal & Conference에 포함해 보존한다 |
MUST |
| P-02 | 카테고리는 레지스트리 상수 1곳에 정의하고, 개별 레코드는 category 판별 필드만 갖는다. 라벨 변경·교체가 레지스트리 수정만으로 완결되어야 한다 |
MUST |
| P-03 | 223건 전량 보존 — 어떤 카테고리에도 배정되지 않아 누락되는 레코드가 있어서는 안 된다. (v1.5 확인: D-01 확정으로 카테고리가 3개로 축소되었으나 intl-conf 배정 레코드가 0건이었으므로 축소는 무손실이다. 실측 68 + 80 + 75 = 223) |
MUST |
| P-04 | 레거시 paper-international.html은 저널과 학술대회 논문이 혼재되어 있다(학술대회 1건 확인: International Conference on ICTC, 2023). 이관 시 게재처 문자열로 판별해 분류한다 |
MUST |
| P-05 | 기본 정렬은 발행 연월 내림차순, 동일 연월 내에서는 레거시 게시 순서를 보존한다 | MUST |
| P-06 (v1.1 개정) | 카테고리 필터 UI를 제공한다. 필터 상태는 URL 경로(/publications/<slug>)에 반영되어 공유 가능한 링크가 되어야 한다. 슬러그는 §7.2 PubCategory 값을 그대로 사용한다. 구현 방식은 §8.5의 렌더링 제약을 반드시 따른다 |
MUST |
| P-06a (v1.1 신설) | 카테고리 내비게이션은 next/link의 <Link>로 구현한다. window.history.pushState 직접 호출·useSearchParams() 사용 금지 (§8.5 R-8.11~8.14) |
MUST |
| P-07 | 전체 223건을 단일 화면에 일괄 렌더하지 않는다. 연도별 그룹 헤더 + 지연 확장 또는 페이지네이션으로 초기 렌더 부하를 제한하되, 전 레코드가 접근 가능해야 한다 (§9.4) | MUST |
| P-07a (v1.1 신설) | 레코드 목록 자체는 서버 컴포넌트에서 정적 HTML로 렌더되어야 한다. 목록 데이터를 클라이언트 컴포넌트 내부나 <Suspense> 경계 안쪽에 두어 정적 문서에서 누락시켜서는 안 된다 (§8.5 R-8.15). 근거: JS 미실행 환경·크롤러에서도 PR-01의 전 레코드가 문서에 존재해야 한다 |
MUST |
| P-08 | 국내 논문의 (KCI) 등재 표시를 배지로 보존한다 (48건) |
MUST |
| P-09 | 특허 레코드는 다음을 모두 보존한다: 발명자 목록, 출원번호·출원일, 등록번호·등록일(있는 경우), 국가(한국/US). 출원/등록 상태를 구분 표기한다 | MUST |
| P-10 | 파생 통계 카운터: 카테고리별 건수를 배열에서 도출해 표기 | SHOULD |
| P-11 | DOI·원문 링크는 레거시에 존재하지 않으므로 이번 범위에서 제외한다. 스키마에 선택 필드로 예약만 한다 | MUST |
| P-12 | 저자명·논문 제목·게재처 표기는 레거시 원문을 그대로 보존한다. 임의 축약·재배열·번역 금지 (PR-01) | MUST |
| P-13 | 국문·영문 제목이 혼재하는 국내 논문 목록에서 언어를 통일하지 않는다 (PR-01) | MUST |
6.4 Lectures (/lectures) — PR-01 적용
레거시 실측: 2016 Fall ~ 2026 Spring, 약 20개 학기, 과목명 + 학수번호 형식.
| ID | 요구사항 | 수준 |
|---|---|---|
| L-01 | 현행 placeholder 3건(사물인터넷 개론, 메타버스 상호운용성과 표준 등)을 실제 강의 이력으로 교체한다. 전 학기 전 과목 보존 |
MUST |
| L-02 | 학기별(Spring/Fall + 연도) 그룹핑을 레거시 구조 그대로 보존한다 | MUST |
| L-03 | 최근 3개 학기를 기본 노출하고 이전 이력은 전체 이력 보기로 확장한다. 확장 시 전 학기가 노출되어야 한다 (PR-01) |
SHOULD |
| L-04 | 과목 레코드: 학수번호(COMP 0414 등), 과목명(EN), 학부/대학원 구분 |
MUST |
| L-05 | 과목명 한글 번역은 레거시에 없으므로 신규 창작하지 않는다. 영문 원문을 정본으로 노출한다 (→ §12 D-02) | MUST |
| L-06 | Fall 2023 — No Class (Sabbatical)과 같은 비강의 학기도 이력에 보존한다 (PR-01) |
MUST |
| L-07 | 동일 과목이 여러 분반(ITEC 401003, ITEC 401004)으로 개설된 경우 분반을 합치지 않고 보존한다 (PR-01) |
MUST |
6.5 Standardization (/standardization) — PR-01 적용
레거시 실측: 기구 6곳 / 표준 문서 약 55건 / 활동 기간 2000~현재.
| 기구 | 활동 기간 | 주요 산출물 | 구분 |
|---|---|---|---|
| IEC TC100 (Multimedia Systems and Equipment) | 2018 ~ 현재 | IEC 63614(Metaverse) 4건, IEC 63478(QoE, WG11 Convenor) 3건, IEC 63479(Infotainment) 3건, IEC 63246(CCIS) 4건 | 국제 |
| ISO/IEC JTC1/SC41 (IoT and Digital Twin) | 2020 ~ 현재 | ISO/IEC TR 30189 2건 | 국제 |
| ITU-T SG20 (IoT Services based on VLC) | 2018 ~ 2020 | Y.4465, Y.4474 | 국제 |
| ITU-T SG13 (Mobility Management) | 2002 ~ 2012 | Q.Sup52, Q.1706~1709, Y.2052, Y.2809 등 7건 | 국제 |
| ISO/IEC JTC1/SC6 WG7 (Network and Transport) | 2000 ~ 2014 | ECTP(14476), RMCP(16512), MMC(24793), FN-PSR(29181) 계열 다수 | 국제 |
| TTA/PG425 (가시광 통신 기반 사물인터넷) | 2018 ~ 2020 | TTAK.KO-10.1158 part1~3 | 국내 |
| ID | 요구사항 | 수준 |
|---|---|---|
| S-01 | 현행 4개 기구(oneM2M, W3C WoT, IETF QUIC, OMA LwM2M)는 실제 기여 이력이 아닌 placeholder이므로 전량 교체한다 |
MUST |
| S-02 | 국제 표준화 / 국내 표준화 2개 섹션으로 구분한다 (레거시 구조 보존) | MUST |
| S-03 | 기구별 카드에 활동 기간과 역할(예: WG11 Convenor, WG30(TA17))을 명시한다 |
MUST |
| S-04 | 표준 문서는 기구 → 워킹그룹/프로젝트 → 문서의 3단 계층으로 표현하고, 문서 55건 전량을 보존한다 | MUST |
| S-05 | 문서 상태(IS / TS / TR / CDV / WDTR / In Progress)를 배지로 구분 노출한다 |
MUST |
| S-06 | In Progress 문서(IEC WDTR 63614-4, IEC CDV 63478-3, ISO/IEC CDTR 30189-2)는 진행 중임이 시각적으로 명확해야 한다 |
MUST |
| S-07 | 기구 카드 강조색은 §8.3 홀수/짝수 교차 규칙을 따른다 | MUST |
| S-08 | 카운터는 기구 수·문서 수를 배열에서 도출한다 | MUST |
| S-09 | 5대 연구 기둥 중 기둥 4(A2A/ACP 개방형 표준) 와의 연결 서술을 도입부에 배치해, 과거 표준화 역량이 신규 연구 방향으로 이어짐을 드러낸다 | SHOULD |
7. 데이터 모델 및 마이그레이션 명세
7.1 데이터 배치 원칙
| ID | 요구사항 | 수준 |
|---|---|---|
| DM-01 | 콘텐츠 데이터는 페이지 컴포넌트에서 분리해 content/ 디렉터리의 타입 지정 모듈로 이관한다 (content/members.ts, content/publications.ts, content/lectures.ts, content/standards.ts) |
MUST |
| DM-02 | 각 모듈은 명시적 TypeScript 인터페이스를 export 한다. any 사용 금지 |
MUST |
| DM-03 (v2.0 개정) | 데이터는 **실시간 동적 런타임 페칭(force-dynamic, cache: 'no-store')**으로 백엔드 API(http://localhost:8080/api/v1)로부터 조회한다. content/*.ts 모듈은 백엔드 미가동/장애 시의 그레이스풀 폴백(Fallback) 데이터셋으로 유지한다. 6개 데이터 라우트는 ƒ Dynamic으로 렌더링되며, 4개 프레임워크 라우트는 ○ Static을 유지한다 (§8.5 R-8.16, §10 AC-17) |
MUST |
| DM-04 | 각 페이지 상단의 // CUSTOMIZATION HOOK 주석 규약(DESIGN.md "콘텐츠 우선" 원칙)은 content/ 모듈로 이전하되 규약 자체는 유지한다 |
MUST |
7.2 스키마 정의 (계약)
// content/members.ts
type Degree = "Professor" | "PhD" | "PhDCandidate" | "PhDStudent" | "MSCandidate" | "MSStudent";
interface Member {
ko: string; // "최동규" (외국인 연구원은 원문 표기)
en: string; // "Dong-Kyu Choi"
degree: Degree;
affiliation?: string; // 컴퓨터학부 외 소속일 때만 (M-04)
}
interface Alumnus {
ko: string;
en: string;
degree: "PhD" | "MS";
graduatedAt: string; // "2026-08" (ISO 8601 부분 표기)
major?: string; // "Computer Science and Engineering"
currentPosition?: string; // "Daegu Catholic University (대구가톨릭대학교) as Professor"
}
// content/publications.ts
// D-01 확정(v1.5) 후 3개 카테고리. 라벨 문자열은 레지스트리에서만 정의한다 (P-02).
type PubCategory =
| "intl-journal-conf" // International Journal & Conference
| "domestic-journal-conf" // Domestic Journal & Conference
| "patent"; // Patent
interface Publication {
category: PubCategory; // P-02: 판별 필드
title: string; // P-12: 원문 보존
authors?: string; // P-12: 원문 보존
venue?: string; // 저널/학술대회명
volume?: string; // "Vol. 23, pp. 4490~4505"
publishedAt: string; // "2026-04" (P-05 정렬 키)
kci?: boolean; // P-08
doi?: string; // P-11: 예약 필드, 현재 미사용
}
interface Patent {
category: "patent";
title: string;
inventors: string; // "고석주, 정중화, 남혜빈, 최동규"
applicationNo: string; // "2023-0180751"
applicationAt: string; // "2023-12-13"
registrationNo?: string; // "2963109"
registrationAt?: string; // "2026-05-06"
country: string; // "한국" | "US"
publishedAt: string; // 정렬 키 (= applicationAt 의 연월)
}
// content/lectures.ts
interface Semester {
term: "Spring" | "Fall";
year: number;
courses: { code: string; en: string; note?: string }[]; // L-05, L-06, L-07
}
// content/standards.ts
type DocStatus = "IS" | "TS" | "TR" | "CDV" | "WDTR" | "InProgress";
interface StandardsBody {
org: string; // "IEC TC100"
full: string; // "Multimedia Systems and Equipment"
scope: "international" | "domestic"; // S-02
period: string; // "2018 ~ Present"
role?: string; // "WG11 Convenor"
projects: {
wg: string; // "WG12"
name: string; // "Multimedia Systems and Equipment for Metaverse (IEC 63614)"
documents: { title: string; ref: string; status: DocStatus; publishedAt?: string }[];
}[];
}
// content/projects.ts (v1.7 신설 · §6.1.2)
// ⚠️ StandardsBody.projects(WG 단위 표준화 프로젝트)와 의미가 다르다. 이름 재사용 금지 (PJ-01).
interface ProjectDeliverable {
title: string; // standards.ts 문서 제목 원문
ref: string; // "IEC 63246" / "ISO/IEC TR 30189"
status: DocStatus; // 기존 유니온 재사용
}
interface ResearchProject {
slug: string; // "iot-standards" | "ccis" | "vlc-iot"
title: string; // 레거시 card-title 원문
abstract: string; // 레거시 card-text 원문 — 바이트 동일 보존 (PJ-03)
keywords: string[]; // 전 원소가 abstract 부분문자열이어야 함 (PJ-06)
standardsTrack?: string; // "IEC/TC 100/TA 17" — 레거시 확장 섹션 원문
standardsOrg?: string; // standards.ts `org` 조인 키
period?: string; // standards.ts `period` 에서 도출 (PJ-04)
deliverables: ProjectDeliverable[]; // standards.ts documents 에서 도출 (PJ-05)
funder?: string; // 현재 전건 미확보(D-07). 값 없으면 UI 미렌더 (PJ-07)
}
7.3 마이그레이션 절차
| ID | 요구사항 | 수준 |
|---|---|---|
| MG-01 | 추출은 재현 가능한 스크립트로 수행하고, 스크립트를 scripts/ 하위에 커밋한다. 수작업 복사·붙여넣기 금지 |
MUST |
| MG-02 | 추출 후 건수 대조 검증을 수행한다. 기대값: 국제 68 / 국내 80 / 특허 75 / 표준 문서 55 / 재학 16 / 졸업생 60 / 학기 약 20 | MUST |
| MG-03 | 한글·특수문자(~, ·, ‧, o, 전각 기호) 인코딩 손실이 없어야 한다. 레거시 파일에 BOM()이 존재하므로 제거한다 |
MUST |
| MG-04 | 날짜는 전부 ISO 8601로 정규화한다 (2026년 6월 → 2026-06, April 2026 → 2026-04, 2023.12.13 → 2023-12-13) |
MUST |
| MG-05 | 레거시에 없는 정보를 추정·창작하지 않는다. 누락 필드는 optional로 두고 UI에서 조건부 렌더한다 (PR-01) | MUST |
| MG-06 | 이미지 자산은 실제 사용분만 public/으로 이관한다. 원본 총량 11.6MB(image/ 3.4MB + assets/ 8.2MB)를 무조건 복사하지 않는다 |
MUST |
| MG-07 | 이관 이미지는 WebP 변환 및 next/image 적용 |
SHOULD |
| MG-08 | 마이그레이션 완료 후 렌더 HTML 전수 스캔으로 구 정체성 잔재 0건을 확인한다 (검사어: 사물인터넷 표준, IoT Standards, MCM, 메타버스 상호운용성, 홍길동, placeholder). 단, 논문·특허 제목에 포함된 도메인 용어는 실데이터이므로 예외로 취급한다 |
MUST |
⚠️ MG-08의 중요한 예외: 레거시 실적에는
사물인터넷,메타버스,oneM2M등이 논문 제목·표준 문서명으로 실재한다(예: IEC 63614 Multimedia Systems and Equipment for Metaverse). 이는 구 정체성 잔재가 아니라 보존해야 할 실데이터다(PR-01). 잔재 검사는 연구실 정체성 서술 영역(Header/Footer/metadata/Home 소개문)에 한정해 적용한다.
8. 디자인 시스템 준수 규격
정본은 refer_landing_page/docs/DESIGN.md("Issue 01")이며, 본 절은 위반 시 리뷰에서 반려되는 항목만 발췌한다.
8.1 색상 토큰 (변경 금지)
| 토큰 | 값 | 용도 |
|---|---|---|
ink / ink-soft / ink-mute |
#0A0A0A / #262420 / #6B655B |
본문·괘선 |
ivory / paper / line |
#F5F1E8 / #ECE6D6 / #D8D1C0 |
종이 배경 / 인셋 / 헤어라인 |
vermillion / vermillion-dark |
#D9342B / #A8231C |
강조 (Hot) — 최초 커밋 이래 불변 |
cobalt / cobalt-dark |
#4E77FF / #345AD2 (v1.13 갱신) |
강조 (Cool) — Primary |
실측 대비 (v1.13 기준선 · WCAG 2.1 재계산)
| 토큰 | ivory(L) |
paper(L) |
ivory(D) |
paper(D) |
라이트↔다크 반전 대비 |
|---|---|---|---|---|---|
cobalt #4E77FF |
3.45 | 3.12 | 4.82 | 4.37 | 1.00 ❌ (R-8.28 위반) |
cobalt-dark #345AD2 |
5.26 | 4.76 | 6.57 | 5.96 | 2.08 ✅ |
vermillion #D9342B |
4.16 | 3.77 | 5.01 | 4.54 | 1.25 ❌ (→ D-13) |
vermillion-dark #A8231C |
6.38 | 5.77 | 6.72 | 6.09 | 2.58 ✅ |
v1.11 갱신 근거: 커밋
eaddc4f가cobalt를#1B3A8A→#4A7CE8,cobalt-dark를#122863→#3462CC로 변경했다.#4A7CE8은 사용자 지정 값이므로 유지하되,cobalt-dark는paper배경에서 4.48:1로 미달하므로 D-10 결정에 따라#32549E(paper 5.82:1)로 재조정한다.vermillion(#D9342B)은 변경된 적이 없다 —eaddc4f의 커밋 메시지…and secondary to #D9342B는 현상 유지의 서술이다(→ §12.1 D-10 상세). v1.12: 두 강조색의-dark변형(#A8231C/#32549E)은 소형 텍스트 전경뿐 아니라text-[0.65rem]상태 칩의 배경으로도 사용된다 —ivory전경만으로 6.386.43(라이트) / 6.576.72(다크)를 확보한다(→ R-8.26 · R-8.29 · §12.1 D-10 보론).v1.13 갱신 근거: 커밋
ca4a7ee·8db16e4가cobalt를#4A7CE8→#4E77FF,cobalt-dark를 D-10 확정값#32549E가 아닌#345AD2로 설정했다.#4E77FF는 사용자 지정 Primary이므로 유지하며,#345AD2도paper4.76으로 R-8.26 바닥값을 충족하므로 D-10 확정값을#345AD2로 개정한다(단 여유가 0.26뿐이라 §12.2 R-4로 등재). 다만--cobalt의 반전 대비가 1.00으로 R-8.28을 다시 위반하며 — 이는 v1.11에서 D-10의 근본 원인으로 규명한 실패 유형의 재발이다 — AC-45 게이트가-dark2개 토큰만 검사하도록 구현되어 검출하지 못했다(→ R-8.28 개정 · AC-45 개정 · §12.1 D-12 상세). 4개 색 변경 커밋 전부 본문이 비어 있어 R-8.1·R-8.27의 대비 재산정표 첨부 의무가 4회 연속 미이행이다.
R-8.1 신규 색 토큰 추가 금지. 색상 값 변경 시 tailwind.config.ts와 app/globals.css의 :root CSS 변수를 반드시 함께 수정하며, R-8.26~R-8.28의 대비·반전 제약을 재산정해 첨부한다.
R-8.2 brand / accent 별칭은 레거시 호환 전용이며 신규 코드에서 사용 금지.
8.2 타이포그래피 · 유틸리티 클래스
R-8.3 지정 서체만 사용한다 — 영문 디스플레이 Fraunces(font-display), 국문 헤드라인 Noto Serif KR(headline-ko), 본문 산세리프 Pretendard/Inter(font-sans).
R-8.4 기존 유틸리티 클래스를 우선 사용한다: .container-content, .display, .display-sm, .headline-ko, .kicker, .pull-quote, .reveal. 동등 기능의 임의 클래스 신설 금지.
8.3 강조색 시맨틱 계약
R-8.5 vermillion = Agent Engineering / Orchestration(홀수 항목), cobalt = MCP / A2A Protocol(짝수 항목). 목록 렌더 시 인덱스 기반 교차 배정을 따른다.
- [v1.13 · 적용 범위 명시] 본 계약은
docs/DESIGN.md§2 "의미 있는 색(Semantic accent pairing)"의 정본 서술과 동일한 내용이며, 목록 교차 배정뿐 아니라 단일 강조 표면(히어로 강조어·섹션 키커 등)에도 적용되는지는 확정되지 않았다. 커밋2441f35가 히어로의Orchestration강조어를 vermillion → cobalt로 변경해 같은 페이지 안에서 규약이 둘로 갈린 상태이므로 D-12로 이관한다. 어느 쪽으로 확정하든 코드와docs/DESIGN.md가 같은 값을 말해야 한다(→ AC-23 · AC-50).
8.4 컴포넌트 재사용
R-8.6 기존 7종을 우선 재사용한다: Header, Footer, PageHeader, SectionLabel, Reveal, Counter, Marquee. 신규 컴포넌트는 기존 조합으로 구현 불가함을 리뷰에서 입증한 경우에만 추가한다.
R-8.7 PageHeader의 index prop은 IA 순서를 따른다 — Home 1 / Members 2 / Publications 3 / Lectures 4 / Standardization 5.
R-8.8 [중요 제약] Counter는 정수 전용이다. 내부에서 Math.round()로 표시값을 산출하므로 소수를 넘기면 반올림된 값이 표시되고, prefers-reduced-motion 경로에서는 반올림이 적용되지 않아 모션 설정에 따라 값이 달라진다. 소수 지표가 필요하면 Counter의 소수 대응 확장을 선행 과제로 처리한다.
R-8.9 그리드에서 gap-px bg-line 헤어라인 기법은 테두리 없는 카드 전용이다. border border-ink를 가진 카드에는 bg-line을 함께 걸지 않는다.
R-8.10 항목 수가 열 수로 나누어떨어지지 않는 그리드는 col-span으로 마지막 행을 채운다. 빈 트랙이 배경색 블록으로 노출되어서는 안 된다 (5개 항목 → lg:grid-cols-6 기준 2/2/2 · 3/3 조판이 확립된 패턴).
8.5 Next.js 렌더링 제약 (v1.1 신설)
출처: 개발 팀장(Agy)의 기술 이의제기(Job
175860e4)를 계기로, 본 프로젝트의 실제 환경(Next.js 14.2.35,refer_landing_page/)에서 4가지 구현 방식을 직접 빌드해 실측한 결과다. 추정이 아닌 재현된 관측치이며, 프로브 라우트는 검증 후 전량 삭제해 저장소에 남기지 않았다.
실측 결과표
| # | 구현 방식 | 빌드 결과 | 정적 HTML에 담기는 내용 |
|---|---|---|---|
| 1 | Client Component에서 useSearchParams() — <Suspense> 없음 |
❌ 빌드 실패useSearchParams() should be wrapped in a suspense boundary at page "/…" → Export encountered errors |
— |
| 2 | useSearchParams() — <Suspense> 있음 |
✅ ○ (Static) |
경계 안쪽은 fallback만 저장됨. 경계 바깥의 서버 렌더 콘텐츠는 정상 프리렌더됨 |
| 3 | Client useState + window.history.pushState |
✅ ○ (Static) |
클라이언트 초기 상태만 저장됨 (cat=all). 공유 링크 진입 시 마운트 후 보정 → 비필터 상태가 먼저 표시됨 |
| 4 | Server Component의 searchParams prop 사용 |
⚠️ ƒ (Dynamic) — 정적 생성 탈락 |
매 요청 서버 렌더 |
| 5 | [category] 세그먼트 + generateStaticParams() |
✅ ● (SSG) — 카테고리별 HTML 4개 생성 |
카테고리 값이 HTML에 그대로 포함됨 (cat=patent) |
도출 규칙
R-8.11 [금지] Server Component 페이지에서 searchParams prop을 사용하지 않는다. 실측 #4에서 확인된 대로 해당 라우트가 ƒ (Dynamic)으로 전환되어 DM-03·NF-03을 직접 위반한다. 본 프로젝트에서 정적 생성을 깨뜨리는 유일하게 확인된 경로다.
R-8.12 [금지] useSearchParams()를 <Suspense> 경계 없이 호출하지 않는다. 실측 #1에서 프로덕션 빌드가 중단됨을 확인했다.
R-8.13 [제한적 허용] useSearchParams() + <Suspense> 조합은 정적 생성을 깨뜨리지 않는다(실측 #2에서 ○ Static 유지 확인). 다만 경계 안쪽 콘텐츠가 정적 HTML에서 누락되므로, 필터 컨트롤 등 소규모 UI에 한해 사용하고 레코드 목록에는 사용하지 않는다(R-8.15).
R-8.14 [금지] 라우팅 목적의 window.history.pushState 직접 호출을 하지 않는다. Next 라우터를 우회하므로 뒤로/앞으로 가기 시 URL만 바뀌고 UI가 갱신되지 않으며, 이를 보정하려면 popstate 리스너를 직접 등록·해제해야 한다. 카테고리 이동은 next/link로 처리한다(P-06a).
R-8.15 [필수] 대량 레코드(Publications 223건, Alumni 60명, 표준 문서 44건)는 서버 컴포넌트에서 정적 HTML로 렌더한다. 클라이언트 상태나 <Suspense> 경계 안쪽에 넣어 정적 문서에서 누락시키지 않는다. 실측 #2에서 경계 바깥 서버 렌더 콘텐츠는 프리렌더된다는 점이 확인되었으므로, 목록은 바깥에 두고 인터랙션만 안쪽에 두는 분리가 가능하다.
R-8.16 [표기] generateStaticParams()를 사용하는 라우트는 빌드 리포트에서 ○ (Static)이 아니라 ● (SSG) 로 표기된다. 두 표기 모두 "빌드 타임 정적 프리렌더"이며 요구사항을 충족한다. 수용 기준의 판정은 §10 AC-17의 개정된 문구를 따른다.
8.6 레이아웃 컨테이너 아키텍처 · 브레이크포인트 토큰 (v1.6 신설)
Job 343b5808 검증에서 본문 좌우 여백·최대 폭 미적용(B1)이, 개발 팀장 이의제기(Job 2560771b)에서 그 수정 방식의 확장성 제약이 각각 확인되었다. 아래 규칙은 D-06 확정 사항이다.
R-8.17 [계층 분리 · 필수] 레이아웃은 3계층으로 분리한다.
<main>(app/layout.tsx) — 뷰포트 전체 폭을 유지한다.max-w-*/px-*/container-content를 부여하지 않는다.- 라우트 최상위 래퍼 — 각 페이지 파일의 루트
<div>에container-content를 부여해 본문 여백(24/40/48/64 px)과 최대 폭(78 rem = 1248 px) 중앙 정렬을 확보한다. - Full-bleed 밴드 — 전체 폭 배경 밴드·구획선·마퀴 티커는 2계층 래퍼 바깥(즉
<main>직속)에 배치한다.
R-8.18 [금지] Full-bleed 연출을 위해 container-content 자식에서 w-screen 또는 -mx-[50vw] 계열 탈출 기법을 사용하지 않는다. 현재 html·body에 overflow-x 가드가 전무하므로(실측 확인), 폭 제한 컨테이너 내부의 w-screen은 좌측 기준점이 부모 콘텐츠 박스여서 우측으로 넘쳐 가로 스크롤을 유발하고 R-9.15/AC-19를 위반한다. Full-bleed가 필요하면 R-8.17의 3계층으로 올린다.
R-8.19 [필수] 라우트 래퍼 방식은 신규 라우트 추가 시 누락될 수 있으므로, 빌드 산출 HTML의 모든 라우트에서 <main> 하위에 container-content가 존재함을 자동 게이트로 검증한다(→ AC-25). 이 게이트 없이는 본 아키텍처를 채택하지 않는다.
R-8.20 [토큰] 데스크톱 내비 전환 임계값은 tailwind.config.ts의 theme.extend.screens에 desktop: "1240px" 단일 토큰으로 등록하고 desktop: 변형으로만 사용한다. 임의값 클래스(min-[1240px]:)를 소스에 직접 쓰지 않는다.
- 실측 확인: Tailwind v3는
extend로 추가한 스크린도 min-width 값 기준으로 정렬해 출력하므로(1024 → 1240 → 1280 → 1536순서 확인),2xl등 상위 브레이크포인트를 덮어쓰는 캐스케이드 사고는 발생하지 않는다.screens전체를 재정의할 필요가 없다. - 주의:
lg(1024px)와desktop(1240px)이 공존하므로, 헤더 내 데스크톱/모바일 전환은desktop:으로만 통일한다. 동일 속성에lg:와desktop:을 혼용하면 1024–1239 px 구간에 의도치 않은 중간 상태가 생긴다(B2가 정확히 이 사고였다).
8.7 색 토큰 알파 계약 (Color Token Alpha Contract) (v1.9 신설)
디자인 토큰은 app/globals.css의 CSS 커스텀 프로퍼티와 tailwind.config.ts의 theme.extend.colors가 한 쌍으로 동작한다. 이 쌍의 계약이 깨지면 lint·tsc·빌드가 모두 통과하는 채로 화면만 무너진다 — 실제로 그 사고가 발생했으므로(§12.1 D-09 상세) 계약을 명문화한다.
R-8.21 [필수 · 공백 구분] --*-rgb 커스텀 프로퍼티의 값은 반드시 공백 구분 3-숫자로 정의한다(--ink-rgb: 10 10 10;). 쉼표 구분(10, 10, 10)을 금지한다.
- 근거: Tailwind는
<alpha-value>를 포함한 색을rgb(var(--ink-rgb) / var(--tw-text-opacity, 1))형태로 전개한다. 값이 쉼표 구분이면 치환 결과가rgb(10, 10, 10 / 1)이 되는데, 이는 CSS Color 4의 현대 문법(공백+슬래시)도 레거시 문법(전량 쉼표)도 아니어서 무효다. 무효 선언은 invalid at computed-value time 으로 처리되어 해당 속성이 통째로 적용되지 않는다. 빌드는 성공하고 CSS 파일에도 규칙이 남으므로 어떤 정적 게이트도 이를 잡지 못한다. --ink: rgb(var(--ink-rgb));형태의 파생 변수는 공백 구분에서도 그대로 유효하므로 함께 유지한다.
R-8.22 [필수 · <alpha-value> 보존] theme.extend.colors의 모든 토큰은 rgb(var(--*-rgb) / <alpha-value>) 형태로 선언한다. var(--ink)처럼 알파 자리표시자가 없는 형태로 축약하지 않는다.
- 근거(실측): 알파 자리표시자가 없으면 Tailwind는 슬래시 수식자 유틸리티를 오류 없이 조용히 생략한다. 독립 프로브 결과 —
colors.ivory = "var(--ivory)"일 때bg-ivory/85·text-ivory/50·border-ivory/15는 출력 CSS에 단 한 줄도 생성되지 않았고,colors.old = "rgb(var(--ivory-rgb) / <alpha-value>)"일 때는rgb(var(--ivory-rgb) / 0.85)로 정상 생성되었다. - 유틸리티가 생성되지 않으면 배경은 투명, 테두리는 Preflight 기본색
#e5e7eb(팔레트 외 회색), 텍스트는 부모 색 상속으로 대체되어 팔레트를 벗어난 화면이 된다.
R-8.23 [금지 · 토큰 우회] 디자인 토큰으로 표현 가능한 색을 컴포넌트의 인라인 style 속성이나 리터럴 색값(#ffffff 등)으로 우회 지정하지 않는다. 인라인 style은 다크 모드 변형(dark:)보다 항상 우선하므로 테마 반전이 무력화되고 대비 요구(R-9.6)가 조용히 깨진다.
- 활성 내비 배지처럼 대비가 임계에 가까운 요소에는
opacity-*유틸리티를 사용하지 않는다. 요소 불투명도는 전경·배경을 함께 합성해 대비를 낮추며, 실측상opacity-90만으로 4.69:1 → 4.05:1(라이트)로 떨어져 AA 미달이 된다.
R-8.24 [필수 · 헤더 가로 예산] 데스크톱 헤더(브랜드 + 내비 + 토글)의 소요 폭은 1240 px 뷰포트의 가용 폭 1112 px과 최대 폭 상한(78 rem) 적용 시의 가용 폭 1120 px을 모두 초과하지 않아야 한다. 헤더에 좌우 패딩·간격·마진을 추가하는 변경은 예산 재계산을 동반해야 하며, 예산 초과 시 내비 라벨이 2줄로 접히는 회귀(§8.6 B2)가 재발한다.
- 실측 기준선(commit
43c75da): 소요 1057.6 px / 가용 1112 px / 여유 +54.4 px, 내비 전량font-bold보정 시 +22.7 px. container-content의 최대 폭이 78 rem(1248 px)로 상한이므로, 1280 px 이상에서도 가용 폭은 1120 px에서 고정된다. 즉 뷰포트를 넓혀도 헤더 넘침은 해소되지 않는다 — 넓은 화면 전용 마진(xl:mr-16등)은 예산을 악화시키기만 한다.
R-8.25 [금지 · 콘텐츠 중복] (v1.10 신설) 서로 다른 두 라우트가 실질적으로 동일한 <main> 콘텐츠를 정적 HTML로 생성해서는 안 된다.
- 근거: 검색 엔진은 중복을 벌점 처리하지는 않으나 어느 URL을 정본으로 삼을지 스스로 선택하므로, 내부 링크·사이트맵이 가리키는 URL과 색인되는 URL이 어긋날 수 있다. 또한 산출물 크기가 이유 없이 늘고, 한쪽만 수정되는 표류(drift) 결함이 구조적으로 가능해진다.
- 인덱스 라우트는 하위 라우트의 본문을 재사용하는 대신 고유한 집계·요약 콘텐츠를 갖는다(→ IA-03).
- 불가피하게 동일 콘텐츠를 두 URL에 노출해야 한다면
metadata.alternates.canonical지정을 필수로 하며, 그 경우에도 R-8.25의 예외임을 §12.1에 결정 항목으로 기록한다. - 자동 검증: AC-41.
R-8.26 [필수 · 강조색 대비 바닥값] (v1.11 신설) 강조 토큰(vermillion·cobalt)의 DEFAULT 변형은 대형 텍스트(≥24 px, 굵게 ≥18.66 px)·도형·테두리·아이콘 전용이며 3:1 이상을 만족한다. 소형 텍스트에는 -dark 변형만 사용하고, -dark는 ivory·paper 양 배경에서 4.5:1 이상이어야 한다.
paper(#ECE6D6)가ivory(#F5F1E8)보다 어두워 항상 더 엄격한 제약이므로 바닥값 산정은paper기준으로 한다. 실측 차이는 약 0.3~0.5 이며,ivory만 보고 통과 판정하면bg-paper카드 내부에서 미달한다.- [v1.14 개정 · 판정 격자] 바닥값 판정은 {라이트, 다크} × {
ivory,paper} 4개 셀 전부에서 수행한다.paper기준 산정 원칙은 다크 테마에도 동일하게 적용된다 — 다크 지면paper(30 28 26)도ivory(18 18 18)보다 밝아 더 엄격하다. v1.12가 지시한 소형 텍스트 라우팅text-cobalt-dark dark:text-cobalt는 라이트 절반만-dark로 보내고 다크 절반은 DEFAULT로 되돌려,bg-paper카드 내부 8곳이 다크 테마에서 4.37로 미달한다(→ AC-51). 이는 본 규칙을 한쪽 테마에만 적용한 계획 오류이며, v1.11 §6.5의 일관성 결함과 같은 형태다. - 실측 근거:
--cobalt: #4A7CE8은ivory3.49 /paper3.16으로 대형 텍스트 기준(3:1)은 충족하나 소형 텍스트 기준은 미달한다. 반면--cobalt-dark: #32549E는 6.43 / 5.82로 양 기준을 충족하며,--vermillion-dark: #A8231C(6.38 / 5.77)와 동일 등급이 되어 두 강조색의-dark슬롯이 대칭을 이룬다. - [v1.12 추가 · 배지·칩 라우팅] 강조색을 배경으로 쓰는 비인터랙티브 상태 칩(
text-[0.65rem]등급)은bg-{accent}-dark+text-ivory를 사용한다. DEFAULT 배경 위에서는 팔레트 내 전경 중 통과 후보가 0~1개뿐이라 설계 여유가 없다 — 실측상bg-cobalt(#4A7CE8) 위 4개 후보(ivory3.49 ·white3.93 ·ink-soft3.94 ·ink5.03) 중 통과는ink1개뿐이고,bg-vermillion(#D9342B) 위ivory는 4.16으로 미달한다.-dark배경은ivory전경만으로 6.386.43(라이트) / 6.576.72(다크) 를 확보한다. - [v1.12 추가 · 짝 칩 등급 일치] 같은 컴포넌트에서 짝을 이루는 강조색 칩은 동일 변형 등급을 사용한다. 한쪽만
-dark로 내리면 두 칩의 상대휘도 대비가 1.19 → 1.54로 악화된다(실측:vermillionL=0.1738 ↔cobalt-darkL=0.0949). 양쪽을-dark로 통일하면 1.01로 균형이 잡힌다(vermillion-darkL=0.0961 ↔cobalt-darkL=0.0949) — 두 강조색의-dark변형이 접근성 등급뿐 아니라 휘도까지 대칭이기 때문이다. - 인터랙티브 내비·토글 요소는 예외로 DEFAULT 배경 +
text-white dark:text-ivory(4.69 / 5.01)를 유지한다. 근거는 §12.1 D-10 상세(부류 A/B 구분) 참조. - [v1.13 개정 ·
text-white의 적용 조건] 위 예외는 배경이 DEFAULT 변형일 때에 한정한다.-dark배경 위 전경은ivory단독을 정본으로 하며text-white·dark:변형을 붙이지 않는다 — 실측bg-cobalt-dark위ivory는 라이트 5.26 / 다크 6.57로 양 테마를 통과하므로 팔레트 외 색이 불필요하다(→ R-8.29). 커밋2441f35가Header.tsx:69,129·CategoryNav.tsx:22의 배경을bg-vermillion→bg-cobalt-dark로 바꾸면서 v1.12가 인정했던text-white의 불가피성이 소멸했다. - 자동 검증: AC-42 · AC-43 · AC-44 · AC-47.
R-8.27 [필수 · 색값 변경 시 재측정 의무] (v1.11 신설) --*-rgb 값을 변경하는 모든 커밋은 해당 토큰이 참여하는 전 전경/배경 조합의 대비를 재산정하고 그 표를 커밋 메시지 또는 리뷰 리포트에 첨부한다.
docs/DESIGN.md의 강조색 교체 안내(커스터마이즈 훅)에 이 제약을 명문화한다. 현행 안내는 "강조색 2개와-dark변형만 교체하면 됩니다"라고 교체 방법만 적고 지켜야 할 대비 제약을 적지 않아, 안내를 그대로 따른 커밋eaddc4f가 라이트 테마 대비를 9.23 → 3.49로 붕괴시켰다. 문서가 사고의 직접 원인이므로 문서 교정이 재발 방지의 일부다.- 색값 변경은 lint·tsc·빌드·기존 게이트 전량을 통과한 채로 화면 접근성만 무너뜨린다 — §12.1 D-09 상세의 알파 계약 사고와 동일한 무성(silent) 실패 유형이며, 이번이 두 번째 발현이다.
R-8.28 [필수 · 명암 반전 계약] (v1.11 신설) html.dark에서 반전되는 모든 토큰은 라이트 값과 다크 값의 상대휘도가 유의미하게 달라야 한다 — 두 값 사이의 대비가 2.0 이상이어야 한다.
- 근거(실측): 변경 전
cobalt는 라이트L=0.0509(#1B3A8A) ↔ 다크L=0.2199(#4D77FF)로 대비 3.13이었으나,eaddc4f이후 라이트L=0.2170(#4A7CE8) ↔ 다크L=0.2199로 대비 1.01이 되었다. 즉 라이트 테마가 다크 테마용 밝기를 그대로 반입했고, 이것이 R-8.26 미달의 직접 원인이다. - 한 토큰만 반전 계약에서 이탈하면 그 시점에는 반대 테마가 우연히 무사할 수 있으나, 반대 테마 값을 조정하는 순간 양 테마가 동시에 무너진다.
- [v1.13 개정 · 검사 범위] 검사 대상은
:root와html.dark양쪽에 정의된 전 토큰이다(현행 10종). 일부 토큰만 검사하는 구현은 본 규칙을 충족하지 않는다 — 현행 게이트는cobalt-dark·vermillion-dark2종만 검사해--cobalt의 반전 대비 1.00을 검출하지 못했다.--vermillion(1.25)도 미달이나 최초 커밋 이래의 상태이므로 D-13으로 분리한다. - 자동 검증: AC-45.
R-8.29 [필수 · 반전 토큰 쌍의 dark: 불필요 원칙] (v1.12 신설) 전경과 배경이 모두 반전 토큰(--*-rgb로 정의되어 html.dark에서 값이 바뀌는 토큰)이면 dark: 변형 없이 양 테마가 성립해야 한다. 어떤 조합에 dark: 변형이 필요하다면 그것은 반전하지 않는 색(white·리터럴 hex 등)이 섞였다는 신호이므로, 팔레트 외 색을 제거할 수 있는지 먼저 검토한다.
- 실측 대조:
bg-cobalt-dark text-ivory는 라이트 6.43 / 다크 6.57로dark:없이 통과한다. 반면bg-cobalt text-ink는 다크에서--ink-rgb가245 241 232로 반전되어 3.49로 미달하므로dark:text-ivory를 수동으로 덧대야 한다 — 반전 계약을 손으로 우회하는 구조이며 R-8.28의 취지에 역행한다. white가 불가피한 경우(bg-vermillion위ivory가 4.16으로 미달하는 인터랙티브 요소)는 AC-47 화이트리스트로 상한을 관리한다. 화이트리스트는 상한이지 허가가 아니다 — 신규 사용처는 먼저-dark배경으로 대체 가능한지 검토한다.- [v1.14 강화 · 강조색
dark:금지] 강조색(cobalt·vermillion및 각-dark)에는dark:변형을 사용하지 않는다. 반전 토큰 위에dark:를 덧대는 것은 반전 계약을 손으로 무력화하는 행위이며, 실제로text-cobalt-dark dark:text-cobalt는 다크 절반을 DEFAULT로 되돌려bg-paper위 4.37을 만든다.-dark단독은 4개 셀 전부(5.26 / 4.76 / 6.57 / 5.96)를 통과한다. - 세 가지 정본 패턴만 사용한다 — ⓐ 대형 텍스트(≥24 px)·도형·테두리·아이콘·SVG:
text-cobalt/bg-cobalt/border-cobalt(3.124.82, 바닥값 3.0), ⓑ 소형 텍스트:6.57, 바닥값 4.5), ⓒ 강조 배경:text-cobalt-dark(4.76bg-cobalt-dark text-ivory(5.26 / 6.57). 세 패턴 모두dark:변형이 없다. - 현행 위반 38건(
dark:text-cobalt28 ·dark:bg-cobalt6 ·dark:hover:border-cobalt2 ·dark:hover:text-cobalt1 ·dark:group-hover:text-cobalt1) 전량이 제거 대상이다. - 자동 검증: AC-47 · AC-48(C11-9) · AC-51.
R-8.30 [필수 · 비텍스트 UI 대비 계약] (v1.13 신설) 테두리·포커스 링·아이콘·상태 도형 등 비텍스트 UI 구성요소(WCAG 2.1 §1.4.11)는 인접색 대비 3:1 이상을 만족한다.
- 슬래시 알파 수식자를 사용한 색은 배경과 합성한 실효색으로 산정한다. 알파는 대비를 조용히 갉아먹으며 토큰 값만으로는 판정할 수 없다 — 실측:
focus:ring-cobalt/50은cobalt자체가 3.45임에도ivory위 합성 후 1.80(다크 2.07),hover:border-cobalt/60은paper위 1.95(다크 2.38)로 양쪽 다 미달한다. - 이는 §12.1 D-09(알파 계약 붕괴)·§12.1 D-10(반전 계약 이탈)에 이은 "알파·토큰 조합이 무성으로 대비를 무너뜨리는" 유형의 세 번째 발현이다. 강조색에 알파 수식자를 붙이는 것은 원칙적으로 지양하고, 필요하면
-dark변형을 불투명하게 사용한다. - 통과 확인된 사용처(회귀 방어 기준선):
hover:border-cobalt3.12 /hover:border-cobalt-dark4.76 /hover:border-vermillion3.77 /ring-vermillion4.16 / 불릿bg-cobalt3.45 / 히어로 SVGvar(--cobalt)3.45 ·var(--vermillion)4.16 (전부paper또는ivory기준 라이트값). - 자동 검증: AC-48(Gate 11 · C11-5).
R-8.31 [필수 · 역할 단위 색 통일 계약] (v1.13 신설) 동일한 클래스 시그니처를 갖는 요소는 단일 색 패턴을 사용한다. 역할은 파일·행이 아니라 시그니처로 식별한다.
- 판정 대상 시그니처(최소): ⓐ 섹션 장식 괘선
h-px w-8 bg-*, ⓑ 섹션 키커font-mono text-xs … uppercase tracking-widest … font-bold, ⓒ 강조 배경 배지·칩의 전경, ⓓ 카드hover:border-*, ⓔ 포커스 인디케이터ring-*. - 판정 기준은 "어떤 색인가"가 아니라 "색 패턴이 하나뿐인가" 이다. 따라서 색 선택 결정(D-12)이 확정되기 전에도 게이트를 구현·운용할 수 있고, 결정이 바뀌어도 게이트는 수정할 필요가 없다.
- 실측 위반: ⓐ
bg-cobalt-dark dark:bg-cobalt6곳 ↔bg-vermillion1곳(DirectionsBlock.tsx:7), ⓑtext-cobalt-dark dark:text-cobalt11곳 ↔text-vermillion1곳(DirectionsBlock.tsx:8), ⓒtext-white dark:text-ivory6곳 ↔text-ivory4곳, ⓓ 4종, ⓔ 2종. - 같은 데이터가 서로 다른 색으로 렌더되는 것도 위반이다 — 지도교수 이메일
sjkoh@knu.ac.kr한 값이members:54(5.26) ·DirectionsBlock:43(4.16) ·Footer:53(paper 위 hover 3.77)에서 3색 3대비로 나타난다. - 예외는 화이트리스트 등재(R-8.32 형식)로만 허용한다.
- 자동 검증: AC-48(Gate 11 · C11-1~C11-4).
R-8.32 [필수 · 게이트 면제 형식 제한] (v1.13 신설) 자동 게이트의 예외는 (파일, 행, 사유) 3-튜플 등재로만 허용하며, 라인 부분문자열 면제(if "…" in line: continue)를 금지한다. 등재 항목이 실제 소스에 존재하지 않으면(고아 항목) 게이트는 실패해야 한다.
- 근거(실측):
run_e2e_tests.py의 AC-44 구현은 면제 조항에"text-vermillion" in line을 두었는데, 위반 판정 정규식이text-(cobalt|vermillion)이므로 vermillion으로 매치된 라인은 예외 없이 그 문자열을 포함한다 — 즉 AC-44의 vermillion 절반이 영구적으로 발화하지 않는다. 실제 소스 4개 라인(lectures:50·members:114·publications:72·DirectionsBlock:8)과 회귀 주입 2건을 동일 로직에 투입해 전부 면제됨을 재현했다. - 나아가
"text-3xl"·"Pillar #"등의 면제도 라인 전체 부분문자열 검사라, 삼항식 한 줄에 두 색이 섞이면 cobalt 검사까지 함께 무력화된다 — 회귀가 가장 숨기 쉬운 형태가 정확히 그 형태다. - 이는 N6(Gate 8 C1/C2 공허 단정, 10라운드 미해소)과 동일 유형이다. 개별 수정이 아니라 형식 차원의 금지로 대응한다.
- 자동 검증: AC-48 · AC-49(F2 · F9).
R-8.33 [필수 · 토큰 등급 불변식] (v1.14 신설) 각 테마에서 -dark 변형은 해당 테마의 지면 배경(ivory·paper) 대비가 DEFAULT보다 커야 한다. DEFAULT 토큰의 값을 조정할 때는 같은 테마의 -dark 값과의 관계를 반드시 함께 검토한다.
- 절대 휘도 순서가 테마 간에 뒤집히는 것은 정상 동작이며 위반이 아니다.
-dark는 "절대적으로 어두운 색"이 아니라 "지면 대비가 더 깊은 변형" 이므로, 다크 지면에서 대비를 깊게 하려면 더 밝아진다. 실측: 라이트cobaltL=0.2203 >cobalt-darkL=0.1270 이지만 다크에서는cobaltL=0.2199 <cobalt-darkL=0.3184이며, vermillion 쌍도 동일하게 뒤집힌다. 판정 기준을 절대 휘도로 두면 정상 상태를 위반으로 오판한다. - 현행 실측(8개 셀 전부 충족): 라이트
ivory3.45→5.26 · 라이트paper3.12→4.76 · 다크ivory4.82→6.57 · 다크paper4.37→5.96 (cobalt), 라이트ivory4.16→6.38 · 다크ivory5.01→6.72 (vermillion). - 근거: 개발 팀장(Agy) 이의제기(Job
4962a667)가 다크 DEFAULT만 단독 상향하면 계층이 무너짐을 지적했고 실측으로 확인했다 — 다크 DEFAULT를 L≈0.52로 올리면 다크paper대비가 9.2가 되어-dark(5.96)를 역전한다. - 자동 검증: AC-43(정책 표에 등급 관계를 포함).
9. 비기능 요구사항 (Non-Functional Requirements)
9.1 빌드 품질 게이트 — 병합 필수 조건
| ID | 요구사항 | 검증 명령 |
|---|---|---|
| NF-01 | ESLint 경고·오류 0건 | npm run lint |
| NF-02 | TypeScript 오류 0건 | npx tsc --noEmit |
| NF-03 (v1.1 문구 정정) | 프로덕션 빌드 성공. 전 라우트가 빌드 타임 정적 프리렌더(○ Static 또는 ● SSG)이며 ƒ Dynamic 라우트가 0건이어야 한다 |
npm run build |
| NF-04 | package.json ↔ package-lock.json 정합. 의존성 추가 시 lockfile 동시 커밋 |
npm install --package-lock-only 후 diff 확인 |
9.2 SEO
R-9.1 전 라우트에 고유한 metadata.title / metadata.description을 정의한다. 타이틀 템플릿은 현행 %s | ANL · 경북대학교를 유지한다.
R-9.2 Open Graph(og:title, og:description, og:image, og:type, og:locale=ko_KR) 및 Twitter Card 메타를 추가한다.
R-9.3 시맨틱 HTML5 요소(<main>, <article>, <section>, <nav>, <address>, <time>)를 사용한다. 논문·특허 날짜는 <time dateTime>으로 표기한다.
R-9.4 app/sitemap.ts와 app/robots.ts를 추가한다.
R-9.5 지도교수 및 연구실 정보에 Person / ResearchOrganization JSON-LD 구조화 데이터를 삽입한다. (SHOULD)
9.3 접근성 (Accessibility)
R-9.6 WCAG 2.1 AA 색 대비를 충족한다. 특히 ink-mute(#6B655B) on ivory(#F5F1E8) 조합은 소형 텍스트 사용 시 대비 실측 후 적용한다.
R-9.7 장식용 SVG·요소는 aria-hidden, 의미 전달 SVG는 role="img" + aria-label을 갖는다.
R-9.8 prefers-reduced-motion: reduce에서 Reveal·Counter·Marquee의 모션이 비활성화되어야 한다(현행 구현 유지).
R-9.9 키보드 내비게이션으로 전 인터랙티브 요소(필터, 확장 토글, 링크)에 도달 가능하고 포커스 링이 보여야 한다.
R-9.10 필터·확장 토글은 aria-expanded / aria-controls를 갖는다.
9.4 성능
R-9.11 초기 렌더 DOM 노드 수를 제한한다. Publications 223건, Alumni 60명, Lectures 약 20학기는 전량 즉시 렌더 금지(P-07, M-06, L-03). 단 PR-01에 따라 전 레코드가 사용자 조작으로 도달 가능해야 한다.
R-9.12 라우트별 First Load JS는 현행 수준(공유 87.3 kB + 라우트별 1 kB 내외)에서 +30 kB를 초과하지 않는다.
R-9.13 신규 런타임 의존성 추가 시 사전 승인을 받는다. 현행 의존성은 next / react / react-dom 3종뿐이며 이 최소 구성을 유지한다.
9.5 반응형
R-9.14 (v1.6 개정) 지원 브레이크포인트는 Tailwind 기본값 sm(640px) / md(768px) / lg(1024px)에 커스텀 토큰 desktop(1240px) 을 더한 구성이다(R-8.20). 검수 기준 뷰포트는 360 / 768 / 1024 / 1440 px 4종에 1239 px과 1240 px을 추가한 6종이다 — 데스크톱 내비 전환 경계의 양쪽을 반드시 확인해야 한다.
R-9.15 어느 뷰포트에서도 가로 스크롤이 발생하지 않아야 한다.
R-9.16 긴 국문 제목의 줄바꿈은 break-keep을 적용한다.
9.6 콘텐츠 무결성
R-9.17 [최우선] 사이트에 게시되는 모든 수치·실적·인물 정보는 ISL-2026/ 실데이터 또는 README.md 정본에서 출처를 추적할 수 있어야 한다. 근거 없는 홍보성 지표 게시를 금지한다.
R-9.18 실명·실제 이메일이 게시되는 페이지이므로, 추정 정보를 사실처럼 표기하지 않는다. 불확실한 항목은 노출하지 않는다.
R-9.19 문서(README.md, docs/DESIGN.md)와 코드의 서술이 어긋나서는 안 된다. 마이그레이션이 미완인 영역은 문서에 미완임을 명시한다(문서가 코드보다 앞서 나가지 않는다).
10. 수용 기준 (Acceptance Criteria)
병합 승인은 아래 전 항목 충족 시에만 이루어진다.
기능 (PR-02·PR-03)
- AC-01
/접근 시 Home이 정상 렌더되고 404가 발생하지 않는다 - AC-02 Home에 연구실 소개 · 주요 연구 분야 · 오시는 길 3개 블록이 모두 존재한다
- AC-03
/intro접근 시/로 308 리다이렉트된다 - AC-04 상단 탭 5종(Home/Members/Publications/Lectures/Standardization)이 전부 정상 라우팅된다
- AC-05 (v1.1 개정 · v1.5 수치 갱신) Publications 3개 카테고리가 각각 고유 URL(
/publications/<slug>)을 가지며, 해당 URL로 직접 진입했을 때 정적 HTML이 이미 해당 카테고리 상태를 담고 있다(비필터 상태가 먼저 보였다가 바뀌는 현상이 없어야 한다) - AC-06 Lectures가 학기별 그룹으로 렌더되고 최근 3개 학기가 기본 노출된다
데이터 무손실 (PR-01)
- AC-07 건수 대조 통과: 국제 68 / 국내 80 / 특허 75 / 표준 문서 44 / 재학 16 / 졸업 60 / 강의 45학기
- AC-08 Publications 223건 중 어느 카테고리에도 배정되지 않은 레코드가 0건이다
- AC-09 확장 UI 조작 시 졸업생 60명·전 학기 강의·전 논문이 모두 도달 가능하다
- AC-10 한글·특수문자 인코딩 손실 0건, BOM 제거 확인
- AC-11 날짜 전 항목 ISO 8601 정규화 확인
- AC-12 연구실 정체성 서술 영역에서 금지어 0건 (
사물인터넷 표준,IoT Standards,MCM,메타버스 상호운용성,placeholder) — 논문·표준 제목의 도메인 용어는 예외(MG-08) - AC-13 전 카운터 수치가 데이터 배열에서 도출됨을 코드로 확인
- AC-14 (v1.1 신설) JS를 비활성화한 상태에서
/publications/<slug>문서에 해당 카테고리 레코드가 전부 포함되어 있다 (R-8.15 · PR-01)
품질 게이트
- AC-15
npm run lint통과 (경고 0) - AC-16
npx tsc --noEmit통과 - AC-17 (v2.0 개정)
npm run build성공. 빌드 리포트에 정확히 6개 데이터 라우트가ƒ (Dynamic)(force-dynamic)이고 **4개 프레임워크/메타데이터 라우트가○ (Static)**으로 분리되어 생성됨을 확인한다 (§7.1 DM-03) - AC-18 First Load JS 증가분 ≤ 30 kB
- AC-19 4종 뷰포트에서 가로 스크롤 없음
- AC-20 신규 Tailwind 반응형 유틸리티가 빌드 CSS에 실제 생성됨을 확인 (JIT 누락 시 빌드는 성공하나 조판이 무너짐)
- AC-21 (v1.1 신설)
generateStaticParams()로 카테고리별 정적 HTML 3개가 실제 생성됨을.next/server/app/publications/파일 목록으로 확인 - AC-22 (v1.1 신설) 소스 전역에
searchParamsprop 사용·useSearchParams()호출·라우팅 목적pushState호출이 0건임을 grep으로 확인 (§8.5 R-8.11·8.12·8.14)
문서
- AC-23
README.md·docs/DESIGN.md서술이 구현 결과와 일치 - AC-24 마이그레이션 스크립트가
scripts/에 커밋됨 - AC-25 (v1.6 신설 · R-8.19) 빌드 산출
.next/server/app/**/*.html의 모든 라우트에서<main>하위에container-content가 존재함을 자동 게이트로 확인.<main>에는max-w-*/px-*가 부여되지 않았음을 함께 확인 (R-8.17) - AC-26 (v1.6 신설 · R-8.18·R-8.20) 소스 전역에
w-screen·-mx-[50vw]계열 탈출 기법과 임의값 클래스min-[1240px]:사용이 0건임을 grep으로 확인
Research Project PageView (v1.7 신설 · §6.1.2)
- AC-27 (PJ-08 · R-8.15)
content/projects.ts전건의title·abstract가.next/server/app/index.html정적 HTML에 존재함을 확인 - AC-28 (PJ-09) Home 라우트가 여전히
○ (Static)이며 빌드 전체에ƒ (Dynamic)이 0건 - AC-29 (PJ-03 · PR-01) 각
abstract가 레거시 원문과 바이트 동일함을 파서 재실행으로 확인 - AC-30 (PJ-06) 모든
keywords[]원소가 해당abstract의 부분문자열임을verify_counts.py로 확인 (창작 차단) - AC-31 (PJ-07 · R-9.18)
funder가undefined인 프로젝트에 대해 산출 HTML에Funder라벨·자리표시자가 렌더되지 않음을 확인 - AC-32 (PJ-05) 모든
deliverables[].ref가content/standards.ts에 실재하는 문서 참조와 일치함을 조인 검증 - AC-33 (H-02 개정 · AC-02 회귀 방어) 히어로 재구성 후에도 연구실 소개 서술 블록 · 주요 연구 분야 그리드 · 오시는 길 · 지표 카운터 3종 ·
HeroComposition이 Home 정적 HTML에 전부 존속함을 확인 - AC-34 (v1.8 신설 · PJ-13·PJ-15·PJ-16) 프로젝트 트랙의 넘침을 브라우저 실측 수치로 판정한다 — 데스크톱(≥1240 px)에서
track.scrollWidth === track.clientWidth(스크롤 잔재 0), 모바일·태블릿에서는scrollWidth > clientWidth가 정상 동작이다. 어느 뷰포트에서도 문서 레벨 가로 스크롤은 0이어야 한다(AC-19 · R-9.15). 데스크톱 3카드 폭의 서브픽셀 거동은 브라우저 없이는 확정할 수 없으므로 이 단정으로 판정을 이관한다 - AC-35 (v1.9 신설 · R-8.21·R-8.22) 슬래시 수식자 실효성 게이트 — 소스(
app/**·components/**의.tsx·.css)에서토큰/불투명도형태로 사용된 모든 색 유틸리티를 추출하고, 각각에 대응하는 규칙이 산출 CSS(.next/static/css/*.css)에 실제로 존재함을 자동 게이트로 확인한다. 1건이라도 누락되면 실패한다. (현행 실측: 사용 26건 / 생성 0건) - AC-36 (v1.9 신설 · R-8.21)
app/globals.css의 모든--*-rgb정의가 공백 구분임을 grep 게이트로 확인한다(쉼표 포함 시 실패). 아울러 산출 CSS에rgb(<쉼표 목록> / …)패턴이 0건임을 확인한다 - AC-37 (v1.9 신설 · R-8.23 · R-9.6)
components/Header.tsx에 인라인style속성과 리터럴 색값이 0건이며, 활성 배지 계열 요소에opacity-*유틸리티가 0건임을 grep으로 확인한다 - AC-38 (v1.9 신설 · R-9.6) 활성 내비 배지의 전 텍스트 상태(데스크톱 라벨·번호 / 모바일
ko·en·번호) 가 라이트·다크 양 테마에서 4.5:1 이상임을 실측 색값으로 계산해 확인한다. 다크 모드 배경은--vermillion-rgb: 235 75 66으로 반전되므로 흰색 전경은 3.74:1로 미달한다 — 다크 모드 전경은ivory(반전 시18 18 18, 실측 5.01:1)를 사용한다 - AC-39 (v1.9 신설 · R-8.24 · AC-19) 헤더 가로 예산을 1240 / 1280 / 1440 px 에서 확인한다 —
header.scrollWidth <= header.clientWidth이고 내비 항목이 2줄로 접히지 않아야 한다(브라우저 실측 판정) - AC-40 (v1.9 신설 · IA-03 · AC-25) 사이트맵에 등재된 모든 URL의 산출 HTML이
redirect()전용이 아니라<main>+container-content를 포함한 실체 문서임을 확인한다 - AC-41 (v1.10 신설 · R-8.25) 산출 정적 HTML 전 라우트의
<main>내부 콘텐츠를 정규화 해시해 동일 해시가 2건 이상 존재하지 않음을 자동 게이트로 확인한다.canonical이 명시된 예외 쌍만 화이트리스트로 허용한다 - AC-42 (v1.10 신설 · v1.11 개정 · R-9.6 · AC-38 확장) vermillion 배경 위 텍스트 전량이 라이트·다크 양 테마에서 4.5:1 이상임을 확인한다. "전량"은 Header·
CategoryNav에 한정되지 않으며,group-open:·hover:등 상태 변형으로 적용되는 배경도 포함한다. 검증 대상은 두 부류로 나누어 각각의 기대 패턴과 기대 대비를 판정한다*(v1.12 개정)*.- 부류 A —
text-[0.65rem]비인터랙티브 상태 칩:app/standardization/page.tsx:40·:88→bg-vermillion-dark text-ivory(라이트 6.38 / 다크 6.72,dark:변형 없음). R-8.26 배지·칩 라우팅 조항 적용 - 부류 B — 인터랙티브 내비·토글:
components/Header.tsx:69,129,CategoryNav.tsx:22,app/lectures/page.tsx:89,app/members/page.tsx:177→text-white dark:text-ivory(라이트 4.69 / 다크 5.01) - [v1.13 개정 · 부류 B 재산정] ⓐ
Header.tsx:69,129·CategoryNav.tsx:22는2441f35에서 배경이bg-vermillion→bg-cobalt-dark로 바뀌어text-white의 불가피성이 소멸했다 — R-8.26 v1.13 조항에 따라text-ivory단독(라이트 5.26 / 다크 6.57)으로 정정한다. ⓑapp/lectures/page.tsx:89는 여전히group-open:text-ivory(4.16)로 미교정이며, 동일 관용구인members/page.tsx:177만 교정되어 한 쌍이 갈라져 있다. ⓒapp/not-found.tsx:22를 신규 등재 —text-ivory hover:bg-vermillion으로 hover 시 4.16이며 v1.12까지의 어떤 목록에도 없었다. 권고 조치는hover:bg-vermillion-dark(→ 6.38)로,white없이 해소된다 - v1.10 기재 정정:
text-whiteon#D9342B의 실측은 4.69:1이다(직전 수렴 리포트의 4.58:1은 오기 — 판정은 동일하게 통과) - 현행 미교정 4곳의 실측은 모두 4.16:1이며,
lectures:89·members:177은group-open:상태 변형으로 배경이 적용되어 육안 리뷰에서 누락되기 쉽다
- 부류 A —
- AC-43 (v1.11 신설 · v1.12·v1.13 개정 · R-8.26·R-8.27·R-9.6) 대비 자동 게이트(Gate 10) —
app/globals.css의:root·html.dark--*-rgb정의를 파싱해 양 테마 전 조합의 대비를 계산하고 정책 표의 바닥값 미만이면 실패한다. 최소 대상:{ink, ink-soft, ink-mute, vermillion, vermillion-dark, cobalt, cobalt-dark} × {ivory, paper}및{ink, ivory, white} × {vermillion, vermillion-dark, cobalt, cobalt-dark}.-dark변형이 배경으로 쓰이는 경우({ivory, white} × {cobalt-dark, vermillion-dark}, 양 테마)를 반드시 포함한다 — v1.11 목록은-dark를 전경으로만 다루어 상태 칩 배경을 검사하지 못했다*(v1.12 개정)*. 정책 표는 스크립트 상단 상수 블록에 두어 규격 변경 시 1곳만 수정되게 한다. (현행 실측:cobalt는ivory3.49 /paper3.16,cobalt-dark는paper4.48로 실패해야 한다)- [v1.13 개정 · C10-1] 현행 구현은 ⓐ 정책 값이 함수 본문에 흩어져 있어 상수 블록 요건을 충족하지 않고, ⓑ 토큰 값만 검사하고 소스의 전경/배경 쌍은 보지 않는다 — 따라서
bg-cobalt-dark text-white(다크 2.85)를 작성해도 통과한다. 검사 대상에 소스에서 실제로 함께 쓰인 전경/배경 조합을 추가하고,text-white가 전경인 조합을 양 테마 모두 계산한다 - [v1.14 개정] ⓐ DEFAULT 토큰 × {
ivory,paper} × {라이트,다크} 를 3:1 바닥값으로 명시 추가한다 — 이 검사가 D-14 A안의 안전망 본체이며, 브랜드 색이 어느 테마에서든 역할 바닥값 아래로 내려가면 즉시 실패해야 한다. ⓑ R-8.33 등급 관계(각 테마 지면 대비에서-dark> DEFAULT)를 정책 표에 포함한다
- [v1.13 개정 · C10-1] 현행 구현은 ⓐ 정책 값이 함수 본문에 흩어져 있어 상수 블록 요건을 충족하지 않고, ⓑ 토큰 값만 검사하고 소스의 전경/배경 쌍은 보지 않는다 — 따라서
- AC-44 (v1.11 신설 · v1.13 개정 · R-8.26·R-8.32) 소형 텍스트 라우팅 게이트 —
app/**·components/**에서text-cobalt·text-vermillion(DEFAULT 변형)이 소형 텍스트 크기 클래스와 동일 요소에 공존하지 않음을 확인한다. 부모로부터 크기를 상속받아 정적 판정이 불가능한 케이스는 화이트리스트에 사유와 함께 등재한다. (현행 실측:text-cobalt소형 텍스트 사용처 12건 +bg-cobalt소형 배지 2건 미달)- [v1.13 개정 · C10-2] 현행 구현의 라인 부분문자열 면제 4종(
"text-vermillion"·"text-3xl"·"Pillar #"·"w-1.5 h-1.5")을 전량 제거하고 R-8.32의(파일, 행, 사유)화이트리스트로 대체한다. 첫 번째 면제 때문에 AC-44의 vermillion 절반이 구조적으로 발화하지 않음을 재현 확인했다(→ R-8.32). 제거 후text-vermillion23건 중 소형 텍스트 사용처가 검출되어야 하며, 최저값은bg-paper카드 내부의members/page.tsx:114,1443.77이다 - [v1.14 개정 · G-7] 판정 정규식의 부정 후방탐색
(?<!dark:)를 제거한다. 현행 구현은 이 후방탐색으로dark:text-cobalt·dark:text-vermillion을 설계상 검사 대상에서 제외하고 있어, 소형 텍스트 라우팅을 라이트 테마에 대해서만 검사한다. 그 결과 다크 테마bg-paper위 8곳(4.37)이 검사 범위 밖이었다(→ AC-51). G-1(부분문자열 면제)·G-2(반전 검사 2종 한정)·G-3(전경/배경 쌍 미검사)에 이은 네 번째 범위 결함이며, 넷 모두 "검사를 절반만 한다"는 같은 형태다
- [v1.13 개정 · C10-2] 현행 구현의 라인 부분문자열 면제 4종(
- AC-45 (v1.11 신설 · v1.13 개정 · R-8.28) 반전 계약 게이트 —
:root와html.dark의 동일 토큰 쌍에 대해 라이트↔다크 상대휘도 대비가 2.0 이상임을 확인한다. (현행 실측:cobalt는 1.01로 실패해야 한다)- [v1.13 개정 · C10-3] 검사 범위를 양쪽에 정의된 전 토큰(현행 10종) 으로 확대한다. 현행 구현은
cobalt-dark·vermillion-dark2종만 검사해--cobalt의 반전 대비 1.00(라이트78 119 255↔ 다크77 119 255)을 검출하지 못했다 — v1.11이 D-10의 근본 원인으로 규명한 바로 그 실패 유형의 재발이며, 게이트가 통과했다는 사실 자체가 오탐 신호였다. 확대 시--vermillion(1.25)도 검출되므로 D-13 확정 전까지는 화이트리스트에 사유와 함께 등재한다 - [v1.14 · 브랜드 고정 토큰 예외 후보]
--cobalt(1.00)·--vermillion(1.25)은 사용자 지정 브랜드 색이며, R-8.29 정리(강조색dark:변형 38건 제거) 후에는 어느 테마에서도 소형 텍스트를 담지 않는다. 남는 사용처는 전부 대형 텍스트·도형·테두리·아이콘이며 양 테마에서 3:1을 충족한다(최저 3.12). 이 상태에서 R-8.28을 관철하려면 다크 값을 파스텔로 올려야 하는데, 그러면 브랜드 색이 다크 테마에서 사라진다. 처리 방침은 D-14로 이관한다 — R-8.28은 수단이고 R-8.26·R-8.30(테마별 대비)이 목적 이므로, 목적 규칙이 양 테마에서 실효적으로 검사되면(→ AC-43 개정) 안전망은 유지된다. 검증: 브랜드 색을#1B3A8A로 되돌리고 테마 불변을 유지하면 다크 지면 대비가 1.80으로 떨어져 AC-43이 즉시 실패한다
- [v1.13 개정 · C10-3] 검사 범위를 양쪽에 정의된 전 토큰(현행 10종) 으로 확대한다. 현행 구현은
- AC-46 (v1.11 신설 · AC-43·AC-44·AC-45 유효성) 폴트 인젝션으로 Gate 10의 실효성을 증명한다 — ①
--cobalt-dark-rgb를52 98 204로 되돌리면 AC-43 실패, ② 소형 텍스트를text-cobalt(DEFAULT)로 되돌리면 AC-44 실패, ③html.dark의--cobalt-rgb를 라이트 값과 동일하게 두면 AC-45 실패, ④standardization/page.tsx:40을bg-vermillion text-ivory로 되돌리면 AC-42 실패, ⑤ 상태 칩을bg-cobalt text-ivory(v1.11 §6.5 폐기안)로 되돌리면 AC-43 실패(3.49), ⑥ 임의 위치에text-white를 1건 추가하면 AC-47 실패(9 > 8) (⑤·⑥은 v1.12 신설). 6건 모두 실패를 재현하지 못하면 Gate 10을 채택하지 않는다 — 통과만으로는 게이트가 결함을 검출한다는 증명이 되지 않는다- ⑤는 기각·교체된 설계를 게이트가 실제로 잡는지 확인한다. v1.10에서 기각한 D-09 C안을 주입해 AC-41을 검증한 것과 같은 방식이며, 교체된 설계는 반드시 게이트의 검출 대상이 되어야 한다
- AC-47 (v1.12 신설 · v1.13 개정 · R-8.29) 팔레트 외 색 상한 게이트 —
app/**·components/**에서text-white·bg-white등 팔레트 외 색 유틸리티의 출현 횟수가 화이트리스트 등재 건수를 초과하지 않음을 확인한다.- 화이트리스트(부류 B 한정, 총 8건):
components/Header.tsx:69,75,129,136,145(5) ·CategoryNav.tsx:22(1) ·lectures/page.tsx:89(1) ·members/page.tsx:177(1) - 각 항목에 사유(해당 위치에서
ivory전경이 4.16으로 미달)를 함께 기재한다. 화이트리스트는 상한이지 허가가 아니며, 신규 사용처는-dark배경으로 대체 가능한지 먼저 검토한 뒤에만 등재한다 - 근거:
docs/DESIGN.md는 "토큰만 사용 — 임의 회색·팔레트 밖 hex 금지"를 규정한다.white는 Issue 01 팔레트(ink/ivory/paper/line/vermillion/cobalt) 밖의 색으로,02247a0에서 불가피성 때문에 도입되었다. 상한을 두지 않으면 그 불가피성이 관행으로 굳는다 - [v1.13 개정 · C10-4] 현행 구현은
content.count("text-white")단순 계수라 위치를 검증하지 않는다. 화이트리스트를(파일, 행)집합으로 두고 실제 출현 위치 집합과 완전히 일치할 때만 통과시킨다(초과·고아 양방향 검출, R-8.32). 배경 변경(bg-vermillion→bg-cobalt-dark)으로 현행 7건 중 6건이 R-8.29상 제거 대상이 되었으므로, Phase 3 완료 후 화이트리스트는lectures/page.tsx:89·members/page.tsx:1772건으로 축소되어야 한다 — 이 2곳만이 DEFAULTbg-vermillion위(ivory 4.16 미달)에 있다
- 화이트리스트(부류 B 한정, 총 8건):
색 통일성 (v1.13 신설)
- AC-48 (v1.13 신설 · R-8.30·R-8.31·R-8.32) 색 통일성 게이트(Gate 11) — 아래 8개 검사를 자동화한다. C11-1~C11-4는 R-8.31, C11-5는 R-8.30, C11-7은 AC-23 회귀 방어에 대응한다.
- C11-1 괘선 통일 —
h-px w-8 bg-*시그니처의 색 클래스가 2종 이상이면 실패 (현행:bg-cobalt-dark dark:bg-cobalt6곳 ↔bg-vermillion1곳 → 실패해야 한다) - C11-2 키커 통일 —
font-mono text-xs … uppercase tracking-widest … font-bold시그니처의 색 클래스가 2종 이상이면 실패 (현행 11곳 ↔ 1곳 → 실패해야 한다) - C11-3 강조 배경 전경 통일 —
bg-{accent}-dark요소에text-white가 결합되어 있으면 실패(R-8.29) (현행 6건 → 실패해야 한다) - C11-4 상태 배경 전경 쌍 —
group-open:bg-*·hover:bg-*로 배경이 바뀌는 요소의 대응 상태 전경과의 대비가 4.5 미만이면 실패 (현행lectures:894.16 ·not-found:224.16 → 실패해야 한다) - C11-5 비텍스트 UI 3:1 —
border-{accent}*·ring-{accent}*·도형bg-{accent}*·SVG의var(--*)참조를 수집하고, 슬래시 알파는 배경과 합성한 뒤 계산해 3.0 미만이면 실패 (현행focus:ring-cobalt/501.80 ·hover:border-cobalt/601.95 → 실패해야 한다) - C11-6 전역 CSS 조합 —
globals.css의background/color쌍(::selection등)을 파싱해 4.5 미만이면 실패 (현행::selection은ivoryonvermillion4.16 → 실패해야 한다) - C11-7 문서 동기화 —
docs/DESIGN.md§3 색상표의 hex ↔globals.css의--*-rgb대조, 불일치 시 실패 (현행 일치 — 회귀 방어용) - C11-8 시맨틱 페어링 — R-8.5의
vermillion = Orchestration대응을 히어로 강조 요소에 대해 확인. D-12 확정 이후에만 활성화한다 - C11-9
dark:변형 제로 (v1.14 신설 · R-8.29) —app/**·components/**에dark:+ 강조색(cobalt·vermillion및 각-dark) 조합이 1건이라도 있으면 실패. 예외는 R-8.32 화이트리스트 등재로만 허용한다(부류 B의dark:text-ivory등) (현행dark:*-cobalt38건 → 실패해야 한다)
- C11-1 괘선 통일 —
- AC-49 (v1.13 신설 · AC-48 유효성) Gate 10·11 폴트 인젝션 — ① F1
DirectionsBlock:8현행 유지 → C11-2 실패, ② F2lectures:50의text-xs text-vermillion현행 유지 → AC-44 실패(면제 제거 확인), ③ F3 다크--cobalt-rgb를 라이트와 동일하게 유지 → AC-45 실패(1.00), ④ F4Header:69에서dark:text-ivory제거 → AC-43 또는 C11-3 실패(다크 2.85), ⑤ F5standardization:89를bg-cobalt text-ivory로 되돌림 → AC-43 실패(3.45), ⑥ F6 화이트리스트 밖 위치에text-white1건 추가 → AC-47 실패(위치 불일치 — 단순 계수로는 통과했을 사례), ⑦ F7focus:ring-cobalt/50현행 유지 → C11-5 실패(1.80), ⑧ F8docs/DESIGN.md색상표 hex 1글자 변경 → C11-7 실패, ⑨ F9 실존하지 않는(파일, 행)을 화이트리스트에 등재 → 고아 항목으로 실패, ⑩ F10members/page.tsx:108을text-cobalt-dark dark:text-cobalt로 되돌리면 AC-44 실패(다크 4.37) — 후방탐색(?<!dark:)제거 확인, ⑪ F11dark:bg-cobalt1건을 되살리면 C11-9 실패 (⑩·⑪은 v1.14 신설).- 11건 전부 실패를 재현하지 못하면 Gate 11을 채택하지 않는다. F1·F2·F3·F7·F10·F11은 현행 코드 자체가 주입 상태이므로 게이트 구현 직후 실행만으로 즉시 검증된다
- AC-50 (v1.13 신설 · R-8.27 · AC-23)
docs/DESIGN.md동기화 — 아래 4건을 교정하고 구현과 일치시킨다.- §10 커스터마이즈 훅(302~308행)에 대비 제약을 명문화한다. 현행 안내는 교체 방법만 적고 지켜야 할 제약을 적지 않아
eaddc4f사고의 직접 원인으로 규명되었는데, v1.11에서 지적된 뒤에도 미교정 상태로 남아 같은 유형의 무기록 색 교체가 4회 더 발생했다 - §8-1(282행) 이 Header 활성 배지를
bg-vermillion text-white dark:text-ivory로 기술하나 실제는bg-cobalt-dark— 갱신한다 - §9(292행) "강조색 위 텍스트는 항상
ivory" ↔ 실제text-white7건 — R-8.26 v1.13 조항(-dark배경은ivory단독 / DEFAULT 배경만white예외)으로 서술을 정합화한다 - §2(30행) 시맨틱 페어링 ↔ 히어로
Orchestration색 변경 — D-12 확정 방향에 맞춰 코드 또는 문서 중 한쪽을 교정한다
- §10 커스터마이즈 훅(302~308행)에 대비 제약을 명문화한다. 현행 안내는 교체 방법만 적고 지켜야 할 제약을 적지 않아
- AC-51 (v1.14 신설 · R-8.26·R-8.29) 다크 테마 소형 텍스트 해소 —
dark:text-cobalt가bg-paper위 소형 텍스트에 적용되어 다크 테마에서 4.37로 미달하는 아래 8곳이text-cobalt-dark단독(다크 5.96)으로 교정되었음을 개별 확인한다.app/page.tsx:148(Pillar 번호,text-sm,bg-paper@:142) ·app/page.tsx:187(Pillar #,text-xs@:183)app/members/page.tsx:108(Ph.D. 학위,bg-paper@:102) ·app/members/page.tsx:138(M.S. 학위,bg-paper@:132)app/_components/ProjectPageView.tsx:88·:93(Standards Track / Organization,text-xs@:80,bg-paper@:44)app/standardization/page.tsx:36([{scope}],bg-paper@:32) ·app/publications/[category]/page.tsx:124(등록번호,text-xs@:118,bg-paper@:103)bg-ivory위 사용처(ProjectPageView:53·members:54,63,202·standardization:64·DirectionsBlock:51· 섹션 키커 전량)는 4.82로 통과하되 여유가 0.32뿐이므로 함께-dark단독으로 정리한다(→ R-8.29 · C11-9)
11. 구현 계획 (Implementation Plan)
11.1 단계별 작업 분해
| Phase | 작업 | 산출물 | 담당 | 선행 조건 |
|---|---|---|---|---|
| P0 | D-01(Publications 카테고리 1·2 중첩) 확정 | 결정 기록 | GM ← 지도교수 | ✅ 완료 (v1.5 · 51aae14) |
| P1 | 레거시 데이터 추출 스크립트 작성 및 content/*.ts 생성 |
4개 데이터 모듈 + 추출 스크립트 | Agy | P0 |
| P1-R | 건수·인코딩·날짜 정규화 교차 검증 (AC-07~11) | 검증 리포트 | Claude | P1 |
| P2 | Home 신설(소개·연구 분야·오시는 길) + /intro 리다이렉트 + Header 내비 갱신 |
app/page.tsx, next.config.js |
Agy | P1-R |
| P3 | Members / Lectures 실데이터 반영 | 2개 라우트 | Agy | P1-R |
| P4 | Publications — /publications + [category] 세그먼트 4종 (§8.5 렌더링 제약 준수, 대량 데이터 처리 포함) |
1개 라우트 + 4개 세그먼트 | Agy | P1-R |
| P5 | Standardization 3단 계층 뷰 | 1개 라우트 | Agy | P1-R |
| P6 | 자산 이관·최적화 (MG-06·07) | public/ |
Agy | P2~P5 |
| P7 | SEO·접근성·반응형 검수 (§9.2·9.3·9.5) | 검수 리포트 | Cline | P6 |
| P8 | 최종 교차 리뷰 및 Verdict | 리뷰 리포트 | Claude | P7 |
병렬 가능: P3 / P4 / P5는 P1-R 완료 후 상호 독립이므로 동시 진행 가능하다. P2는 Header.tsx를 수정하므로 P3~P5와 파일 충돌 가능성이 있어 먼저 완료할 것을 권장한다.
11.2 잡 분할 권고
Publications(P4)는 데이터 규모(223건)와 필터·점진적 노출 요구로 인해 타 라우트 대비 작업량이 크다. P4를 단독 잡으로 분리하고 P3·P5를 묶는 편이 리뷰 단위로 적절하다.
11.3 리뷰 프로토콜
.agents/MULTI_AGENT_RULES.md §3에 따라 Phase 완료 시마다 리뷰 사이클을 돌린다. 리뷰어는 NOT PASS 시 사유와 검증된 개선 방향을 반드시 함께 제시하고, 개발 팀장은 부당하다고 판단하는 지적에 대해 근거를 갖춰 반박한다.
12. 리스크 및 미결 결정 (Risks & Open Decisions)
12.1 미결 결정 등록부
| ID | 결정 사항 | 상태 | 기본값(잠정) | 영향 |
|---|---|---|---|---|
| D-01 | Publications 카테고리 1(International Conference)과 2(International Journal & Conference)의 범위 중첩 해소 |
✅ 확정 (v1.5, 2026-07-30) | — | 결정: 1번 단독 카테고리 폐기 → 3개 카테고리 확정. A안(저널/학술대회 분리)은 학술대회가 1건에 불과해 기각, B안(미수록 논문 확보)은 신규 데이터 유입 없이 실행 불가하여 기각. 레지스트리 1곳(content/categories.ts) + PubCategory 유니온 수정으로 완결되었고 223건 무손실을 유지했다(P-03). 근거: intl-conf 배정 레코드 실측 0건 |
| D-02 | 강의 과목명 한글 병기 여부 | 🟡 미결 | 영문 원문만 노출 (L-05) | Lectures 표기. 병기 시 지도교수 확인 필요 |
| D-03 | 오시는 길의 지도 표현 방식 | 🟡 미결 | 주소 텍스트 + 캠퍼스 링크 (지도 임베드 없음) | H-16. 외부 지도 스크립트는 R-9.13 최소 의존성 원칙과 충돌 |
| D-04 | 졸업생 기본 노출 범위(N년) | 🟢 위임 | 최근 3년 | M-06. 구현자 재량 |
| D-05 | 연구실 GitHub 조직명(github.com/iot-standards-laboratory) 개명 여부 |
🟡 미결 | 현행 URL 유지 | 조직명이 구 정체성. 개명 시 기존 링크 무효화 위험 |
| D-06 | 본문 여백·최대 폭 컨테이너를 어느 계층에 부여할 것인가 | ✅ 확정 (v1.6, 2026-07-30) | — | 결정: <main> 일괄 부여안 기각 → 라우트 래퍼 방식 + 자동 게이트 채택. Planner 초안(<main>에 container-content)은 1행 수정·누락 불가라는 장점이 있으나, 개발 팀장 이의제기(Job 2560771b)대로 full-bleed 밴드·마퀴 티커를 구조적으로 차단한다. 래퍼 방식의 유일한 약점(신규 라우트 누락)은 AC-25 게이트로 상쇄되므로 래퍼 방식이 우월하다. → R-8.17~R-8.19 |
| D-07 | Research Project 카드의 Funder/Sponsor 실데이터 확보 여부 |
🔴 미결 | funder 미노출 + 실존하는 Standards Track 표기 |
PJ-07. ISL-2026/ 전체를 과제·연구비·IITP·NRF·한국연구재단·정보통신기획평가원 등으로 검색해 0건이다. 임의 생성은 MG-05·R-9.17·R-9.18 위반이며 실명·실제 이메일이 게시되는 페이지이므로 절대 불가. 기본값으로 구현 차단은 아니며, 지도교수가 사업명·부처·기간을 제공하면 content/projects.ts 재생성만으로 반영된다 |
| D-08 | Research Project 집합의 정체성 범위 — 레거시 3건(IoT/CCIS/VLC)만인지, ANL 신규 과제를 포함할지 | 🟡 미결 | 레거시 3건 노출, 섹션 라벨 Research Projects |
레거시 3건은 IoT 시대 실적이고 현 정체성은 ANL이다. 신규 과제 추가는 지도교수 입력이 필요하다(MG-05). 레거시 3건 비노출은 PR-01에 역행하므로 배제 |
| D-09 | /publications 인덱스 라우트를 Overview 뷰 / redirect() / 기본 카테고리 재렌더 / 전체 통합 뷰 + All 탭 중 무엇으로 둘 것인가 |
✅ 재확정 (v1.10, 2026-07-31) | — | 결정: Overview 뷰 채택(A안). v1.9는 C안(첫 카테고리 본문 재렌더)을 채택했으나, 개발 팀장 이의제기(Job 22b7a309)대로 동일 DOM 정적 HTML 2본이 생성되어 R-8.25를 위반한다 — 지적이 타당하여 채택안을 교체한다. redirect()(B안)는 AC-25·AC-40과 충돌하고, All 탭 포함 전체 통합 뷰(D안)는 commit 22a31ff의 탭 제거 결정을 되돌리며 223건 단일 페이지로 P-07·R-9.11과도 충돌한다. A안은 고유 콘텐츠(카테고리별 집계 + 최신 하이라이트)를 가지므로 중복이 원천 소멸하고, All 탭 없이 3개 탭 체계를 유지해 22a31ff의 의도를 보존한다 → IA-03 재개정 · R-8.25 · AC-41 |
| D-10 | eaddc4f가 도입한 --cobalt: #4A7CE8의 라이트 테마 대비 미달(ivory 3.49 / paper 3.16)을 어떻게 해소할 것인가 |
✅ 확정 (v1.11, 2026-07-31) | — | 결정: C안 채택 — --cobalt는 #4A7CE8 그대로 두고 --cobalt-dark를 52 98 204(#3462CC) → 50 84 158(#32549E)로 재조정한 뒤, 소형 텍스트 사용처를 -dark 변형으로 라우팅한다. 근거: ⓐ 사용자가 지정한 브랜드 색이 보존된다 — 히어로 SVG(var(--cobalt) 직접 참조)·대형 세리프 수치·불릿·테두리·아이콘 등 시각적으로 먼저 인지되는 표면은 전부 #4A7CE8을 유지하며, 이들은 대형 텍스트·비텍스트 UI 기준(3:1)을 실측 3.49로 충족한다. ⓑ cobalt-dark 슬롯은 현재 사용처 0건이므로 신규 토큰 없이 빈 슬롯을 활용해 토큰 계층이 늘지 않는다. ⓒ 결과값 6.43 / 5.82는 vermillion-dark(6.38 / 5.77)와 동일 등급이라 두 강조색이 대칭이 된다. 기각 사유 — A안(--cobalt 자체를 #3C64BC로 하향)은 브랜드 색이 눈에 띄게 어두워져 지시를 훼손하고, B안(신규 --cobalt-text 토큰)은 비어 있는 -dark 슬롯과 역할이 중복되며, D안(#1B3A8A 복귀)은 사용자 지시 역행이다. #3C64BC(paper 4.51)가 아니라 #32549E(5.82)를 쓰는 이유는 4.51이 임계선 대비 여유 0.01에 불과해 §12.1의 opacity-90 사고(4.69 → 4.05)처럼 후속 변경 한 번으로 재미달하기 때문이다. v1.12 개정 — 배지·칩 전경/배경: 개발 팀장(Agy) 이의제기(Job 7f136931)를 수용해 v1.11의 bg-cobalt text-ink dark:text-ivory(5.03 / 4.82)를 폐기하고 bg-cobalt-dark text-ivory(6.43 / 6.57) 로 교체한다. v1.11은 소형 텍스트 12곳에만 -dark 라우팅을 적용하고 동일 크기 등급(10.4 px)의 상태 칩 2곳은 DEFAULT 배경으로 남겨 스스로의 원칙과 어긋나 있었다 — 지적이 타당하다. 다만 이의제기의 권장 전경 text-white dark:text-ivory(7.25 / 6.57)는 미채택 — -dark 배경에서는 ivory 전경만으로 양 테마가 통과하므로 팔레트 외 색 white와 dark: 변형이 모두 불필요하다(→ R-8.29). 아울러 권장안을 그대로 적용하면 standardization:87-89 삼항식의 나란한 두 칩의 상대휘도 대비가 1.19 → 1.54로 악화되므로, vermillion 칩도 -dark로 통일해 1.01로 맞춘다(→ R-8.26 짝 칩 등급 일치 조항) v1.13 개정 — 확정값 갱신: 커밋 ca4a7ee·8db16e4가 --cobalt를 #4E77FF, --cobalt-dark를 확정값 #32549E가 아닌 #345AD2(52 90 210)로 설정했다. #345AD2는 paper 4.76 / ivory 5.26으로 R-8.26 바닥값을 충족하고 브랜드 색상(226.1°)에도 #32549E보다 가까우므로 확정값을 #345AD2로 개정한다. 단 paper 여유가 0.26뿐이라 위에서 #3C64BC를 배격한 것과 같은 사유가 부분적으로 적용되므로 §12.2 R-4로 등재하고, 추가 상향은 금지한다(색상 유지 시 paper 4.5 한계는 #3B5AC2 4.92 부근이라 이득이 작다). 아울러 #4E77FF는 반전 대비 1.00으로 R-8.28을 다시 위반하며 이는 D-10 근본 원인의 재발이다 → D-12로 이관 → R-8.26 · R-8.28 · R-8.29 · AC-42 · AC-43 · AC-44 · AC-45 · AC-47 |
| D-11 | text-vermillion(DEFAULT) 소형 텍스트 약 30곳을 교정할 것인가 |
🟡 미결 | 현행 유지 (교정하지 않음) | 실측 ivory 4.16 / paper 3.77로 R-8.26 소형 텍스트 기준에 미달하나, ⓐ eaddc4f가 만든 회귀가 아니라 최초 커밋 36a4cd8 이래의 상태이고, ⓑ 30곳 일괄 변경은 "전체적인 에디토리얼 디자인 시스템 유지" 목표와 정면 충돌하는 시각적 대변경이며, ⓒ vermillion(#D9342B)은 사용자가 명시적으로 현행 유지를 지정한 색이다. 교정 시에는 D-10과 동일한 패턴(text-vermillion-dark dark:text-vermillion, 라이트 6.38 / 5.77)을 적용하면 되므로 기술적 경로는 확보되어 있고 판단만 남는다. AC-44 화이트리스트에 사유와 함께 등재해 게이트가 이 결정을 명시적으로 기록하게 한다. v1.13 실측 갱신 — 정확한 건수는 23건(상태 변형 포함)이며 최저값은 bg-paper 카드 내부의 members/page.tsx:114,144 3.77이다. Footer.tsx:53,71의 hover:text-vermillion도 bg-paper 위라 3.77이다 |
| D-12 | "Primary Color(#4E77FF) 전 요소 통일 적용"의 판정 기준을 토큰 값으로 볼 것인가, 화면 인지색으로 볼 것인가 — 그리고 히어로 Orchestration 강조어의 색을 R-8.5 규약대로 vermillion으로 되돌릴 것인가 |
🔴 미결 (v1.13 신설) | A안 + B안 병행 | 접근성 제약상 소형 텍스트에는 #4E77FF를 쓸 수 없다(라이트 3.45 / 3.12). 그 결과 토큰은 #4E77FF, 화면은 #345AD2라는 이중 상태이며, 라이트 테마에서 #4E77FF가 정적으로 칠해지는 곳은 히어로 SVG와 6 px 불릿 2곳뿐이다(hover·focus 제외). A안(현행 유지): 코드 변경 0, 지시는 토큰 수준에서 충족. B안(대형 표면 확대): page.tsx:84,92의 30 px 지표 등 3:1을 충족하는 대형 텍스트·도형 표면에 #4E77FF를 적극 확대해 브랜드 가시성을 회복한다 — 접근성 손실 없이 문제를 실질적으로 완화하는 유일한 경로다. C안(-dark 상향) 기각 — 여유 0.26에서 더 밝히면 D-10이 배격한 임계선 상황에 근접한다. 히어로 Orchestration: docs/DESIGN.md:30과 R-8.5가 vermillion = Orchestration을 명문 규정하므로, cobalt를 유지하려면 문서를 먼저 개정해야 한다. 현재는 코드가 문서를 앞질러 같은 페이지 안에서 규약이 반씩 갈린 상태다. 어느 쪽이든 코드와 문서가 같은 값을 말해야 한다 → R-8.5 · AC-48(C11-8) · AC-50 |
| D-13 | --vermillion의 반전 대비 1.25(라이트 217 52 43 ↔ 다크 235 75 66)를 교정할 것인가 |
🟡 미결 (v1.13 신설) | 현행 유지 + 화이트리스트 등재 | R-8.28 바닥값 2.0에 미달하나 ⓐ 최초 커밋 이래의 상태로 특정 커밋이 만든 회귀가 아니고, ⓑ #D9342B는 사용자가 현행 유지를 지정한 Secondary이며, ⓒ --vermillion-dark(2.58)가 정상이라 소형 텍스트 경로는 이미 확보되어 있다. 다만 R-8.28의 취지대로 "반대 테마 값을 조정하는 순간 양 테마가 동시에 무너지는" 상태이므로, AC-45 화이트리스트에 사유와 함께 등재해 게이트가 이 결정을 명시적으로 기록하게 한다 → R-8.28 · AC-45 |
| D-14 | --cobalt DEFAULT의 반전 대비 1.00을 어떻게 처리할 것인가 — R-8.28 예외로 등록할 것인가, 다크 값을 대칭 상향할 것인가 |
🔴 미결 (v1.14 신설, Agy 이의제기 4962a667 반영) |
A안 (브랜드 고정 예외) | R-8.29 정리(강조색 dark: 변형 38건 제거) 후 --cobalt DEFAULT는 어느 테마에서도 소형 텍스트를 담지 않으며 남는 사용처(히어로 SVG·6 px 불릿·hover 테두리·토글 아이콘·대형 텍스트)가 양 테마에서 3:1을 충족한다(최저 3.12). 즉 측정 가능한 실패는 남지 않고 형식적 위반만 남는다. A안 — 브랜드 고정(theme-invariant) 토큰으로 등록: 다크 값을 라이트와 정확히 동일(78 119 255)하게 맞춰 불변성을 소스에 드러내고 AC-45 화이트리스트에 등재한다. 근거 ⓐ R-8.28은 수단, R-8.26·R-8.30(테마별 대비)이 목적 이며 목적 규칙이 양 테마에서 실효 검사되면(AC-43 v1.14 개정) 안전망이 유지된다 — 검증: #1B3A8A 역주입 시 다크 지면 대비 1.80으로 AC-43 즉시 실패. ⓑ #4E77FF는 사용자 지정 Primary이므로 다크 테마만 다른 색으로 치환하면 브랜드 정체성이 갈라진다. B안 — 대칭 상향(이의제기 구조 채택 · 수치 정정): --cobalt-rgb(다크) 168 188 255(#A8BCFF, 반전 2.09) + --cobalt-dark-rgb(다크) 199 212 255(#C7D4FF, 반전 4.04, 다크 paper 11.56 > DEFAULT 9.14로 R-8.33 충족). 이의제기 원안의 #85ACFF는 반전 1.73으로 R-8.28 미달이라 미채택하고, #B0CDFF의 기재 반전 2.50은 #345AD2의 상대휘도를 폐기값 #32549E의 0.0949로 적은 오기에서 파생된 값으로 실제는 3.68이다. B안의 비용은 다크 강조색이 파스텔로 변해 브랜드 색이 다크 테마에서 사라지고 bg-cobalt-dark 칩이 대비 12.75의 거의 흰 배경이 되는 것 — D-12(브랜드 가시성)를 다크 테마에서 악화시킨다. A안은 본 계획자가 작성한 R-8.28을 스스로 완화하는 제안이므로 cline·GM의 별도 심사를 요청하며, 승인 전에는 집행하지 않는다 → R-8.28 · R-8.29 · R-8.33 · AC-43 · AC-45 |
D-01 상세
PR-04에 명시된 4개 라벨 중 1번과 2번의 범위가 논리적으로 중첩된다. International Journal & Conference가 국제 저널과 국제 학술대회를 모두 포함한다면, International Conference는 그 부분집합이 되어 동일 레코드가 두 카테고리에 해당하게 된다.
레거시 데이터 구조와의 대조:
| 레거시 파일 | 실제 내용 | PR-04 라벨과의 대응 |
|---|---|---|
paper-international.html |
국제 저널 67 + 국제 학술대회 1 = 68 | International Journal & Conference에 정확히 대응 |
paper-domestic.html |
국내 논문 80 (KCI 48) | Domestic Journal & Conference에 정확히 대응 |
patent.html |
특허 75 | Patent에 정확히 대응 |
| — | 대응 원본 없음 | International Conference ← ⚠️ |
권고안 (A안) — 국제 실적을 저널/학술대회로 분리:
International Journal / International Conference / Domestic Journal & Conference / Patent
→ 1번 라벨이 Journal의 오기라는 가정. 레거시 국제 목록을 게재처로 분리하면 저널 67 / 학술대회 1이 되어 학술대회 카테고리가 1건으로 빈약해지는 점을 함께 확인해야 한다.
대안 (B안) — 원문 라벨을 그대로 두고 1번을 국내외 통합 학술대회 카테고리로 재정의:
International Conference에 미수록 학술대회 논문을 지도교수로부터 확보해 채운다.
리뷰어 판단: 어느 안이든 P-02의 레지스트리 설계로 인해 구현 착수를 막지 않는다. P1 단계에서는 레거시 3개 원본을 그대로 3개 카테고리에 적재하고, D-01 확정 후 4번째 카테고리 분리를 적용하는 순서를 권고한다. 단 P-03(레코드 무손실) 은 어느 안에서도 반드시 지켜져야 한다.
✅ 확정 결과 (v1.5, 2026-07-30 · commit 51aae14) — C안: 1번 단독 카테고리 폐기로 결정되었다.
| 항목 | 내용 |
|---|---|
| 기각된 A안 | 국제 실적을 저널/학술대회로 분리 → 학술대회가 실측 1건뿐이어서 단독 카테고리로 성립하지 않음 |
| 기각된 B안 | 미수록 학술대회 논문을 추가 확보 → MG-05(ISL-2026/에 없는 데이터 생성 금지) 에 저촉되며 신규 원본 유입 없이는 실행 불가 |
| 채택된 C안 | intl-conf 슬러그·라벨·타입 유니온을 제거하고 3개 카테고리로 확정 |
| 무손실 검증 | intl-conf 배정 레코드 0건 → 축소가 정의상 무손실. 실측 68 + 80 + 75 = 223건 유지 |
| 변경 범위 | content/categories.ts, content/types.ts(유니온), E2E 기대 라우트 목록, README.md 라우트 맵 — P-02 설계 예측대로 레지스트리 중심 수정으로 완결 |
이 확정으로 §4.1 사이트맵·§7 PubCategory·P-01·P-03이 v1.5에서 함께 갱신되었고, 문서 상태가 승인(Approved)으로 전환되었다.
D-09 상세 — 색 토큰 알파 계약 붕괴와 /publications 리다이렉트 (v1.9)
D-09를 촉발한 것은 라우트 문제 하나가 아니라, 정적 게이트 전부를 통과하면서 화면만 무너지는 결함 계열이 한 배치에서 두 종류 확인된 사건이다. 계약을 §8.7로 승격한 근거를 여기에 기록한다.
(1) 근본 원인 — 쉼표 구분 --*-rgb
app/globals.css는 토큰을 --vermillion-rgb: 217, 52, 43;처럼 쉼표 구분으로 정의해 왔다. 반면 tailwind.config.ts는 rgb(var(--vermillion-rgb) / <alpha-value>)를 선언했고, Tailwind는 이를 다음으로 전개한다.
.bg-vermillion { --tw-bg-opacity: 1; background-color: rgb(var(--vermillion-rgb) / var(--tw-bg-opacity, 1)) }
↓ var() 치환 후
rgb(217, 52, 43 / 1) ← 무효
rgb()는 공백+슬래시(현대) 또는 전량 쉼표(레거시) 중 하나여야 하며 혼용은 문법 위반이다. 무효 선언은 invalid at computed-value time 으로 폐기되므로 토큰 배경색이 아예 적용되지 않는다. 커밋 7889398("solid vermillion background")·40b252b("enforce high contrast white text")가 같은 증상을 반복 교정하려 한 이력이 이 진단을 뒷받침한다.
(2) 부작용 — <alpha-value> 제거가 만든 2차 무성 결함
7889398은 위 증상을 colors.ivory = "var(--ivory)" 형태로 축약해 해결했다. 단색은 정상화되었으나, 알파 자리표시자가 사라지면 Tailwind는 슬래시 수식자 유틸리티를 오류 없이 생략한다(독립 프로브로 확인). 그 결과 소스에 남은 26개 사용처가 전부 무효화되었고 lint·tsc·빌드·Gate 0–7은 그대로 통과했다.
| 소멸한 유틸리티 계열 | 대표 사용처 | 실제 화면 |
|---|---|---|
bg-*/… |
Header bg-ivory/85 |
sticky 헤더 배경 소실(본문이 비쳐 지나감) |
border-*/… (15건) |
border-line/60 등 |
Preflight 기본색 #e5e7eb — 팔레트 외 회색, 다크 모드에서 특히 부각 |
text-*/… |
Footer text-ink/90 |
부모 색 상속 |
ring-*/… |
ProjectPageView focus:ring-vermillion/50 |
Tailwind 기본 파란색 포커스 링 |
(3) 3차 결함 — 인라인 style 우회
단색이 적용되지 않는 상태를 우회하려 활성 배지에 style={{ backgroundColor: "var(--vermillion)", color: "#ffffff" }}가 투입되었다. 인라인 style은 dark: 변형을 항상 이기므로 다크 모드에서 흰색 전경이 고정되었고, opacity-90이 함께 도입되어 대비가 추가로 떨어졌다. 이는 Job b3f001de에서 제기하고 43c75da에서 해소했던 R-9.6 결함의 직접 회귀다.
| 상태 | 라이트 | 다크 | 판정 |
|---|---|---|---|
| 배지 라벨 (흰색 단색) | 4.69:1 | 3.74:1 | 다크 미달 |
배지 번호·en (opacity-90) |
4.05:1 | 3.29:1 | 양 테마 미달 |
참고: 43c75da의 dark:text-ivory |
4.69:1 | 5.01:1 | 양 테마 충족 |
(4) 확정 — 계약 복원이 스타일 보존과 일치한다
| 항목 | 내용 |
|---|---|
| 채택 | --*-rgb를 공백 구분으로 정정(R-8.21) + tailwind.config.ts에 <alpha-value> 복원(R-8.22) + 인라인 style·opacity-* 제거(R-8.23) |
| 기각 | <alpha-value> 제거 상태 유지 후 26개 사용처를 각각 리터럴 색으로 치환 — 토큰 체계가 사실상 붕괴하고 다크 모드 반전이 사용처마다 깨진다 |
| 스타일 영향 | 의도된 디자인으로의 복원이며 재디자인이 아니다. 사용처 26곳은 원래 의도대로 렌더되고, 단색 토큰은 7889398 이후 상태를 그대로 유지한다 |
| 재발 방지 | AC-35(슬래시 수식자 실효성) · AC-36(공백 구분) · AC-37(인라인 style 0건) · AC-38(양 테마 대비) 게이트 신설 |
(5) /publications 라우트 (v1.10 재확정)
같은 배치에서 All Overview 탭 제거와 함께 /publications가 redirect()로 대체되어 Gate 8이 실측 실패했다(<main> tag not found in .next/server/app/publications.html).
v1.9는 C안(첫 카테고리 본문 재렌더) 을 채택했으나, 개발 팀장 이의제기(Job 22b7a309)가 정적 HTML 2본이 동일 DOM을 갖는 문제를 지적했고 이는 타당하다. 현재 코드베이스에 metadataBase·alternates.canonical이 전무함을 확인했으므로(grep 0건), C안을 그대로 두면 완화 장치 없이 중복이 노출된다. 이에 A안(Overview 뷰) 으로 교체한다.
| 안 | 중복 | 22a31ff(All 탭 제거) 의도 |
AC-25/40 | 판정 |
|---|---|---|---|---|
| A · Overview 뷰 | 없음 | 보존(탭은 3개 유지) | 충족 | ✅ 채택 |
B · redirect() 유지 |
— | 보존 | 위반 | 기각 |
| C · 첫 카테고리 재렌더 | 2본 동일 | 보존 | 충족 | 기각 (v1.9 → v1.10 교체) |
D · 전체 통합 + All 탭 |
없음 | 역행 | 충족 | 기각 |
한편 이의제기의 두 번째 논거(isActive 하이라이트 모호)는 성립하지 않는다. Header.tsx의 활성 판정은 pathname === href || pathname.startsWith(\${href}/`)이므로, href="/publications"`는 세 하위 카테고리 경로 전부에 대해 이미 참이 된다. v1.9 계획의 3-3(예외 분기 제거)은 이 일반 규칙만으로 성립하며 별도 조치가 필요 없다. Overview에서 하위 탭이 하나도 활성이 아닌 것은 결함이 아니라 Overview의 정상 상태다(→ IA-03).
D-10 상세 — 강조색 교체가 대비를 붕괴시킨 경위 (v1.11)
증상. 커밋 eaddc4f("update primary color token to #4A7CE8 and secondary to #D9342B") 이후 라이트 테마에서 cobalt 계열 소형 텍스트가 읽기 어려워졌다. lint·tsc·프로덕션 빌드·기존 게이트 0~9가 전부 통과한다 — 빌드는 exit 0, 정적 13/13 생성, 동적 라우트 0건이다.
변경 실체. :root 블록 2줄만 바뀌었다.
- --cobalt-rgb: 27 58 138; /* #1B3A8A */
- --cobalt-dark-rgb: 18 40 99; /* #122863 */
+ --cobalt-rgb: 74 124 232; /* #4A7CE8 */
+ --cobalt-dark-rgb: 52 98 204; /* #3462CC */
html.dark 블록(--cobalt-rgb: 77 119 255)과 --vermillion-*는 양 블록 모두 미변경이다.
대비 실측(WCAG 2.1 공식 재계산).
| 조합 | 변경 전 | 변경 후 | 판정 |
|---|---|---|---|
text-cobalt on ivory |
9.23 | 3.49 | 소형 텍스트 미달 |
text-cobalt on paper |
8.35 | 3.16 | 소형 텍스트 미달 |
ivory on bg-cobalt |
9.23 | 3.49 | 미달 |
text-cobalt-dark on paper |
11.16 | 4.48 | 간발의 미달 |
소형 텍스트 미달 사용처는 14건(text-cobalt 12건 + bg-cobalt 소형 배지 2건)이다. 반면 page.tsx:92(text-3xl, 30 px)·page.tsx:174(불릿 도형)·ThemeToggle.tsx:146(아이콘)·members/page.tsx:102,132(hover:border-cobalt)는 대형 텍스트·비텍스트 UI 기준 3:1을 3.49로 충족한다. 즉 #4A7CE8은 큰 글자·도형으로는 적법하고 작은 글자로만 부적법하며, 이 경계가 D-10 채택안의 설계 근거다.
근본 원인 — 반전 계약 이탈. 이 시스템의 모든 토큰은 html.dark에서 반전된다(ivory 245→18, ink 10→245). cobalt도 예외가 아니어서 라이트는 짙은 남색, 다크는 밝은 청색이었다.
| 라이트 L | 다크 L | 라이트↔다크 대비 | |
|---|---|---|---|
| 변경 전 | 0.0509 (#1B3A8A) | 0.2199 (#4D77FF) | 3.13 |
| 변경 후 | 0.2170 (#4A7CE8) | 0.2199 (#4D77FF) | 1.01 |
라이트 값이 다크 값과 사실상 같은 밝기가 되었다 — cobalt 한 토큰만 반전 체계에서 이탈해, 라이트 테마가 다크 테마용 밝기를 그대로 반입했다. → R-8.28.
게이트가 놓친 이유. Gate 6은 ["--ink", "--ivory", …, "--cobalt"]의 문자열 존재 여부만 확인하고, Gate 9는 알파 계약(구분자·<alpha-value>·인라인 style)만 확인한다. run_e2e_tests.py에 contrast·4.5·luminance 검사는 0건이다. 즉 토큰의 "값"을 검사하는 게이트가 없어 --cobalt: #FF00FF로 바꿔도 10개 게이트가 전부 통과한다. → AC-43 · AC-44 · AC-45 · AC-46.
문서가 사고에 기여한 부분. docs/DESIGN.md의 커스터마이즈 훅은 "강조색 2개와 그 -dark 변형만 교체하면 됩니다"라고 교체 방법만 안내하고 지켜야 할 대비 제약을 적지 않는다. 안내를 문자 그대로 따른 결과가 이 커밋이므로, 문서 교정(R-8.27)이 재발 방지의 일부다.
부수 확인 — Secondary는 무변경. 커밋 메시지의 …and secondary to #D9342B는 변경이 아니라 현상 유지의 서술이다. --vermillion-rgb는 최초 커밋 36a4cd8(--vermillion: #d9342b) 이래 상수이며, 02247a0의 217, 52, 43 → 217 52 43은 R-8.21 구분자 교정이지 색 변경이 아니다. 수렴 대장에 "Secondary 변경 검증 완료"로 기재되면 사실과 어긋나므로 무변경(no-op) 으로 기록한다.
AC-42 미충족 잔존. 직전 수렴(02247a0)에서 AC-42는 통과로 판정되었으나, 문언의 "vermillion 배경 위 텍스트 전량" 중 교정된 것은 Header 2곳·CategoryNav 1곳뿐이고 standardization/page.tsx:40·:88, lectures/page.tsx:89, members/page.tsx:177의 4곳이 4.16:1로 남아 있다(뒤 두 곳은 group-open: 상태 변형이라 육안 리뷰에서 누락되기 쉽다). → AC-42 개정.
D-10 보론 — 배지·칩 부류 분리 (v1.12, Agy 이의제기 7f136931 반영)
v1.11의 설계 오류. v1.11 §6.5는 bg-cobalt(#4A7CE8) 배경을 유지한 채 전경만 text-ink로 바꾸도록 정했다. 이는 채택안 C의 원칙("작은 요소는 -dark 변형으로 라우팅한다")을 소형 텍스트 12곳에만 적용하고 동일 크기 등급의 상태 칩 2곳에는 적용하지 않은 일관성 결함이다. 개발 팀장 이의제기가 이를 정확히 지적했다.
기술적 근거(심미 판단과 독립). 이의제기의 논거는 "짙은 검은 텍스트가 매거진 톤을 훼손한다"는 심미 판단이나, 같은 결론을 취향과 무관하게 지지하는 근거가 있다.
bg-cobalt(#4A7CE8) 위 전경 |
대비 |
|---|---|
ivory |
3.49 🔴 |
white |
3.93 🔴 |
ink-soft |
3.94 🔴 |
ink |
5.03 ✅ (유일) |
팔레트 내 후보 4종 중 통과는 1종뿐이고, 그마저 라이트 전용이다 — 다크에서 --ink-rgb가 245 241 232로 반전되어 3.49로 미달하므로 dark:text-ivory를 수동으로 덧대야 한다. 즉 반전 계약을 손으로 우회하는 구조였다. bg-cobalt-dark text-ivory는 6.43 / 6.57로 dark: 없이 양 테마가 자동 통과한다(→ R-8.29).
권장안을 그대로 쓰지 않은 이유 — 짝 칩 무게 불균형. 대상인 app/standardization/page.tsx:86-90은 하나의 삼항식으로, InProgress(vermillion)와 그 외(cobalt) 배지가 문서 목록의 같은 자리에 번갈아 나타난다.
| 조합 | 배경 상대휘도 | 두 칩 간 대비 |
|---|---|---|
v1.11: vermillion #D9342B ↔ cobalt #4A7CE8 |
0.1738 ↔ 0.2170 | 1.19 |
이의제기 권장안: vermillion ↔ cobalt-dark #32549E |
0.1738 ↔ 0.0949 | 1.54 (악화) |
v1.12 확정: vermillion-dark #A8231C ↔ cobalt-dark #32549E |
0.0961 ↔ 0.0949 | 1.01 |
cobalt 칩만 어둡게 내리면 vermillion 칩이 밝은 채로 남아 무게 차가 오히려 벌어진다. 이의제기의 논거(에디토리얼 완성도)가 요구하는 vermillion 쪽 대칭 조치가 권장안에서 누락되었다. 두 강조색의 -dark 변형은 휘도가 거의 같으므로(0.0961 vs 0.0949) 추가 색 조정 없이 균형이 나온다.
부류 A / 부류 B. 크기 기반으로 두 패턴을 분리한다 — R-8.26의 논리(가장 작은 글자에 가장 여유 있는 대비)를 연장한 것이다.
| 부류 | 대상 | 패턴 | 라이트 / 다크 |
|---|---|---|---|
A 상태 칩(text-[0.65rem]) |
standardization:40·:88(verm) · standardization:89 · publications/[category]:135(cobalt) |
bg-{accent}-dark text-ivory |
6.38 |
| B 인터랙티브 내비·토글 | Header:69,129 · CategoryNav:22(교정 완료) · lectures:89 · members:177 |
text-white dark:text-ivory |
4.69 / 5.01 |
부류 B를 -dark로 내리지 않는 이유: ① Header 활성 배지는 사이트에서 가장 눈에 띄는 브랜드 표면이며 #D9342B → #A8231C 변경은 "전체 스타일 유지" 지시를 벗어난다. ② 해당 2곳은 02247a0에서 교정되어 리뷰 PASS를 받았으므로 불필요한 재작업·재검증을 유발한다. ③ 4.69:1은 AA를 충족한다 — 개선 여지는 있으나 결함이 아니다.
시각 변경 고지. 부류 A의 vermillion 칩 2곳은 배경이 #D9342B → #A8231C로 실제로 어두워진다. #A8231C는 팔레트에 이미 정의된 vermillion-dark이므로 신규 색이 아니며(R-8.1 위반 아님) 대상 면적도 text-[0.65rem] 칩 2개로 극히 작다. GM이 배경 무변경을 선호하면 부류 B 패턴(bg-vermillion text-white dark:text-ivory, 4.69)으로 내려도 규격은 충족되며, 그 경우 위 표의 무게 불균형 1.54가 남는다는 점만 함께 기록한다 — 차단 사유가 아니라 선택지다.
D-12 상세 — 게이트가 녹색인 채로 남은 결함과 브랜드 색의 가시성 (v1.13)
관측. eaddc4f → 082d71e 4개 커밋 이후 상태에서 npm run build(exit 0 · 13/13 정적 · ƒ Dynamic 0건)와 run_e2e_tests.py Gate 0~10 전량이 통과한다. 그러나 같은 상태에서 WCAG AA 미달 6건과 통일성 결함 9건이 실재한다. 특히 lectures/page.tsx:89는 v1.12 AC-42 부류 B에 "미교정"으로 명시 등재된 항목인데 신설된 대비 게이트가 이를 통과시켰다.
원인 — 게이트의 범위 결함 3종.
| ID | 결함 | 결과 |
|---|---|---|
| G-1 | AC-44 구현의 면제 조항 if … or "text-vermillion" in line: continue. 위반 판정 정규식이 text-(cobalt|vermillion)이므로 vermillion으로 매치된 라인은 예외 없이 그 문자열을 포함한다 |
AC-44의 vermillion 절반이 영구 무효. 실제 소스 4개 라인 + 주입 2건을 동일 로직에 투입해 전부 면제됨을 재현 |
| G-2 | AC-45 구현이 cobalt-dark·vermillion-dark 2종만 검사 |
--cobalt 반전 대비 1.00 미검출 — D-10 근본 원인의 재발 |
| G-3 | AC-43 구현이 토큰 값만 보고 소스의 전경/배경 쌍은 보지 않음 | bg-cobalt-dark text-white(다크 2.85)를 작성해도 통과 |
G-1은 N6(Gate 8 C1/C2 공허 단정, 10라운드 미해소)과 동일 유형이다 — 단정·면제가 구조적으로 발화하지 않는데 출력은 ✅로 찍힌다. 개별 수정이 아니라 형식 차원의 금지(R-8.32)로 대응한다. 아울러 §12.1 D-09(알파 계약)·D-10(반전 계약)에 이어 focus:ring-cobalt/50 1.80 · hover:border-cobalt/60 1.95가 드러났다 — 알파·토큰 조합이 무성으로 대비를 무너뜨리는 유형의 세 번째 발현이며 R-8.30의 근거다.
브랜드 색의 가시성. 라이트 테마에서 지정 Primary #4E77FF가 정적으로 칠해지는 표면은 히어로 SVG와 6 px 불릿 2곳뿐이다. 나머지는 전부 hover·focus 상태이거나 -dark #345AD2다.
| 표면 | 색 | 상태 |
|---|---|---|
히어로 HeroComposition SVG (var(--cobalt)) |
#4E77FF | 정적 |
Pillar 불릿 page.tsx:174 bg-cobalt (6 px) |
#4E77FF | 정적 |
members:102,132 hover:border-cobalt · ProjectPageView:35,44 |
#4E77FF | hover/focus 전용 |
ThemeToggle:146 text-cobalt |
#4E77FF | 다크 테마 전용 렌더 |
| 섹션 괘선·키커·링크·지표·Pillar 라벨(20여 곳) | #345AD2 | 정적 — 사용자가 "Primary"로 인지하는 색 |
즉 지시는 토큰 수준에서 충족되었으나 화면 수준에서는 다른 색이 Primary로 읽힌다. 접근성을 지키면서 이 간극을 좁히는 유일한 경로가 B안(대형 표면 확대) 이다 — page.tsx:84,92의 30 px 지표처럼 3:1만 요구되는 표면은 #4E77FF로 칠해도 적법하다(실측 3.45). 반대로 -dark를 브랜드 색 쪽으로 밝히는 C안은 paper 여유가 0.26뿐이라 D-10이 #3C64BC를 배격한 것과 같은 사유로 기각한다.
시맨틱 규약의 분열. docs/DESIGN.md:30과 R-8.5는 vermillion = Agent Eng / Orchestration을 규정한다. 2441f35가 히어로의 Orchestration 강조어를 cobalt로 바꾸었으나, 같은 파일의 PILLARS 교차 배정(page.tsx:12~48)은 규약을 유지 중이다 — 한 페이지 안에서 규약이 둘로 갈렸다. 코드를 되돌리든 문서를 개정하든 무방하나, 둘 중 하나는 반드시 상대에 맞춰야 AC-23이 성립한다.
12.2 리스크
| ID | 리스크 | 영향 | 완화 방안 |
|---|---|---|---|
| R-01 | 레거시 HTML의 비정형 마크업으로 추출 정확도 저하 | PR-01 위반 (데이터 누락·오배치) | MG-01 스크립트화 + MG-02 건수 대조 + P1-R 독립 검증 |
| R-02 | 223건 일괄 렌더로 초기 로드 지연 | 성능 저하 | P-07 점진적 노출, R-9.11·9.12 예산 명시 |
| R-03 | Tailwind JIT이 동적 조립 클래스를 인식하지 못함 | 빌드는 성공하나 조판이 조용히 붕괴 | 클래스는 완전한 문자열 리터럴로 작성. AC-20으로 빌드 CSS 실측 검증 |
| R-08 (v1.1 신설) | Publications 필터 구현이 정적 생성을 깨뜨림 | ƒ Dynamic 전환 → DM-03·NF-03 위반, 또는 빌드 중단 |
§8.5 실측 규칙 R-8.11~8.16 준수. AC-17·AC-21·AC-22로 검증 |
| R-09 (v1.1 신설) | 레코드 목록이 클라이언트 렌더로 밀려 정적 문서에서 누락 | PR-01 실질 위반 — 크롤러·JS 미실행 환경에서 실적이 보이지 않음 | R-8.15 서버 렌더 강제. AC-14로 JS 비활성 검증 |
| R-04 | 실명·실적 데이터 오기재 | 연구실 신뢰도 훼손 | R-9.17·9.18 무결성 원칙, MG-05 창작 금지, 지도교수 최종 확인 |
| R-05 | 잔재 검사(MG-08)가 논문 제목의 도메인 용어까지 오검출 | 실데이터를 잔재로 오인해 삭제 → PR-01 위반 | MG-08 예외 규정을 검사 스크립트에 반영. 검사 범위를 정체성 서술 영역으로 한정 |
| R-06 | 문서-코드 불일치 재발 | 후속 작업자 혼선 | R-9.19. 미완 영역은 문서에 미완으로 표기 |
| R-07 | P2(Header 수정)와 P3~P5 병렬 진행 시 충돌 | 머지 충돌 | §11.1 주석대로 P2 선행 완료 |
| R-10 (v1.13 신설) | 색값 교체가 대비 재산정표 없이 5회 연속 진행됨(eaddc4f·ca4a7ee·8db16e4·2441f35·082d71e 전부 커밋 본문 없음) |
관행화 시 무성 실패가 반복 발생 | R-8.1·R-8.27 이행 강제 + AC-50으로 docs/DESIGN.md 커스터마이즈 훅 교정. 문서가 원인으로 규명된 지 2라운드째 미교정 |
| R-11 (v1.13 신설) | 게이트 통과가 결함 부재의 근거로 오용될 위험 — Gate 0~10 전량 ✅인 상태에서 AA 미달 6건이 실재했다 | 잘못된 PASS 확정 | 폴트 인젝션 없는 게이트는 채택하지 않는다(AC-46 · AC-49). 신설 게이트는 현행 코드 자체가 주입 상태인 항목(F1·F2·F3·F7)으로 즉시 실효성을 확인한다 |
| R-12 (v1.13 신설) | --cobalt-dark #345AD2의 paper 여유가 0.26뿐 |
후속 변경 1회로 재미달 | 추가 상향 금지(D-10 v1.13 개정). 변경 시 R-8.27 재산정 필수 |
| R-13 (v1.13 신설) | Phase 3 색 통일 작업이 "에디토리얼 디자인 시스템 유지" 목표와 충돌할 소지 | 시각적 대변경 | 단일화 대상을 동일 역할 시그니처 내부로 한정(R-8.31). 색 선택 자체는 D-12로 이관 |
13. 부록: 레거시 데이터 인벤토리 (실측)
ISL-2026/ 기준, 2026-07-30 파싱 실측치.
| 원본 파일 | 레코드 수 | 비고 |
|---|---|---|
member.html |
재학 16 / 졸업 60 | 재학: 교수 1, Ph.D. 1, Ph.D. Candidate 4, Ph.D. Student 5, M.S. Candidate 3, M.S. Student 2. 졸업생 2007~2026 |
paper-international.html |
68 | 저널 67 + 학술대회 1. 최신 2026-04(IEEE TNSM), 최고(最古) 1995 |
paper-domestic.html |
80 | KCI 등재 표시 48건. 최신 2026-06 |
patent.html |
75 | 국내 출원 다수 + US 출원 일부. 최신 출원 2025-12-16 |
standard.html |
기구 6 / 문서 약 55 | 국제 5개 기구 + 국내 1개(TTA/PG425). 2000~현재 |
lecture.html |
약 20개 학기 | 2016 Fall ~ 2026 Spring |
index.html |
연구분야 3종 | IoT Standards, CCIS, VLC-IoT — 폐기 대상(5대 기둥으로 교체, R-5.3) |
introduction.html |
연구 주제 13종 | 구 연구 분야 상세 — 폐기 대상(R-5.3) |
image/, assets/ |
11.6 MB | image/ 3.4 MB + assets/ 8.2 MB. 선별 이관(MG-06) |
연락처·소재지 (H-13~H-15 원천)
- 소재지: 경북대학교 IT대학 5호관(415동) 527호 (레거시
index.html에 HTML 주석 처리된 상태로 존재 — 복원 필요) - 소속: School of Computer Science and Engineering, Kyungpook National University
- 지도교수 이메일:
sjkoh@knu.ac.kr - 연구실 GitHub:
https://github.com/iot-standards-laboratory(→ D-05) - 지도교수 GitHub:
https://github.com/sjkoh12 - 기관 링크: KNU
http://www.knu.ac.kr/· 컴퓨터학부http://cse.knu.ac.kr/· IT대학http://it.knu.ac.kr/ - 전화·팩스: 레거시에 없음 (H-14에 따라 창작 금지)
14. 변경 이력
| 버전 | 일자 | 작성자 | 내용 |
|---|---|---|---|
| 1.0 | 2026-07-30 | claude (planner) | 최초 작성. 사용자 원본 요구사항(§1)을 정본으로 확장. Job 4148350e |
| 1.1 | 2026-07-30 | claude (planner) | 개발 팀장(Agy) 기술 이의제기(Job 175860e4) 반영. §8.5 Next.js 렌더링 제약 신설(실측 5종). IA-03을 라우트 세그먼트 방식으로 개정, P-06 개정 + P-06a·P-07a 신설, DM-03·NF-03·AC-05·AC-16 문구 정정, AC-22~24 및 R-08·R-09 신설. Job 45d05868 |
| 1.2 | 2026-07-30 | agy (creator) | 교차 리뷰 리포트(Job 3820bdc8) 결함 피드백 전면 반영. F1 §4.1 사이트맵 쿼리 표기를 라우트 세그먼트(/publications/<slug>)로 갱신, F2 §2.1·§2.2 연구 실적 수치 279건 → 223건 정정, F3 §10 수용 기준 AC-14~24 순서 및 그룹핑 정돈. Job f3e09780 |
| 1.3 | 2026-07-30 | agy (creator) | 교차 리뷰 리포트(Job 60c92d3a) 결함 피드백 전면 반영. G-1 417행 R-8.16 참조 AC-16 → AC-17 정정, G-4 575행 R-03 참조 AC-19 → AC-20 정정, G-2 576행 R-08 참조 AC-16/22/23 → AC-17/21/22 정정, G-3 577행 R-09 참조 AC-24 → AC-14 정정. Job a535ce20 |
| 1.4 | 2026-07-30 | agy (creator) | 구현 교차 리뷰 리포트(Job 777c3ab8) 피드백 전면 반영. I1 전 파서 ISO 8601 정규화 100%, I2 Footer 주소/이메일 실주소 교체, I3 README 라우트 맵 갱신, I4 verify_counts.py 엄격 게이트로 강화 및 실측 수치(표준 44, 학기 45) 정정, I5 pycache 제거 및 .gitignore 차단, I6/I7 Home 카운터 및 5대 기둥 영문 라벨 정본 정렬. Job a54723ce |
| 1.5 | 2026-07-30 | claude (planner) | D-01 확정 및 문서 상태 승인(Approved) 전환. commit 51aae14(백로그 4건 반영)에 대한 검증 결과를 정본에 동기화: intl-conf 단독 카테고리 폐기(A·B안 기각, C안 채택 — §12.1 D-01 상세에 결정 근거 기록), §4.1 사이트맵·§7 PubCategory 유니온·P-01·P-03·IA-03·§11 P0 갱신, 사이트맵의 학기(45)·표준 문서(44) 실측치 정정. Job 343b5808 |
| 1.6 | 2026-07-30 | claude (planner) | 개발 팀장(Agy) 기술 이의제기(Job 2560771b) 반영. §8.6 레이아웃 컨테이너 아키텍처·브레이크포인트 토큰 신설(R-8.17~R-8.20) — <main> 일괄 부여안을 기각하고 3계층 분리(전체 폭 <main> / 라우트 래퍼 container-content / full-bleed 밴드)를 채택, w-screen 탈출 기법 금지(R-8.18) 및 desktop: 1240px 스크린 토큰화(R-8.20, Tailwind 정렬 동작 실측 확인). D-06 신설·확정, AC-25·AC-26 신설, R-9.14 검수 뷰포트 6종으로 확대. AC-21 정적 HTML 4개 → 3개, R-8.15 표준 문서 55 → 44건 실측치 정정. Job 019b7331 |
| 1.7 | 2026-07-30 | claude (planner) | Home Hero → Research Project PageView 전환 계획 반영. §6.1.2 신설(PJ-01period·deliverables를 content/standards.ts 조인으로 도출하는 무창작 설계, 활성 슬라이드 전용 캐러셀 금지(PJ-08)·URL 상태 동기화 금지(PJ-09)·캐러셀 라이브러리 금지(PJ-10)·scroll-snap 기반 JS-off 동작 보장(PJ-11) 규정. H-02 개정(슬로건 교체 허용 + H-03·H-04·H-05·H-06·H-07·H-10 존속 명시). **AC-27ResearchProject·ProjectDeliverable 타입 추가, D-07·D-08 신설. Job 6b3840a1 |
| 1.8 | 2026-07-30 | claude (planner) | 개발 팀장(Agy) 기술 이의제기(Job 2299a6b9) 반영. PJ-13 개정 — 데스크톱 3카드를 flex 스크롤 트랙에서 grid-cols-3 정적 3열 + overflow-visible 로 전환하고 데스크톱 퍼센트 연산을 제거. PJ-15·PJ-16 신설(min-w-0+줄바꿈으로 shrink-0 min-content 넘침 방어 / 스크롤바 은폐 시 AC-34 동반 의무), AC-34 신설(데스크톱 scrollWidth === clientWidth 실측 판정). 이의제기의 근거 수식은 정정 — calc(33.333%-16px)은 초과가 아니라 0.0125 px 미달이며, 대안 B의 분수식은 여유가 0이어서 해당 실패 모드에 오히려 더 취약하다. Tailwind가 calc 연산자 공백을 자동 삽입함과 grid-cols-3의 minmax(0,1fr) 전개·미디어 쿼리 출력 순서를 실측 확인. Job 294570ab |
| 1.9 | 2026-07-31 | claude (planner) | 스타일 관련 누적 커밋 23건(43c75da..b7f2e05) 검증 결과 반영. §8.7 색 토큰 알파 계약 신설(R-8.21--*-rgb가 rgb(a, b, c / α) 무효 선언을 만들어 토큰 색이 적용되지 않던 근본 원인을 규명하고, 그 우회로 도입된 <alpha-value> 제거가 슬래시 수식자 유틸리티 26건을 무성 소멸시킴을 독립 프로브로 실측 확인. 인라인 style·opacity-* 토큰 우회 금지(R-8.23)와 헤더 가로 예산(R-8.24, 1240 px 기준 −69.3 px 초과 산정) 규정. D-09 신설·확정(/publications redirect() 기각 → 기본 카테고리 화면), IA-03 개정, **AC-359a79e302 |
| 1.10 | 2026-07-31 | claude (planner) | 개발 팀장(Agy) 기술 이의제기(Job 22b7a309) 반영. D-09 재확정 — v1.9의 C안(첫 카테고리 본문 재렌더)이 동일 DOM 정적 HTML 2본을 만든다는 지적이 타당하여 A안(Overview 뷰) 으로 교체하고, All 탭 재도입(D안)은 commit 22a31ff 결정 역행·P-07 충돌로 기각. R-8.25 신설(라우트 간 콘텐츠 중복 금지 + canonical 예외 절차), AC-41 신설(<main> 정규화 해시 중복 0건), IA-03 재개정. 이의제기의 isActive 논거는 정정 — pathname.startsWith(\${href}/`)일반 규칙이 하위 카테고리를 이미 포괄하므로 모호성이 없음을 코드로 확인. 아울러 별건으로CategoryNav 활성 탭(bg-vermillion text-ivory)이 **라이트 테마 4.16:1로 R-9.6 미달**임을 발견해 **AC-42 신설**. Job 6a6094c6` |
| 1.11 | 2026-07-31 | claude (planner) | 강조색 교체 커밋 eaddc4f 검증 및 리뷰 수렴. 라이트 테마 cobalt 대비가 9.23:1 → 3.49:1(ivory) / 8.35 → 3.16(paper)로 붕괴하여 소형 텍스트 14개 사용처가 AA 미달임을 WCAG 공식 재계산으로 확정. 근본 원인은 명암 반전 계약 이탈(라이트↔다크 상대휘도 대비 3.13 → 1.01)이며, run_e2e_tests.py에 대비 검사가 0건이라 게이트 0--cobalt는 사용자 지정 #4A7CE8을 유지하고 --cobalt-dark만 #3462CC → #32549E(paper 4.48 → 5.82)로 재조정해 소형 텍스트를 -dark로 라우팅(A·B·D안 기각). D-11 신설(🟡 text-vermillion 소형 텍스트 30여 곳, 기본값 현행 유지). AC-42 개정 — 직전 수렴에서 통과 판정되었으나 standardization:40,88·lectures:89·members:177 4곳이 4.16:1로 미교정 잔존함을 확인하고 대상을 명시 목록화, text-white on vermillion 수치를 4.58 → 4.69로 정정. §8.1 색상 토큰표를 실제 값과 동기화하고, Secondary #D9342B는 최초 커밋 이래 무변경(no-op) 임을 계보로 확인해 기록. Job 5c2137c6 |
| 1.12 | 2026-07-31 | claude (planner) | 개발 팀장(Agy) 기술 이의제기(Job 7f136931) 반영. D-10 배지·칩 결정 재확정 — v1.11의 bg-cobalt text-ink dark:text-ivory(5.03 / 4.82)는 채택안 C의 원칙(작은 요소는 -dark 라우팅)을 소형 텍스트 12곳에만 적용하고 동일 크기 등급의 상태 칩 2곳에는 적용하지 않은 일관성 결함이었음을 인정하고 폐기, bg-{accent}-dark text-ivory 로 교체(6.38text-white dark:text-ivory(7.25)는 미채택 — -dark 배경에서는 ivory만으로 양 테마가 통과해 팔레트 외 색 white와 dark: 변형이 모두 불필요하다(R-8.29 신설). 아울러 권장안을 그대로 적용하면 standardization:87-89 삼항식의 나란한 두 칩 상대휘도 대비가 1.19 → 1.54로 악화됨을 실측해, vermillion 칩도 -dark로 통일하여 1.01 균형을 달성(R-8.26에 배지·칩 라우팅 및 짝 칩 등급 일치 조항 추가). 배지류를 부류 A(text-[0.65rem] 상태 칩 4곳) / 부류 B(인터랙티브 내비·토글 5곳) 로 분리해 AC-42 개정, -dark가 배경으로 쓰이는 조합을 AC-43 검사 대상에 추가(v1.11 목록은 전경만 다루어 칩 배경을 놓쳤다), AC-47 신설(팔레트 외 색 상한 8건 화이트리스트), AC-46에 폴트 인젝션 ⑤·⑥ 추가(폐기된 v1.11 칩 패턴 및 white 증가 검출). 부류 A vermillion 칩 2곳의 배경이 #D9342B → #A8231C로 어두워지는 시각 변경은 GM 승인 사항으로 명시하되 차단 사유가 아님을 기록. Job 3d3b823a |
| 1.13 | 2026-07-31 | claude (planner) | 테마 색상 통일성 검증 계획 수립 (eaddc4f→082d71e 4개 커밋). Gate 0~10 전량 통과·빌드 exit 0인 상태에서 WCAG AA 미달 6건·통일성 결함 9건이 실재함을 실측으로 확정 — 게이트 통과가 곧 오탐 신호였다. 원인은 게이트 범위 결함 3종: ⓐ AC-44의 vermillion 절반이 구조적으로 무효(면제 조항 "text-vermillion" in line이 판정 정규식과 항상 동시 매치 — 실소스 4라인 + 주입 2건으로 재현), ⓑ AC-45가 -dark 2종만 검사해 --cobalt 반전 대비 1.00(D-10 근본 원인의 재발)을 미검출, ⓒ AC-43이 소스의 전경/배경 쌍을 보지 않아 bg-cobalt-dark text-white(다크 2.85)를 통과. R-8.30 신설(비텍스트 UI 3:1 · 알파는 합성 후 산정 — focus:ring-cobalt/50 1.80 · hover:border-cobalt/60 1.95 검출), R-8.31 신설(역할 시그니처 단위 색 통일 — 괘선 6:1 · 키커 11:1 · 배지 전경 6:4 · hover 테두리 4종 · 포커스 2종, 지도교수 이메일 1값이 3색 3대비), R-8.32 신설(게이트 면제는 (파일,행,사유) 등재만 허용 · 라인 부분문자열 면제 금지 — N6과 동일 유형). R-8.5·R-8.26·R-8.28 개정, AC-42·43·44·45·47 개정, AC-48~AC-50 신설(Gate 11 C11-1docs/DESIGN.md 동기화 4건). §8.1 색상표를 실제 토큰값 #4E77FF/#345AD2로 동기화하고 D-10 확정값을 #345AD2로 개정(paper 4.76, 여유 0.26 → R-12). D-12 신설(🔴 Primary 적용의 판정 기준 — 라이트 테마에서 #4E77FF가 정적으로 보이는 곳이 2곳뿐이며 인지색은 #345AD2. 히어로 Orchestration이 R-8.5·DESIGN.md §2를 위반해 cobalt로 변경되어 한 페이지 안에서 규약이 분열), D-13 신설(🟡 --vermillion 반전 1.25). A-1 lectures:89 4.16 미교정 잔존·A-2 not-found.tsx:22 4.16 신규 발견(어떤 AC에도 없던 항목)·A-7 ::selection 4.16 미등재 확정. D-11 실측 갱신(23건, 최저 3.77). 색 교체 5회 연속 대비표 미첨부(R-10). Job 43f3f74a |
| 1.14 | 2026-07-31 | claude (planner) | 개발 팀장(Agy) 기술 이의제기(Job 4962a667) 반영. 구조적 통찰 채택 — 다크 --cobalt만 단독 상향하면 다크 지면 대비가 DEFAULT 9.2 > -dark 5.96으로 계층이 역전됨을 실측 확인, v1.13 §7 각주의 누락을 인정하고 R-8.33 신설(토큰 등급 불변식). 다만 불변식을 절대 휘도 순서가 아니라 테마 상대 대비로 정식화 — 절대 순서의 테마 간 뒤집힘은 vermillion 쌍에서도 동일한 정상 동작이며 현행 8개 셀 전부에서 성립하므로, 절대 휘도로 판정하면 정상 상태를 오판한다. 제안 수치 미채택 — 주 권장값 #85ACFF의 반전 대비는 1.73으로 조정을 촉발한 R-8.28(≥2.0) 자체를 충족하지 못하며, 제안 표의 #345AD2 L=0.095는 폐기된 #32549E의 값(실제 0.1270)이라 #B0CDFF 반전 대비 2.50도 실제 3.68이다. 이의제기 지점에서 더 큰 결함 발굴 — 다크 --cobalt(#4D77FF)는 bg-paper 위 4.37이므로 v1.12가 지시한 text-cobalt-dark dark:text-cobalt 라우팅이 다크 절반을 DEFAULT로 되돌려 8곳이 AA 미달이다(AC-51 신설). 원인은 R-8.26의 "paper 기준 산정" 원칙을 본 계획자가 라이트 테마에만 적용한 오류로, v1.11 §6.5와 같은 형태의 누락이다. 게이트도 AC-44 정규식의 부정 후방탐색 (?<!dark:)로 다크 절반을 설계상 면제하고 있었다(G-7 — G-1·G-2·G-3에 이은 네 번째 "검사를 절반만 한다" 유형). 처방을 토큰 조정에서 dark: 변형 제거로 재설계 — -dark는 반전 토큰이므로 dark: 없이 4개 셀 전부(5.26/4.76/6.57/5.96)를 통과한다. R-8.29 강화(강조색 dark: 금지 · 정본 패턴 3종 · 현행 위반 38건), R-8.26·AC-43·AC-44·AC-48(C11-9)·AC-49(F10·F11, 총 11건) 개정. D-14 신설(🔴 --cobalt 반전 1.00 — A안 브랜드 고정 예외 권고 / B안 대칭 상향 정정 수치 #A8BCFF+#C7D4FF). A안은 본 계획자가 작성한 R-8.28의 완화를 포함하므로 cline·GM 별도 심사 대상으로 명시했고, 안전망 유지 근거로 #1B3A8A 역주입 시 AC-43 즉시 실패(1.80)를 제시했다. Job d35bc3e7 |
| 2.0 | 2026-08-24 | claude (planner) / agy (creator) | 실시간 동적 런타임 페칭 아키텍처 도입 (DM-03·AC-17·R-08 개정). Go/Gin 백엔드 REST API(http://localhost:8080/api/v1) 연동 및 force-dynamic + cache: 'no-store' 적용으로 전 페이지 실시간 데이터 바인딩 지원. 6개 데이터 라우트를 ƒ (Dynamic)으로, 4개 프레임워크 라우트를 ○ (Static)으로 분리. 기존 content/*.ts 정적 상수를 장애 시 그레이스풀 폴백 데이터셋으로 유지. E2E 테스트 게이트 2, 4, 7, 8을 라이브 서버 기반 검증으로 리팩터링. Job 258f6ff7 |