반갑습니다! FE 개발자 이창우입니다. 포트폴리오 사이트 만들기

창우·2024년 9월 30일
2

ToyProject

목록 보기
5/7
post-thumbnail

개요

FE 개발자 이창우 포트폴리오 사이트
팀 : 1인개발
프론트엔드 : Next, TypeScript
개발기간 : 9월10일 ~ 진행중
깃허브 : https://github.com/changchangwoo/changwoo_portfolio
배포주소 : https://www.changwoo.site/ <도메인 만료, 배포 중단>

  • 9월이 들어서며, 데브코스의 모든 활동이 끝나고 정말 본격적으로 취업준비의 길을 걷게 되었다.
  • 그간 진행했던 크고 작은 프로젝트를 돌아보니 여러 노력을 했구나 새삼 뿌듯한 느낌이 들었다
  • 그러다가, 별 것 아니지만 땀방울이 담긴 소중한 프로젝트를 소개해주는 포트폴리오 사이트가 있었으면 좋겠다는 생각이 들었다.

구현 목표

  • 모바일/태블릿/PC 등 디바이스별 호환 가능한 반응형 컴포넌트 설계
  • 사용자 경험을 고려한 UI/UX 디자인 ( 애니메이션 라이브러리 적용 )
  • 배포 및 커스텀 도메인 적용
  • 3주 이내의 최대한 빠른 개발 시간
  • 유독 신경 썼던 목표는 최대한 빠른 시일 내로 배포를 진행하는 것이다.
  • 당장 구직활동을 하고싶었기에 포트폴리오 페이지는 간략하게 구현하고, 이후 활동을 하며 보완해나가는것을 목표로 하였다.

구현

1. 설계

  • 피그마를 통해 우선적으로 각 컴포넌트의 배치를 설계하였다.
  • 스스로 시간을 한정했기에, 비교적 구현이 간단한 단색 위주로 하여 최대한 깔끔해 보일 수 있도록 구상하였다.
  • 포트폴리오 관련 레퍼런스를 적극 참고하였고, 추후에 전반적으로 UI를 수정하려고한다.

프레임워크는 Next.JS를 선택하였다. SSR을 통해 SEO 이점을 얻을 수 있으며, 현재는 미구현이지만 이후 방명록과 같은 데이터를 처리하는 부분에 있어 백엔드 접근이 간편하고, Vercel 생태계를 활용해 쉽게 배포할 수 있기 때문이었다.

2. Framer Motion을 활용한 애니메이션 구현

  • 컴포넌트 애니메이션은 Framer Motion 라이브러리를 활용해 구현하였다.
  • 옵션인자를 통해 쉽게 애니메이션을 설정할 수 있으며 컴포넌트 단위로 처리하기에 재사용에 있어도 굉장히 유연했다
const FlipUp = ({ children, initialY, delay, className, height, leading } : FlipUpProps) => {
  return (
    <div className={`overflow-hidden ${height} ${leading}`}>
    <motion.h1
      className={className}
      initial={{ y: initialY }}
      animate={{ y: 0 }}
      transition={{ duration: 0.5, ease: "easeOut", delay }}
    >
      {children}
    </motion.h1>
  </div>  )
}
  • 다음과 같이, 각 애니메이션 별로 컴포넌트로서 분리하여 관리를 하니 재사용이 간편하였고 이를 통해 작업시간을 크게 단축시킬 수 있었다.

라이브러리로 Framer Motion을 선택한 이유

  • Framer Motion 진입 장벽이 낮아 단순 애니메이션 구현을 요구하는 현재 상황에 적합하다
  • 또한 컴포넌트 구조이기에 React 기반 프레임워크와의 호환이 좋고 가상 DOM 최적화를 제공한다.

3. TailWindCSS를 통한 반응형 컴포넌트 구현

  • TailWindsCSS에서 제공하는 Responsive Design 속성을 활용하여 반응형 컴포넌트를 구현하였다.
  • lg를 기준으로 PC 레이아웃을 설계하여 lg, md, sm 이렇게 분류로 구분하였다.
  • 보통 해상도에 따라 사이즈나 배치를 변경함으로 전환이 가능하였지만 컴포넌트 형태가 변경되는 경우 기능은 동일하기에 단일 컴포넌트로 설계하여 반응형에따라 속성을 변경할지, 아니면 디바이스별 독립된 컴포넌트를 조건에 따라 출력할지가 고민이 되었다.
  • 이후 개선 작업이 예정되어있고, 각 컴포넌트 별로 분리되어있는 것이 컴포넌트 복잡성을 줄이는 방법이라고 생각하여 후자의 방법을 선택하였다.
  return (
    <AnimatePresence>
      {isNav && (
        <>
          <div className="lg:block hidden">
       // 데스크탑 NavBar 컴포넌트
          </div>
          {/* 데스크탑 */}
          <div className="lg:hidden block">
       // 모바일, 태블릿 NavBar 컴포넌트 
    	</div>
          {/* 모바일, 태블릿 */}
        </>
      )}
    </AnimatePresence>
  );
};

export default NavBar;
  • 다음과 같이 미디어 크기에 따라 요소를 block-hidden 처리 함으로, 디바이스에 해당하는 NavBar를 독립적으로 출력하도록 하였다.
PC모바일

4. 커스텀 도메인 적용 및 Google Analytics 설정

  • 나름 나 자신을 소개하는 사이트여서 정이 갔는지 vercel.app이 아닌 도메인으로 배포를 진행해보고 싶었다.
  • gabia를 통해서 마음에 드는 도메인을 구매하였고 (changwoo.site) vercel 에 가비아 DNS를 연결함으로 적용하였다.
  • 도메인 가격이 정말 천차만별이었다. 나는 돈이 없으니 이벤트중인 저렴한걸로..

https://www.changwoo.site/ 확실히 내 이름이 있는 사이트라 마음에 든다!

  • 방문객 추이를 google을 통해 확인하기 위해 google Analytics 계정을 생성하고, 프로젝트와 연결하였다.
import Script from 'next/script';

export default function GoogleAnalytics({ gaId }: { gaId: string }) {
	return (
		<>
			<Script
				async
				src={`https://www.googletagmanager.com/gtag/js
				?id=${gaId}`} 
			/>
			<Script
				id="google-analytics"
				dangerouslySetInnerHTML={{
						__html: `
		window.dataLayer = window.dataLayer || [];
		function gtag(){dataLayer.push(arguments);}
		gtag('js', new Date());

		gtag('config', '${gaId}');
		`,
				}}
			/>
		</>
	);
}

마치며

  • 추석 연휴와 여러 여행 일정이 겹쳐 결국에는 완성하지는 못했지만, 구현하고자 하는 목표는 어느정도 이룬 것 같다.
  • 당장은 포트폴리오페이지로서 내용은 부족하지만, 구직활동을 진행하면서 피드백들을 적극 수용하고 보완해 나갈 예정이다.
  • 그동안 작성했던 프로젝트를 정리해보면서 여러 생각이 들었다.
  • 취업에 대한 근심과 불안, 잘 하고 있는지에 대한 확신 등 대체로는 착잡했지만
  • 내가 선택하고, 좋아하는 분야에 현업자가 꼭 되고싶다는 욕심도 생겼다
  • 이 프로젝트는 정말 잘 선택한 것 같다.
profile
물을 줘야지😂

2개의 댓글

comment-user-thumbnail
2025년 3월 10일

안녕하세요!! 혹시 포트폴리오 템플릿이 마음에 들어서 그런데, 사용해도 괜찮을까요???

1개의 답글