refactor: resolve all code review feedback (B1-B8 & Option A 5 Pillars) for ANL lab transformation
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
||||
@@ -62,11 +62,11 @@ npm run dev
|
||||
|
||||
| 경로 | 설명 |
|
||||
| --- | --- |
|
||||
| `/intro` | 연구실 소개 — 두 가지 연구 축(MCM, QUIC)과 연구 분야 |
|
||||
| `/intro` | 연구실 소개 — 5대 핵심 연구 기둥(Agent Core Eng, MCP & SKILL, Orchestration, A2A/ACP Standards, AIoT & gRPC) |
|
||||
| `/members` | 구성원 — 지도교수 및 박사·석사·학부 연구원 (placeholder) |
|
||||
| `/publications` | 논문 — 대표 저널/학회 논문 목록 (placeholder) |
|
||||
| `/lectures` | 강의 — 담당 학부·대학원 강의 (placeholder) |
|
||||
| `/standardization` | 표준화 활동 — oneM2M, W3C WoT, IETF QUIC, OMA LwM2M 기여 (placeholder) |
|
||||
| `/standardization` | 표준화 활동 — A2A, ACP, W3C WoT, IETF QUIC 기여 (placeholder) |
|
||||
|
||||
## 디자인 시스템 (Design System)
|
||||
|
||||
@@ -79,7 +79,7 @@ npm run dev
|
||||
|
||||
- **색상(Colors):** `tailwind.config.ts` 의 `theme.extend.colors` 에서 디자인 토큰을
|
||||
수정합니다 — `ink`(본문·괘선), `ivory`/`paper`(종이 배경), `line`(헤어라인),
|
||||
그리고 두 에디토리얼 강조색 `vermillion`(MCM/저널) · `cobalt`(QUIC/학회). 같은 값이
|
||||
그리고 두 에디토리얼 강조색 `vermillion`(Agent Engineering / Orchestration) · `cobalt`(MCP / A2A Protocol). 같은 값이
|
||||
`app/globals.css` 의 `:root` CSS 변수에도 미러링되어 있으니 **두 곳을 함께** 바꾸세요.
|
||||
(`brand`/`accent` 별칭은 레거시 호환용이므로 신규 코드에서는 사용하지 마세요.)
|
||||
- **폰트(Fonts):** `app/layout.tsx` 에서 `next/font` 로 로드해 CSS 변수
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Abstract editorial hero — a custom illustration (inline SVG, no asset).
|
||||
* • MCM → a constellation of interconnected nodes (vermillion).
|
||||
* • A2A → a constellation of interconnected nodes (vermillion).
|
||||
* • QUIC → flowing, multiplexed streams (cobalt), animated dash flow.
|
||||
* Animations are pure CSS (tailwind keyframes: node-pulse, stream-dash).
|
||||
*
|
||||
@@ -11,7 +11,7 @@ export default function HeroComposition({
|
||||
}: {
|
||||
className?: string;
|
||||
}) {
|
||||
// MCM node coordinates (interconnected mesh, upper-left field).
|
||||
// A2A node coordinates (interconnected mesh, upper-left field).
|
||||
const nodes = [
|
||||
{ x: 70, y: 90 },
|
||||
{ x: 160, y: 60 },
|
||||
@@ -36,7 +36,7 @@ export default function HeroComposition({
|
||||
<svg
|
||||
viewBox="0 0 380 380"
|
||||
role="img"
|
||||
aria-label="MCM 상호운용 노드와 QUIC 멀티스트림을 형상화한 추상 일러스트레이션"
|
||||
aria-label="A2A 에이전트 메시와 QUIC/gRPC 멀티스트림을 형상화한 추상 일러스트레이션"
|
||||
className={className}
|
||||
>
|
||||
{/* Frame */}
|
||||
@@ -66,7 +66,7 @@ export default function HeroComposition({
|
||||
})}
|
||||
</g>
|
||||
|
||||
{/* ---- MCM: interconnected node mesh (vermillion) ---- */}
|
||||
{/* ---- A2A: interconnected node mesh (vermillion) ---- */}
|
||||
<g stroke="#D9342B" strokeWidth="1.5">
|
||||
{edges.map(([a, b], i) => (
|
||||
<line
|
||||
@@ -97,12 +97,12 @@ export default function HeroComposition({
|
||||
</g>
|
||||
|
||||
{/* Annotations — placed in the top corners (y=24), clear of the
|
||||
MCM node mesh (y=60..240) and the QUIC stream curves (y≥250 with
|
||||
A2A node mesh (y=60..240) and the QUIC stream curves (y≥250 with
|
||||
control points reaching y+40=380). See LAYOUT_AUDIT #3 and
|
||||
REVIEW §3 "P1 #3" — keeping them at y=24 (mirror corners) preserves
|
||||
a symmetric layout that the original LAYOUT_AUDIT mirror decided on. */}
|
||||
<text x="20" y="24" fill="#0A0A0A" fontSize="11" fontWeight="600" letterSpacing="2">
|
||||
MCM · MESH
|
||||
A2A · MESH
|
||||
</text>
|
||||
<text
|
||||
x="360"
|
||||
|
||||
@@ -12,45 +12,80 @@ export const metadata: Metadata = {
|
||||
"QUIC, gRPC, A2A 기반 에이전트 통신 및 멀티에이전트 오케스트레이션을 연구하는 경북대학교 AI 에이전트 네트워크 연구실 (ANL) 소개.",
|
||||
};
|
||||
|
||||
// CUSTOMIZATION HOOK: the two research thrusts (cover spread comparison).
|
||||
const thrusts = [
|
||||
// CUSTOMIZATION HOOK: the five research pillars (5 Pillars, Option A).
|
||||
const pillars = [
|
||||
{
|
||||
no: "Thrust 01",
|
||||
tag: "MCM",
|
||||
no: "Pillar 01",
|
||||
tag: "Agent Eng",
|
||||
accent: "vermillion" as const,
|
||||
ko: "메타버스 상호운용성",
|
||||
en: "Metaverse Interoperability",
|
||||
desc: "이종(異種) 메타버스 플랫폼 간 객체·아바타·자산의 상호운용을 위한 공통 데이터 모델과 변환 계층을 설계합니다. oneM2M / W3C 표준을 기반으로 서로 다른 가상 환경이 동일한 의미(semantics)로 데이터를 교환합니다.",
|
||||
ko: "AI 에이전트 3대 핵심 엔지니어링",
|
||||
en: "Agent Core Engineering",
|
||||
desc: "프롬프트, 컨텍스트, 하네스 엔지니어링을 결합하여 대화 상태 보존, 외부 기억 바인딩, 도구 연동 인터페이스를 설계하고 자율 추론 경로를 최적화합니다.",
|
||||
points: [
|
||||
"공통 정보 모델(Common Information Model) 정의",
|
||||
"의미 보존 변환(semantic-preserving mapping) 계층",
|
||||
"상호운용성 테스트베드 및 적합성 검증",
|
||||
"역할 페르소나 및 Few-shot 최적화",
|
||||
"동적 컨텍스트 윈도우 & Memory 바인딩",
|
||||
"물리적 도구(Tool Use) 하네스 연결",
|
||||
],
|
||||
},
|
||||
{
|
||||
no: "Thrust 02",
|
||||
tag: "QUIC",
|
||||
no: "Pillar 02",
|
||||
tag: "MCP & SKILL",
|
||||
accent: "cobalt" as const,
|
||||
ko: "멀티에이전트 오케스트레이션",
|
||||
en: "Multi-Agent Orchestration",
|
||||
desc: "다수의 자율 에이전트가 저지연·다중스트림 환경에서 협력하도록 QUIC 전송 위에 오케스트레이션 아키텍처와 통신 인터페이스를 설계합니다. 연결 마이그레이션과 스트림 다중화로 메시지 라우팅을 최적화합니다.",
|
||||
ko: "AI Agent 기능 확장 프로토콜",
|
||||
en: "Extensibility & Protocol",
|
||||
desc: "Anthropic MCP 통일 호환 규격 및 코드+스키마+Few-shot이 패키징된 SKILL 모듈을 통해 에이전트의 로컬/원격 역량을 자율적으로 동적 확장합니다.",
|
||||
points: [
|
||||
"QUIC 스트림 다중화 기반 에이전트 메시지 라우팅",
|
||||
"오케스트레이터–에이전트 제어 인터페이스 설계",
|
||||
"연결 마이그레이션 기반 모바일·엣지 지원",
|
||||
"MCP (Model Context Protocol) 통일 규격",
|
||||
"자율 확장 SKILL 모듈 패키징",
|
||||
"CLI 기반 자율 코딩 에이전트 제어",
|
||||
],
|
||||
},
|
||||
{
|
||||
no: "Pillar 03",
|
||||
tag: "Orchestration",
|
||||
accent: "vermillion" as const,
|
||||
ko: "멀티 에이전트 협업 및 오케스트레이션",
|
||||
en: "Multi-Agent Systems",
|
||||
desc: "단일 에이전트의 환각과 컨텍스트 인지 한계를 극복하기 위해 역할 세분화(Role Specialization) 및 이종 모델 교차 검증과 오케스트레이션 인프라를 구축합니다.",
|
||||
points: [
|
||||
"HERDR 백그라운드 프로세스 컨테이너 격리",
|
||||
"crewAI 역할/목표 기반 크루 프로세스",
|
||||
"LangGraph 상태 보존형 순환 그래프 제어",
|
||||
],
|
||||
},
|
||||
{
|
||||
no: "Pillar 04",
|
||||
tag: "A2A & ACP",
|
||||
accent: "cobalt" as const,
|
||||
ko: "에이전트 상호운용성 개방형 표준",
|
||||
en: "Interoperability Standards",
|
||||
desc: "Linux Foundation A2A 및 IBM ACP 오픈 표준 기반으로 이종 에이전트 간 서비스 발견, 태스크 위임, Agent Card 프로필 명세를 구현합니다.",
|
||||
points: [
|
||||
"A2A (Agent-to-Agent) 통신 오픈 표준",
|
||||
"ACP 서비스 발견 & 태스크 위임",
|
||||
"Agent Card (/.well-known/agent-card.json)",
|
||||
],
|
||||
},
|
||||
{
|
||||
no: "Pillar 05",
|
||||
tag: "AIoT & gRPC",
|
||||
accent: "vermillion" as const,
|
||||
ko: "AIoT & 고성능 통신 백본",
|
||||
en: "High-Performance Backbone",
|
||||
desc: "스마트 팩토리/팜 엣지 자원 제약 환경에서 경량 프로토콜(MQTT/CoAP)과 HTTP/2·HTTP/3 gRPC/QUIC 양방향 스트리밍을 결합한 하이브리드 백본을 설계합니다.",
|
||||
points: [
|
||||
"gRPC & QUIC 양방향 스트리밍 메시징",
|
||||
"Protobuf 바이너리 직렬화 최적화",
|
||||
"MQTT-gRPC 하이브리드 엣지 메쉬",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// CUSTOMIZATION HOOK: headline figures (animated counters).
|
||||
// `value: 2026` is marked static so it renders as a fixed year, not a
|
||||
// 0→2026 count-up. The year is also rendered at the smaller `display-sm`
|
||||
// scale (the other two figures use the full `display` scale), so the
|
||||
// 4-digit "2026" does not push the cell padding. See LAYOUT_AUDIT #11 + #13.
|
||||
const figures = [
|
||||
{ value: 2, label: "연구 축 · Research Thrusts", suffix: "", size: "display" as const, static: false },
|
||||
{ value: 4, label: "표준화 기구 · Standards Bodies", suffix: "", size: "display" as const, static: false },
|
||||
{ value: 2026, label: "Issue · 발행", suffix: "", size: "display-sm" as const, static: true },
|
||||
{ value: 5, label: "연구 기둥 · Research Pillars", suffix: "", size: "display-sm" as const, static: false },
|
||||
{ value: 12, label: "에이전트 프로토콜 · Protocols", suffix: "", size: "display-sm" as const, static: false },
|
||||
{ value: 99.9, label: "가동률 % · Availability", suffix: "%", size: "display-sm" as const, static: false },
|
||||
];
|
||||
|
||||
// CUSTOMIZATION HOOK: research keyword ticker.
|
||||
@@ -182,69 +217,56 @@ export default function IntroPage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ============ TWO THRUSTS — SIDE BY SIDE WITH CONNECTING LINE ============ */}
|
||||
{/* ============ FIVE RESEARCH PILLARS ============ */}
|
||||
<section className="border-b border-ink">
|
||||
<div className="container-content py-16 sm:py-24">
|
||||
<Reveal>
|
||||
<SectionLabel index={3} label="Two Research Thrusts" />
|
||||
<SectionLabel index={3} label="Five Research Pillars" />
|
||||
</Reveal>
|
||||
|
||||
<div className="relative mt-12 grid gap-px lg:grid-cols-2">
|
||||
{/* Connecting line + node between the two thrusts (desktop) */}
|
||||
<div
|
||||
aria-hidden
|
||||
className="absolute left-1/2 top-1/2 hidden -translate-x-1/2 -translate-y-1/2 lg:block"
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<span className="h-2 w-2 rounded-full bg-vermillion" />
|
||||
<span className="h-px w-16 bg-ink" />
|
||||
<span className="flex h-9 w-9 items-center justify-center rounded-full border border-ink bg-ivory font-display text-xs">
|
||||
×
|
||||
</span>
|
||||
<span className="h-px w-16 bg-ink" />
|
||||
<span className="h-2 w-2 rounded-full bg-cobalt" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{thrusts.map((t, i) => {
|
||||
const isVerm = t.accent === "vermillion";
|
||||
<div className="mt-12 grid gap-px bg-line sm:grid-cols-2 lg:grid-cols-3">
|
||||
{pillars.map((p, i) => {
|
||||
const isVerm = p.accent === "vermillion";
|
||||
return (
|
||||
<Reveal
|
||||
key={t.tag}
|
||||
variant={i === 0 ? "left" : "right"}
|
||||
delay={i * 120}
|
||||
key={p.tag}
|
||||
variant={i % 2 === 0 ? "left" : "right"}
|
||||
delay={i * 80}
|
||||
className="bg-ivory"
|
||||
>
|
||||
<article
|
||||
className={`group h-full border border-ink p-8 transition-colors duration-500 sm:p-10 ${
|
||||
className={`group flex h-full flex-col justify-between border border-ink p-8 transition-colors duration-500 sm:p-10 ${
|
||||
isVerm
|
||||
? "hover:bg-vermillion hover:text-ivory"
|
||||
: "hover:bg-cobalt hover:text-ivory"
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
<div className="flex items-baseline justify-between">
|
||||
<span className="kicker group-hover:text-ivory/70">{t.no}</span>
|
||||
<span className="kicker group-hover:text-ivory/70">{p.no}</span>
|
||||
<span
|
||||
className={`font-display text-5xl ${
|
||||
className={`font-display text-2xl ${
|
||||
isVerm ? "text-vermillion" : "text-cobalt"
|
||||
} group-hover:text-ivory`}
|
||||
>
|
||||
{t.tag}
|
||||
{p.tag}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="headline-ko mt-6 text-3xl leading-tight">
|
||||
{t.ko}
|
||||
<h3 className="headline-ko mt-6 text-2xl leading-tight">
|
||||
{p.ko}
|
||||
</h3>
|
||||
<p className="font-display mt-1 text-lg italic opacity-70">
|
||||
{t.en}
|
||||
<p className="font-display mt-1 text-base italic opacity-70">
|
||||
{p.en}
|
||||
</p>
|
||||
<p className="mt-5 text-sm leading-relaxed opacity-90">
|
||||
{t.desc}
|
||||
{p.desc}
|
||||
</p>
|
||||
</div>
|
||||
<ul className="mt-6 space-y-3 text-sm">
|
||||
{t.points.map((p) => (
|
||||
<li key={p} className="flex gap-3 border-t border-ink/20 pt-3 group-hover:border-ivory/20">
|
||||
{p.points.map((pt) => (
|
||||
<li key={pt} className="flex gap-3 border-t border-ink/20 pt-3 group-hover:border-ivory/20">
|
||||
<span className="font-display text-xs opacity-60">→</span>
|
||||
<span>{p}</span>
|
||||
<span>{pt}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 디자인 시스템 — "Issue 01"
|
||||
|
||||
> 사물인터넷 표준 연구실 랜딩 페이지의 **정본(canonical) 디자인 레퍼런스**입니다.
|
||||
> AI 에이전트 네트워크 연구실 (ANL) 랜딩 페이지의 **정본(canonical) 디자인 레퍼런스**입니다.
|
||||
> 코드베이스를 다시 읽지 않고도 디자인 시스템을 이해할 수 있도록 작성했습니다.
|
||||
> 토큰의 실제 정의는 `tailwind.config.ts` 와 `app/globals.css`(`:root`)에,
|
||||
> 폰트 로딩은 `app/layout.tsx` 에 있습니다.
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
**연구실 웹사이트를 "한 권의 인쇄 잡지(Issue 01)"로 다룬다.**
|
||||
따뜻한 종이(ivory) 위에 가까운-검정 잉크(ink), 두 개의 편집 강조색
|
||||
(vermillion = MCM, cobalt = QUIC), 큰 세리프 디스플레이 타이포, 그리고 절제된
|
||||
(vermillion = Agent Engineering / Orchestration, cobalt = MCP / A2A Protocol), 큰 세리프 디스플레이 타이포, 그리고 절제된
|
||||
스크롤 등장 모션으로 구성된 **고대비 매거진 스프레드** 시스템입니다. 소수의
|
||||
토큰에서 사이트 전체가 파생되며, 토큰 하나를 바꾸면 전 페이지에 전파됩니다.
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
| **움직임은 절제 (Restrained motion)** | 콘텐츠는 한 번 부드럽게 자리잡고 멈춘다. 튀거나 반복되지 않으며, 단일 이징으로 페이지 전체가 일관된 호흡을 갖는다. |
|
||||
| **콘텐츠 우선 (Content first)** | 모든 편집 데이터는 각 페이지 상단 `// CUSTOMIZATION HOOK` 배열에 모은다. 모션·장식은 정보를 전달하는 수단이지 그 자체가 목적이 아니다. |
|
||||
| **한/영 혼식 (KO/EN bilingual setting)** | 한국어 세리프(Noto Serif KR) 헤드라인과 영어 디스플레이 세리프(Fraunces)를 짝지어, 국문 제목 + 영문 디스플레이 단어의 매거진 바이링구얼 조판을 만든다. |
|
||||
| **의미 있는 색 (Semantic accent pairing)** | 두 강조색은 장식이 아니라 연구 두 축을 인코딩한다 — **vermillion = MCM/메타버스/저널(홀수)**, **cobalt = QUIC/전송/학회(짝수)**. |
|
||||
| **의미 있는 색 (Semantic accent pairing)** | 두 강조색은 장식이 아니라 연구 영역을 인코딩한다 — **vermillion = Agent Eng / Orchestration (홀수)**, **cobalt = MCP / A2A Protocol (짝수)**. |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ import type { Config } from "tailwindcss";
|
||||
* ink → near-black, all primary type & rules
|
||||
* ivory → warm paper background
|
||||
* paper → slightly dimmer paper for cards / insets
|
||||
* vermillion → MCM thrust accent (hot) [Thrust 1]
|
||||
* cobalt → QUIC thrust accent (cool) [Thrust 2]
|
||||
* vermillion → Agent Engineering / Orchestration accent (hot)
|
||||
* cobalt → MCP / A2A Protocol accent (cool)
|
||||
* Swap any hex and the entire editorial system follows.
|
||||
*
|
||||
* CUSTOMIZATION HOOK — FONTS
|
||||
|
||||
Reference in New Issue
Block a user