👉 해당 레포지토리는 서버 레포지토리입니다. 클라이언트 레포지토리를 확인하고 싶으시다면 바로가기
- 개발 기간: 2024.12 ~ 2025.01
- 개발자: 전진우 (프론트엔드 개발자)
- 배포 주소: https://jinu-sportfolioconsole.web.app
이 프로젝트는 닌텐도 스위치 콘솔을 모티브로 한 개인 포트폴리오 웹사이트입니다. 사용자에게 게임 콘솔과 유사한 인터랙티브한 경험을 제공하면서 개발자의 프로젝트와 기술 스택을 소개합니다. 특히 부트업 화면부터 프로젝트 상세 정보까지 게임 콘솔의 사용자 경험을 웹에서 구현하는 데 중점을 두었습니다.
- 사용자 경험을 위한 애니메이션 부트업 화면 구현
- 반응형/데스크톱 환경에 따른 다른 부트업 로직
- 프로그레스 바를 통한 로딩 상태 표시
- 프로젝트 간 직관적인 네비게이션
- 프로젝트 썸네일 및 상세 정보 표시
- 애니메이션 효과로 부드러운 전환
- 각 프로젝트의 상세 정보 제공
- 기술 스택, 주요 기능, 개발 과정 설명
- 비디오 및 이미지 갤러리 통합
- 연결 리스트 자료구조를 활용한 댓글 관리
- 프로젝트별 독립적인 댓글 시스템
- CRUD 기능 구현
// serverPortfolio/src/comments.ts - 연결 리스트를 활용한 댓글 관리 시스템
// 각 프로젝트별로 독립적인 댓글 리스트를 관리합니다
class CommentLinkedList {
projectLists: { [projectId: string]: Node | null } = {};
projectCounts: { [projectId: string]: number } = {};
constructor() {
this.projectLists = {};
this.projectCounts = {};
}
insertAt(projectId: string, index: number, data: IComment) {
if (!this.projectLists[projectId]) {
this.projectLists[projectId] = null;
this.projectCounts[projectId] = 0;
}
// ... 연결 리스트 삽입 로직
}
// 기타 연결 리스트 메서드들
}- 재귀 함수를 활용한 댓글 목록 렌더링
// Portfolio/src/components/comments/CommentsList.tsx
const renderComments = (
current: INode | null,
depth: number = 0,
isLastNode: boolean = true
): ReactNode => {
// 로딩 상태 처리
if (!current || isProjectLoading) {
// 로딩 상태 및 빈 댓글 처리 로직
// ...
}
if (!current) {
return (
<NoComments>
{CommentIcons.noComments()}
<p>
No Comments...{" "}
<span onClick={() => setIsModalOpen(true)}>Write One?</span>
</p>
</NoComments>
);
}
// 현재 댓글 노드 렌더링
const result = (
<AnimatePresence>
<CommentItem
key={current.data.id}
id={`comment-${current.data.id}`}
variants={CommentItemVariants}
custom={depth}
>
{/* 댓글 헤더 및 내용 UI */}
{/* ... */}
<CommentInfo>{current.data.content}</CommentInfo>
</CommentItem>
{/* 재귀적으로 다음 댓글 노드 렌더링 */}
{current.next && renderComments(current.next, depth + 1, false)}
</AnimatePresence>
);
// 마지막 노드 처리
if (!current.next && isLastNode) {
setIsProjectLoading(false);
}
return result;
};- 모바일, 태블릿, 데스크톱 환경 지원
- 디바이스별 최적화된 UI/UX 제공
- 화면 크기에 따른 동적 레이아웃 조정
- 페이지 전환 시 부드러운 애니메이션 효과 제공
// Portfolio/src/components/AnimatedOutlet.tsx
const AnimatedOutlet = (): React.JSX.Element => {
const location = useLocation();
const element = useOutlet();
const error = useRouteError();
return (
<AnimatePresence mode="wait">
{isRouteErrorResponse(error) ? (
<NotFound key="error" />
) : (
element && React.cloneElement(element, { key: location.pathname })
)}
</AnimatePresence>
);
};Portfolio/
├── public/ # 정적 파일 (이미지, 비디오, SVG 등)
│ ├── images/ # 프로젝트 이미지
│ ├── media/ # 비디오 파일
│ ├── svgs/ # SVG 아이콘
│ └── logo/ # 로고 파일
├── src/
│ ├── components/ # 재사용 가능한 컴포넌트
│ ├── routes/ # 페이지 컴포넌트
│ ├── stores/ # Zustand 상태 관리
│ ├── styles/ # 전역 스타일 및 테마
│ ├── App.tsx # 메인 앱 컴포넌트
│ ├── Router.tsx # 라우터 설정
│ ├── Icons.tsx # SVG 아이콘 컴포넌트
│ ├── api.ts # API 호출 함수
│ └── index.tsx # 앱 진입점
└── package.json
ServerPortfolio/ # 백엔드 서버
├── src/
│ ├── comments.ts # 댓글 관리 로직
│ └── server.ts # Express 서버
└── package.json| 폴더 | 설명 |
|---|---|
public/ |
정적 리소스 파일들이 저장된 폴더 |
src/components/ |
재사용 가능한 UI 컴포넌트 (부트업 화면, 레이아웃, 모달 등) |
src/routes/ |
페이지 단위 컴포넌트 (메인, 프로필, 댓글 등) |
src/stores/ |
Zustand를 사용한 상태 관리 로직 |
src/styles/ |
전역 스타일 및 테마 설정 |
ServerPortfolio/ |
방명록 기능을 위한 Express 백엔드 서버 |
저장소 클론
git clone https://github.com/GiToon10100011/Portfolio.git디렉토리 이동
cd Portfolio의존성 설치
npm install개발 서버 실행
npm run dev빌드
npm run build배포
npm run deploy디렉토리 이동
cd ServerPortfolio의존성 설치
npm install개발 서버 실행
npm run dev- 연결 리스트 자료구조 활용: 방명록 시스템에 연결 리스트를 구현하여 효율적인 데이터 관리 방법을 학습했습니다.
- 재귀적 렌더링 패턴: 트리 구조의 데이터를 효율적으로 렌더링하는 재귀 함수
- 애니메이션 최적화: Framer Motion을 활용한 복잡한 애니메이션 구현과 성능 최적화 기법을 익혔습니다.
- 상태 관리: Zustand를 사용하여 전역 상태를 효율적으로 관리하는 방법을 배웠습니다.
- 콘솔 UI/UX 구현: 게임 콘솔의 사용자 경험을 웹에서 구현하는 방법을 연구했습니다.
- 반응형 디자인: 다양한 디바이스에서 일관된 사용자 경험을 제공하기 위한 반응형 디자인 기법을 적용했습니다.
- 모듈화 및 컴포넌트 설계: 재사용 가능한 컴포넌트 설계와 모듈화를 통해 코드 유지보수성을 향상시켰습니다.
- 프론트엔드와 백엔드 통합: 클라이언트와 서버 간의 효율적인 통신 방법을 구현했습니다.
- 배포 자동화: Firebase와 AWS를 통한 배포 자동화 프로세스를 구축했습니다.