Skip to content

Repository files navigation

지식재산 기반 무역안보 연구실 (IP Trade Security Lab)

신한대학교 경영대학 글로벌무역학과 · 연구실 홈페이지

  • Next.js 16 (App Router, Turbopack) / React 19 / TypeScript
  • Tailwind CSS v4
  • 한국어 · 영어 전환 (클라이언트 Context 기반)
npm install
npm run dev        # 개발 서버 http://localhost:3000
npm run build      # 정적 사이트를 out/ 에 생성
npm run deploy     # GitHub Pages(gh-pages 브랜치)로 배포

정적 내보내기(output: "export") 구성이라 npm run start(= next start)는 쓰지 않습니다. 빌드 결과를 미리 보려면 npx serve out 처럼 정적 서버로 열면 됩니다.


콘텐츠 수정하기 — content/

화면에 보이는 글자는 전부 content/ 안에만 있습니다. 컴포넌트를 열 필요 없이 이 파일들만 고치면 됩니다.

파일 내용
content/site.ts 연구실 이름·주소·이메일, 네비게이션 메뉴, 구성원 하위 페이지, 공통 문구
※ 메뉴명과 페이지 제목(label)은 한/영 구분 없이 항상 영어라 그냥 문자열입니다
content/research.ts 연구 분야 5개 (홈 화면 카드 + 논문 태그에 함께 사용)
content/projects.ts 연구 사업 목록 (Projects 페이지)
content/publications.ts 논문 · 국제학술발표 목록 (Publications 페이지)
content/people.ts 교수 프로필
content/students.json 학생 명단 (대학원생 · 학부연구생)
content/alumni.json 졸업생 명단
content/contact.ts 모집 안내, 지도 임베드 주소

한/영 텍스트 규칙

모든 텍스트는 { ko: "한국어", en: "English" } 형태(Localized 타입)로 저장합니다.

title: { ko: "무역안보", en: "Trade Security" }

화면에서는 useT() 훅이 현재 언어에 맞는 값을 꺼내 줍니다. 문자열 배열도 동일합니다.

const t = useT();
<h2>{t(area.title)}</h2>
{t(area.keywords).map(...)}

선택한 언어는 localStorage(ips-lang)에 저장되고, 저장값이 없으면 브라우저 언어를 따릅니다.

자주 하는 작업

  • 논문 추가content/publications.tsjournalPublications 맨 앞에 추가. areascontent/research.tsid 를 참조하므로 태그가 자동으로 붙습니다.
  • 메뉴 추가content/site.tsnavigation 배열만 수정하면 데스크톱 메뉴와 모바일 드로어에 한 번에 반영됩니다.

구성원 추가 — students.json / alumni.json

두 파일 모두 배열에 객체를 추가하면 카드가 한 장 늘어납니다. 배열이 비어 있으면 안내 문구가 대신 표시됩니다. (졸업생 문구는 content/people.tsalumniEmpty, 그 밖에는 content/site.tsui.preparing)

학생 (content/students.json)

필드 설명
name 이름
group "graduate"(대학원생) 또는 "undergraduate"(학부연구생). 이 값에 따라 소제목 아래로 묶입니다
degree 학위 — 석사과정 / 박사과정 / 학부연구생 …
major 전공 · 소속
interests 관심 키워드 배열
photo public/images/members/ 안의 파일명. null 이면 이름 첫 글자가 표시됨
links { "type": "github", "url": "..." } 배열. 없으면 []. typelinkedin · github · homepage · email 중 하나이며 아이콘으로 표시됩니다 (emailmailto: 가 자동으로 붙습니다)

졸업생 (content/alumni.json)

필드 설명
name 이름
degree 학위 — 석사 / 박사 …
year 졸업 · 수료 연도
major 전공 · 소속 학교
current 현 소속 (직장 · 학교)
links 학생과 동일

name, degree, major, interests, current 는 모두 { "ko": "...", "en": "..." } 형태로 적습니다. year, photo, links 는 언어와 무관하므로 그냥 문자열입니다.


히어로 배경 — 세계지도

components/home/HeroMap.tsx2D 캔버스만 사용하며 추가 라이브러리가 없습니다.

무역'안보'를 표현하기 위해 세 겹으로 구성되어 있습니다.

  1. 대륙 실루엣 — 실제 해안선을 채워 그립니다 (content/world-land.json)
  2. 교역로 — 경기도(연구실 소재지)와 주요 항만을 잇는 점선. 수출은 금색, 수입은 네이비로 흐름 방향이 반대입니다
  3. 위협과 방어 — 바깥에서 붉은 궤적이 직선으로 날아와 대한민국 테두리에 부딪혀 튕겨 나갑니다. 부딪히는 면의 법선을 기준으로 실제 반사각을 계산하므로 방향마다 튕기는 각도가 다릅니다

위협은 특정 국가나 항만을 지목하지 않도록 실제 지점이 아닌 방위각으로만 정의합니다.

무엇을 바꾸려면 어디를
교역 거점 추가·삭제 content/globe.tshubsflow: "in" | "out" 로 방향 지정
기준점 위치 content/globe.tsorigin
국토 윤곽 (튕기는 기준선) content/globe.tskoreaOutline
위협 방향·개수 HeroMap.tsxTHREATS — 들어오는 방위각만 지정, 반사각은 자동 계산
위협 속도 HeroMap.tsxTHREAT_CYCLE
국토 화면상 위치 HeroMap.tsxFOCUSNARROW 분기 (좁은 화면은 위쪽·오른쪽으로)
바꿀 필요 없음 — globals.css 팔레트를 읽어 씁니다 (--color-alert-500 이 위협색)
해안선 정밀도 scripts/build-world-land.mjsMIN_AREAnpm run world:land

해안선(링 78개)은 world-atlas 지도 데이터에서 미리 뽑아 content/world-land.json(42KB)에 저장해 둡니다. 생성 스크립트만 devDependency 를 쓰고, 실행 시점에는 이 JSON 만 필요합니다.

  • prefers-reduced-motion 이면 움직임을 멈추고, 화면 밖으로 스크롤되면 렌더링을 쉽니다.

디자인 · 스타일

색상 · 폰트 · 컨테이너 폭 등 모든 디자인 토큰은 app/globals.css@theme 블록 한 곳에만 있습니다. 컴포넌트에서는 하드코딩된 hex 대신 text-navy-800, bg-surface, text-muted, border-line 같은 유틸리티를 사용합니다.

  • 본문 서체: Pretendard (app/fonts/PretendardVariable.woff2)
  • 제목 · 영문 라벨 서체: Plus Jakarta Sansfont-display 클래스로 적용

폴더 구조

app/                     라우트 (page.tsx 는 데이터 조립만 담당)
  members/layout.tsx     구성원 3개 페이지 공통 상단(타이틀 + 탭)
components/
  layout/                Header, Footer, PageHero, Section
  ui/                    Container, SectionHeading, Tag, Reveal, LangToggle, EmptyState
  home/                  홈 전용 섹션 (HeroMap 등)
  people/                교수 프로필, 구성원 카드 목록
  research/              Projects · Publications 페이지 (ProjectList 는 홈과 공유)
  contact/               Contact 페이지 본문
content/                 모든 텍스트 데이터 (한/영) + world-land.json
scripts/                 지도 데이터 생성 (npm run world:land)
lib/i18n.tsx             언어 Context + useT() 훅
public/images/           이미지

사진 파일과 배포

public/images/ 안의 이미지는 .gitignore 로 저장소에서 제외되어 있습니다 (개인정보). 폴더 구조는 .gitkeep 으로만 유지되고, 실제 사진은 로컬에만 있습니다.

사진이 없어도 사이트는 정상 동작합니다 — photo: null 이면 이름 첫 글자 플레이스홀더가 표시됩니다.

GitHub Pages 배포

이 저장소를 GitHub 에 올리고, 로컬에서 빌드한 결과물만 gh-pages 브랜치로 보냅니다. main 에는 소스만 남고 사진과 빌드 결과물은 커밋되지 않습니다.

git remote add origin https://github.com/<계정>/<저장소>.git   # 처음 한 번만
npm run deploy

npm run deploy 가 알아서 하는 일:

  1. origin 주소에서 저장소 이름을 읽어 basePath 를 자동으로 정합니다
  2. 그 basePath 로 next build 실행 → out/
  3. out/gh-pages 브랜치로 강제 push

처음 한 번은 저장소 Settings → Pages 에서 이렇게 지정해 주세요.

항목
Source Deploy from a branch
Branch gh-pages / (root)

basePath 를 자동으로 넣는 이유

https://<계정>.github.io/<저장소>/ 처럼 하위 경로로 열리면 모든 자산 경로 앞에 저장소 이름이 붙어야 합니다. 안 붙이면 CSS·JS·사진이 전부 404 가 됩니다. 저장소 이름이 <계정>.github.io 이거나 커스텀 도메인이면 basePath 없이 빌드합니다. 직접 지정하려면 NEXT_PUBLIC_BASE_PATH=/저장소이름 npm run build 로도 됩니다.

next/imageimages.unoptimized: true 일 때 src 를 그대로 내보내 basePath 가 붙지 않으므로, 이미지 경로는 lib/asset.tsasset() 을 거쳐 씁니다.

알아두실 점

  • public/.nojekyll 파일은 지우면 안 됩니다. GitHub Pages 는 기본으로 Jekyll 을 돌리는데, Jekyll 은 _ 로 시작하는 폴더를 무시합니다. Next.js 결과물은 _next/ 라서 이 파일이 없으면 사이트가 통째로 깨집니다.
  • gh-pages 브랜치에는 사진이 들어갑니다. GitHub Pages 는 파일이 저장소 안에 있어야 서비스할 수 있어서 피할 수 없습니다. 무료 계정은 public 저장소에서만 Pages 를 쓸 수 있으니, 사진이 공개되면 안 되는 상황이면 Pages 대신 업로드형 호스팅(Netlify CLI 등)을 쓰는 편이 맞습니다.
  • 이미지 파일은 환경변수(.env)에 넣을 수 없습니다. 환경변수는 문자열만 담습니다. 사진을 소스에서 빼는 방법은 .gitignore + 위의 배포 방식 조합입니다.
  • 정적 내보내기에서는 next/image 서버 최적화가 동작하지 않아 원본이 그대로 나갑니다. public/images/ 에 넣기 전에 가로 1000px 내외로 줄여 주세요. (교수님 사진은 4.4MB → 60KB 로 줄여 둔 상태이고, 원본은 IPS/material/ 에 있습니다.)
  • 빌드 결과를 로컬에서 미리 보려면 npx serve out 로 열면 됩니다. 단 basePath 를 넣어 빌드한 결과물은 하위 경로에서만 정상 동작합니다.

남은 작업 (콘텐츠 확인 필요)

  • 졸업생·대학원생 명단 — 아직 없어 안내 문구만 표시됨. 생기면 alumni.json · students.json 에 추가
  • 신규 연구사업 3건(개인정보보호위원회 / 홍익대 / 한국전자기술연구원)의 진행 기간content/projects.ts 상단 TODO
  • 연구실 상세 호실 번호
  • 연구실 대표 전화번호 — content/site.tstel 이 현재 (031) 000-0000 임시값
  • 영문 성함 확인 — Jongseong Kim(교수), Heeseo Kim(김희서), Seoyoung Song(송서영) 은 추정 표기

Releases

Packages

Contributors

Languages