서울대학교 전기·정보공학부 Machine Perception and Reasoning Lab(SNUMPR) 홈페이지입니다.
Next.js(React) 기반으로 만들어져 있고, 대부분의 콘텐츠는 /public/data/ 안의 JSON 파일로 관리됩니다. 따라서 일상적인 업데이트(팀원 추가, 논문 추가, 사진 업로드 등)는 코드를 거의 건드리지 않고도 가능합니다.
이 문서를 읽는 분께 React/Next.js는 처음이어도 문제없이 운영하실 수 있도록 작성했습니다. 코드 수정이 필요한 작업은 대부분 Claude Code (Opus 모델 권장)에 한 줄짜리 프롬프트만 던지면 됩니다. 본 README의 §4에 예시 프롬프트가 정리되어 있습니다.
# 1) 처음 한 번만
npm install
# 2) 매번 작업할 때
npm run dev브라우저에서 http://localhost:3000 으로 접속하시면, 파일을 저장하는 즉시 변경사항이 반영된 화면을 확인할 수 있습니다.
main 브랜치에 push하면 Vercel이 자동으로 https://snumpr.vercel.app 에 배포합니다 (1~2분 소요).
- GitHub의 commit 메시지 옆에 초록 체크 = 배포 성공
- 빨간 X = 빌드 실패 (코드에 에러가 있거나 JSON 문법이 깨졌거나 등)
- 배포가 실패하면 우선
npm run dev를 로컬에서 돌려보고, 터미널에 뜨는 에러 메시지를 그대로 Claude Code에 붙여넣어 "이 에러 고쳐줘"라고 하시면 보통 해결됩니다.
snumpr/
├── public/
│ ├── data/ ← 모든 콘텐츠 JSON (팀, 논문, 갤러리 등)
│ │ ├── people.json
│ │ ├── publications.json
│ │ ├── highlights.json
│ │ ├── news.json
│ │ ├── gallery.json
│ │ └── links.json ← GitHub / HuggingFace / SNS / Google Form 링크
│ ├── images/ ← 모든 이미지 (people, publications, gallery 등)
│ ├── icons/ ← 페이지별 SVG 아이콘
│ ├── research-pdfs/ ← 논문 PDF 파일
│ └── logo.svg
│
├── src/
│ ├── app/ ← 페이지 (Next.js App Router)
│ │ ├── layout.tsx ← 폰트/메타데이터/네비/푸터 등 공통 레이아웃
│ │ ├── globals.css ← 전역 스타일 + --nav-height, --font-main 등
│ │ ├── theme.css ← 색상 변수 (이 파일만 바꿔도 사이트 전체 색이 바뀜)
│ │ ├── page.tsx ← Home 페이지
│ │ ├── page.module.css ← Home 페이지 스타일
│ │ ├── team/ ← /team
│ │ ├── publications/ ← /publications
│ │ ├── highlights/ ← /highlights
│ │ ├── gallery/ ← /gallery
│ │ └── join-us/ ← /join-us
│ ├── components/ ← 재사용 컴포넌트
│ │ ├── Navbar.tsx ← 상단 네비게이션
│ │ ├── Footer.tsx ← 하단 푸터
│ │ ├── Title.tsx ← 페이지 제목
│ │ ├── FadeIn.tsx ← 스크롤 페이드 인 애니메이션
│ │ └── Icons.tsx ← 인라인 SVG 아이콘들
│ ├── types/index.ts ← TypeScript 타입(데이터 schema의 정답지)
│ └── utils/ ← 유틸 함수
│
├── README.md ← 이 문서
└── CLAUDE.md ← Claude Code가 이 repo에서 일할 때 보는 규칙
- 페이지 하나 =
src/app/<route>/page.tsx하나. 폴더 이름이 곧 URL이 됩니다. - 콘텐츠 데이터는 전부
/public/data/*.json. 텍스트/사진을 바꾸려면 JSON만 수정. - 색·폰트는
src/app/theme.css와src/app/globals.css의 CSS 변수로 관리. - 이미지는
/public/images/<용도>/에 두고, 코드/JSON에서는/images/...경로로 참조.
모든 콘텐츠는 /public/data/ 아래의 JSON 파일로 관리됩니다. JSON 문법만 지켜 주시면 됩니다.
JSON 공통 주의사항
- 따옴표는 반드시 직선 큰따옴표(
"). 한글 문서에서 자동으로 들어가는 둥근 따옴표(",")는 에러를 냅니다.- 마지막 항목 뒤에 콤마(
,)를 붙이지 마세요.- 저장 후
npm run dev가 돌고 있다면 즉시 화면이 갱신됩니다. 화면이 깨지면 터미널에 빨간 에러가 떠 있을 가능성이 높습니다.
5개 섹션으로 구성됩니다(배열 순서 = 화면에 보이는 순서):
faculty_and_researchersgraduate_studentsundergraduate_internsrobotsadministrative_staff
한 명당 entry 형식:
{
"name": "Jonghyun Choi",
"position": "Associate Professor",
"image": "/images/people/jonghyunchoi.jpg",
"website": "https://ppolon.github.io",
"email": "jonghyunchoi@snu.ac.kr",
"github": "http://github.com/jchoivision"
}- 비워둘 필드는
""(빈 문자열)로 두면 됩니다. - 사진은
public/images/people/에 jpg/png/webp로 저장하고, 위와 같은 경로로 참조.
{
"title": "Modular Memory is the Key to Continual Learning Agents",
"authors": ["Vaggelis Dorovatas", "Jonghyun Choi", "..."],
"journalsInfo": "arXiv 2603",
"thumbnailUrl": "/images/publications/arxiv2603-memory.jpg",
"links": [
{ "label": "PDF", "url": "https://arxiv.org/pdf/2603.01761" },
{ "label": "Code", "url": "https://github.com/..." }
],
"researchTopic": ["AI"],
"year": "2026",
"publicationType": ["Conference"],
"recognized": "ORAL"
}| 필드 | 설명 |
|---|---|
journalsInfo |
"CVPR 2026", "arXiv 2603" 같은 자유 문자열 |
links[].label |
PDF / Code / Data / Page / Supp / Media / Slides 권장 (theme.css에 색이 매핑되어 있습니다) |
researchTopic |
배열. 예: ["AI"], ["Vision"] |
year |
"2026", "2025", "Preprint" 등 |
publicationType |
["Conference"] 또는 ["Journal"] 등 |
recognized |
""(없음) 또는 "ORAL", "Best Paper" 같은 강조 라벨 |
논문 PDF를 사이트에 직접 호스팅하려면 public/research-pdfs/에 파일을 넣고 links에서 "/research-pdfs/<파일명>.pdf"로 참조하시면 됩니다.
{
"id": "g4",
"title": "2026 Spring Picnic",
"description": "Lab spring picnic at Seoul Forest",
"category": "Social Events",
"color": "green",
"date": "April 12, 2026",
"location": "Seoul, Korea",
"images": ["/images/gallery/picnic-1.jpg", "/images/gallery/picnic-2.jpg"]
}id: 다른 항목과 겹치지 않게 (g4,g5, ...).category: 자유 문자열. 기존에 사용 중인 값:"Conference","Lab Events","Social Events".color: 카테고리 배지 색. 다음 8개 중 하나 —red | orange | yellow | green | teal | blue | purple | pink.images: 한 장이어도 배열로. 두 장 이상이면 카드 안에서 슬라이드로 표시됩니다.
- 사진을
public/images/gallery/폴더에 저장합니다. 파일명은 영문/숫자/하이픈만 사용해 주세요(예:emnlp2025-1.jpg). 한글·공백·괄호는 사용하지 마세요. - 사진 한 장당 약 1MB 이하로 압축해 주세요(너무 큰 사진은 사이트가 느려집니다).
public/data/gallery.json파일을 열고, 배열 맨 끝에 위 형식의 객체를 하나 추가합니다.images배열에 위에서 저장한 파일들의 경로를/images/gallery/<파일명>형식으로 적습니다.- 저장한 뒤
npm run dev로 띄워 본인이 추가한 항목이 잘 나오는지 확인 → 이상 없으면 commit & push.
둘 다 같은 구조입니다.
{
"id": "1",
"title": "Four Papers at CVPR 2026",
"details": "Four papers from our lab will be presented at CVPR 2026 in Nashville.",
"imageUrl": "/images/news/news1.jpg"
}- News: Home 상단 캐러셀(자동 슬라이드).
- Highlights: Home에 4개 미리보기로 보이고,
/highlights페이지에서 전체가 보입니다. - 이미지는 각각
public/images/news/,public/images/highlights/아래에 저장.
{
"github": "https://github.com/snumprlab",
"huggingface": "https://huggingface.co/SNUMPR",
"sns": {
"x": "/",
"bluesky": "/",
"instagram": "/",
"linkedin": "/",
"facebook": "/"
},
"googleForm": "#"
}github,huggingface: 우상단 네비 아이콘.sns: 푸터의 SNS 아이콘들. 사용하지 않는 항목은"/"또는""로 두면 됩니다.googleForm: Join Us 페이지의 신청 폼 링크.
이 파일 한 군데만 바꿔도 사이트 전체 색이 즉시 반영됩니다.
| 변수 | 의미 / 영향 범위 |
|---|---|
--color-primary |
브랜드 메인 색 (링크, 활성 메뉴, 강조 텍스트) |
--color-primary-accent |
메인 색의 살짝 밝은 버전 |
--color-text / --color-text-muted / --color-text-faint |
본문 / 보조 / 캡션 텍스트 |
--color-bg-soft / --color-bg-card / --color-bg-list |
페이지 배경 / 카드 / 리스트 톤 |
--color-divider / --color-border-soft / --color-border-faint |
구분선·테두리 |
--color-swatch-{red,orange,yellow,green,teal,blue,purple,pink} |
8가지 파스텔 — 갤러리 배지/논문 태그가 공유 |
--color-tag-pdf / code / data / page / supp / media / slides |
Publications 링크 라벨별 배경색 (위 swatch를 참조) |
--color-highlight |
"ORAL", "Best Paper" 같은 강조 빨강 |
--color-scrollbar-* |
스크롤바 색 |
예) 메인 색을 보라색 계열로 바꾸려면 theme.css에서 한 줄만 수정하면 됩니다:
--color-primary: #5b3df0;폰트 변수는 globals.css에 있습니다:
--font-main: var(--font-figtree), sans-serif;
--font-secondary: var(--font-figtree), sans-serif;폰트 자체는 layout.tsx에서 next/font/google을 통해 등록합니다(현재 Figtree 사용 중).
- Google Fonts에 있는 폰트로 바꾸기 (예: Inter):
layout.tsx에서Inter를 import해--font-inter변수로 노출하고,globals.css의--font-main을var(--font-inter)로 바꿉니다. - Google Fonts에 없는 폰트 (예: Pretendard): variable woff2 파일을
src/fonts/에 넣고next/font/local로 등록한 뒤, 같은 방식으로 변수로 매핑합니다.
직접 하기 번거로우면 §4-3의 프롬프트 예시처럼 Claude Code에 맡기시는 게 가장 편합니다.
--nav-height(globals.css): 상단 네비게이션 높이.
이 사이트는 Claude Code(Opus 권장) 와 함께 작업하도록 설계되어 있습니다. 프로젝트 루트에 있는 CLAUDE.md에 폴더 구조와 컨벤션이 정리되어 있어, Claude가 알아서 적절한 파일을 찾아 수정합니다. 별도의 정교한 프롬프트는 거의 필요 없습니다.
프롬프트 예시
"
/research라우트로 새 페이지를 만들어줘. Team 페이지(src/app/team)와 비슷한 구조로page.tsx+page.module.css. Navbar에도 'Research' 링크를 Publications 다음에 추가해주고, 우선 placeholder 섹션 3개(Topic 1/2/3)로 채워줘."
페이지를 만든 뒤 콘텐츠를 JSON으로 분리하고 싶다면:
"방금 만든 research 페이지의 콘텐츠를
public/data/research.json으로 분리하고, page.tsx에서 그 JSON을 읽어 렌더링하도록 바꿔줘. 타입은src/types/index.ts에 추가해."
프롬프트 예시
"Home 페이지(
src/app/page.tsx)의 Highlights 아래에 새 섹션 'Sponsors'를 추가해줘. 데이터는public/data/sponsors.json에서 읽고({ id, name, logoUrl, link }배열), 로고들이 가로로 나열되는 형태야. 스타일은page.module.css에 추가해주고, 색은theme.css변수를 사용해 줘."
캐러셀처럼 동작하게 하고 싶으면 "News 캐러셀과 똑같은 방식으로 동작하게"라는 한 줄을 덧붙이세요.
그대로 던져도 잘 동작하는 수준의 짧은 프롬프트들:
- "Team 페이지의 인물 카드 사이 간격을 좀 좁혀줘"
- "메인 색을 좀 더 차분한 남색으로 바꿔줘 (theme.css의
--color-primary)" - "Publications 페이지의 thumbnail 크기를 약 20% 키워줘"
- "Home의 Highlights 카드 모서리를 더 둥글게 해줘"
- "전체 폰트를 Inter로 바꿔줘. layout.tsx에서 등록하고 globals.css의 변수도 같이 수정해줘"
팁: 어느 페이지의 어느 요소인지 한 줄로만 명시해 주시면 보통 한 번에 끝납니다.
npm run dev로 시각적으로 확인.- 다른 페이지에 영향이 갔을지 의심되면 Claude에게 "방금 변경이 다른 페이지에 영향 없는지 확인해줘"라고 추가 요청.
- 만족스러우면 commit → push → Vercel 빌드 초록 체크 확인.
| 증상 | 보통 원인과 대처 |
|---|---|
npm run dev에서 에러 |
JSON 문법(콤마/따옴표) 또는 import 경로 실수가 대부분. 터미널 메시지를 그대로 Claude에 붙여넣고 "이 에러 고쳐줘"라고 하시면 됩니다. |
| 이미지가 안 뜸 | 경로가 /images/...로 시작하는지 확인(루트는 public/이지만 코드에서는 /로 시작). 파일명 대소문자/공백도 확인. |
| Vercel 배포 실패 | Vercel 대시보드 또는 GitHub PR의 빌드 로그 확인. 안 풀리면 Slack으로 연락. |
| 글꼴이 갑자기 굴림체 | layout.tsx의 폰트 import가 깨졌을 가능성. 최근 변경 commit을 보고 되돌리세요. |
npm run dev # 로컬 개발 서버
npm run build # 프로덕션 빌드 (배포 전 점검용)
npm run start # 빌드 결과 로컬에서 서비스
npm run lint # ESLint 검사
npm run format # Prettier + ESLint 자동 정리내부 연구실 사이트입니다. 외부에서 일부 코드를 참고/사용하실 경우 사전에 문의 바랍니다.