Demo : https://www.jin-hyeong.com/
github : https://github.com/7jjin/Portfolio
제작 기간 : 2023.12.17 ~ 2024.01.17
기술 스택 : React, TypeSciprt, Styled-component, Recoil
포트폴리오 사이트
내가 프론트엔드를 처음 시작했을 때 이론을 배우고 가장 먼저 클론 코딩을 한 것이 다른 사람의 '포트폴리오 사이트' 였다. 나만의 사이트가 있는 것이 멋있어 보였고, 나도 언젠가는 나를 소개하는 웹 사이트를 만들어 보겠다고 다짐했었다.
마침 취업을 준비하기 위해 포트폴리오가 필요했고, 옛 생각이 나서 만들기로 결심했다. 내가 프로젝트를 시작하면서 의도 했던 것은 아래와 같다.
- 나를 나타나되, 너무 투머치한 내용은 삼가하자.
- 인터렉티브한 웹 페이지를 만들자.
- 코드를 최대한 효율적으로 짜보자.
3가지의 규칙을 항상 생각하면서 기획부터 배포까지 만들었다.
그래서 갑자기 Recoil은 왜 씀?🤔
기술 스택을 보면 recoil을 썻다는 걸 볼 수 있다. 지금까지 redux, redux-toolkit, zustand를 쓰면서 상태관리 라이브러리에 대해 장단점을 비교해보고 가장 쓰기 쉬운 라이브러리를 찾고 있었는데, recoil은 아직 안써봐서 사용해보고 싶었다.
써보면서 가장 좋았던 점은 redux같이 store를 설정하지 않아도 된다는 점, provider로 감싸지 않아서 불필요한 리렌더링이 안일어 난다는 점이다. recoil은 Atom이라는 상태 단위를 통해 업데이트와 구독이 가능하기 때문에 Atom을 구독하고 있는 컴포넌트만 리렌더링이 된다. 또한 useXXX같이 리액트스러운 문법을 사용하고 있어서 문법적으로 이해하기도 쉬웠다.
이외에도 직접적으로 효과를 보진 못했지만 아래와 같은 효과가 있다고 한다.
- 비동기 처리를 추가적인 라이브러리 없이(redux-thunk, redux-saga) recoil안에서 가능하다.
- 내부적으로 캐싱을 지원한다. 동일한 Atom 값에 대한 내부적으로 메모이제이션된 값을 반환하여 속도가 빠르다.
⚒️ 구현 부분
- 인터랙티브한 동작
1. 타이핑 효과 (setTimeout 함수)
텍스트를 넣은 변수와 초기값을 빈 문자열로 갖는 state값을 만들었다. setTimeout 함수가 실행되서 0.1초가 지날 때 마다 텍스트의 길이만큼 state값에 텍스트 글자가 한 글자씩 push된다. 이후 정리함수를 통해 setTimeout 함수를 정 리해준다.
기능을 구현하는데 어려움을 없었다. 하지만 나는 한줄이 아니라 두줄로 쪼개서 만들고 싶어서 아래에 똑같은 setTimeout 함수를 만들고 타이핑 속도에 차이를 두게 하고 싶어 0.17초로 만들었다.
2. 타임라인 기반 애니메이션 효과 (GSAP 라이브러리 사용)
타임라인 기반의 애니메이션이란 하나의 타임라인 안에 여러개의 애니메이션 효과를 줄 수 있는데, 순서를 정할 수 있 다는 장점이 있다. 나는 타이핑 효과가 끝난 후 설명란, 깃허브 아이콘, 티스토리 아이콘, 화살표 아이콘이 순서대로 나 오게 하고 싶었다.
GSAP는 사용하기 쉬웠다. 하나의 타임라인을 만든 후 변수에 할당한다. 할당된 변수에 차례대로 넣어주기만 하면 끝 났다. 첫번째 인자에는 DOM의 클래스이름을 넣으면 되고, 두번째 인자에는 애니메이션 효과를 넣어주면 된다.
// 타이핑 완료 후 로직 (차례대로 깃허브 링크와 티스토리 링크 나타나게)
const tl = gsap.timeline();
tl.to('.subIntro', { duration: 0.7, opacity: 1 })
.to('.github', {
duration: 0.5,
opacity: 1,
top: 0,
})
.to('.tistory', { duration: 0.5, opacity: 1, top: 0 })
.to('.slidebox', { duration: 1, opacity: 1 });
3. 스킬 section
FE, BE, ETC은 모두 checkbox로 만들었다. checkbox의 checked 속성을 이용해서 true면 스택들이 나오는 방식이다.
부모의 checkbox가 true가 되면 해당 스택들이 나오는 동작이며, css의 translate3d 속성을 활용하여 각각의 위치로 움직이도록 만들었다.
그리고 이 섹션이 관측 될 때마다 마지막으로 열렸던 checkbox를 열리게 만들고 싶어서 마지막으로 열린 checkbox를 state값에 저장해 두었다. 이후 Intersection-observer를 통해 해당 섹션이 관측되면 마지막으로 열린 checkbox를 활성화 시켰다.
- Full Page Scroll
Full page scroll이란 한번의 스크롤으로 한 페이지씩 이동하게 하는 효과다. 최근 여러 사이트에서 이 효과를 적용하고 있기 때문에 나도 한번 구현하고 싶었다. 구현 방법은 아래와 같다.
- 마우스 휠에 이벤트를 줘서 스크롤이 위로 향하고 있는지 아래로 향하고 있는 확인한다.
- 스크롤이 내려가면 스크롤의 높이와 window.innerHeight를 비교하며 스크롤 이동을 한다.
- 스크롤이 반대의 경우에도 똑같은 원리로 작동한다.
- 이메일 기능(email.js)
입력 정보에 대한 form 형식은 React-hook-form을 사용해 관리했다. 최소한의 필수 조건만 충족하면 이메일이 보내지도록 만들었다. 따라서 이름은 2글자 이상 이메일은 형식에 맞게 써야 하며, 내용도 2글자 이상 써야 조건이 충족되도록 만들었다. 만약 조건을 충족시키지 않고 다른 입력란을 클릭하면 아래에 경고창이 뜨도록 만들었다. 또한 입력폼이 모두 충족되지 않고 메일을 보내면 모달창이 나와 사용자에게 충족되지 않은 입력란을 포커싱하게 해주고 메일이 전송이 안된다. 모두 충족했을 경우에는 모달창이 나와 사용자에게 메일을 보낸 것을 인지 시켜주고 모든 입력란을 초기화 시키도록 만들었다.
- React Portal
렌더링 과정을 최적화 하기 위해 사용했다. 렌더링 과정에서 부모 컴포넌트가 렌더링 되면 자식 컴포넌트도 같이 렌더링 되는게 당연하다. 하지만 모달 같은 처음에 불필요한 컴포넌트는 렌더링 될 필요가 없다. 또한 부모 컴포넌트의 style에 따라 z-index를 처리해줘야 하는 경우도 있다. React portal은 이러한 점을 해결하기 위해 사용된다.
createportal을 통해 만들 수 있다. 첫번째 인자는 portal할 요소를 넣어주고 두번째 인자는 목적지를 넣어준다. 나는 index.html에 태그를 하나 만들어 그 안에 넣어줬다.
확실히 z-index를 생각할 필요가 없었다. 렌더링에서는 큰 차이를 느끼지 못했지만 나중에 모달을 사용한다면 React portal을 꼭 한번 고려해 봐야겠다고 생각했다.
'프로젝트' 카테고리의 다른 글
C#, WPF로 개인 프로젝트 만들어 보기(1) (0) | 2024.07.04 |
---|---|
[리팩토링] 둥지 프로젝트 (0) | 2024.02.23 |
[리팩토링] - JinCha 프로젝트 뜯어 고치기 (2) | 2024.01.28 |
[포스코x코딩온] 웹개발자 풀스택 과정 4차 팀프로젝트 - 자취방 리뷰 페이지(1) (1) | 2023.12.12 |
[포스코x코딩온] 웹개발자 풀스택 과정 4차 팀프로젝트 - 핫딜 페이지(2) (0) | 2023.12.12 |