Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/soozynn/soozynn.dev
My Frontend Portfolio ✌️
https://github.com/soozynn/soozynn.dev
nextjs14 tailwindcss typescript vercel
Last synced: 11 days ago
JSON representation
My Frontend Portfolio ✌️
- Host: GitHub
- URL: https://github.com/soozynn/soozynn.dev
- Owner: soozynn
- Created: 2024-03-14T06:54:08.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2024-04-23T04:49:27.000Z (7 months ago)
- Last Synced: 2024-04-23T07:28:52.852Z (7 months ago)
- Topics: nextjs14, tailwindcss, typescript, vercel
- Language: TypeScript
- Homepage: https://soozynn.vercel.app
- Size: 473 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
https://soozynn.vercel.app
# soozynn.dev
next14 + tailwind + vercel을 이용한 개인 포트폴리오입니다.
해당 프로젝트는 next14의 이점 및 문법을 알아가기 위함입니다.
## 프로젝트를 개발하며..
개발 과정에서 마주치는 다양한 문제들은 누구나 경험하는 보편적인 과정일 것입니다. 이러한 문제들을 정리해두면, 단순히 기억에 오래 남는 것을 넘어서 나중에 이를 다시 읽었을 때 "당시에는 이런 어려움에 직면했었구나"하고 돌아볼 수 있는 소중한 기록이 됩니다. 따라서, 개인 블로그 프로젝트에 사소해 보일 수 있는 고민거리조차도 세심하게 적어나가려 합니다. 이 과정을 통해 자신만의 경험을 체계적으로 정리하고, 나아가 이러한 기록이 미래의 저또는 누군가에게 도움이 될 수 있을 거 같아 정리해봅니다.
잦은 애니메이션 업데이트: requestAnimationFrame API 사용
> setInterval 타이머 지연 및 블로킹 현상 및 타이머 드리프트
- 처음에는 현지 시간이 업데이트 되는 로직을 setInterval과 setTimeout을 사용하여 자바스크립트로 개발하였다. setInterval은 타이머 드리프트 현상이 생각보다 꽤 길게 나타났고, setTimeout은 그보다는 빨랐지만, 시간이 업데이트 될 때에 맞추어 실시간으로 동작하지 않는 문제가 있었다.
또한, setInterval 같은 경우 브라우저의 다른 탭 화면을 보거나 브라우저가 최소화되어 있을 때 계속 타이머가 돌아 콜백을 호출하기 때문에 시스템 리소스 낭비를 초래하고 불필요한 전력을 소모하게 만든다고 한다.
반면 위 API는 페이지가 비활성화 된 상태면 페이지 화면 그리기 작업도 브라우저에 의해 일시 중지됨으로 CPU 리소스나 배터리 수명을 낭비하지 않게 된다고 한다. 이 밖에도 Animation frames 큐에서 처리되기 때문에 실행이 뒤쳐지거나 하는 현상을 감소시킬 수 있다. 마이크로 태스크 큐, 매크로 태스크 큐에서는 알고있었지만, 애니메이션 프레임 큐에 대해서는 이번 기회에 더 공부해볼 수 있었다.
useEffect내에서 requestAnimationFrame를 등록해주어 시간이 업데이트 될 때마다 브라우저가 리페인트 할 때에 맞춰 시간을 업데이트 해줌으로써 타이머 드리프트 문제를 해결했다.
해당 API에 대해 잘 정리해둔 블로그가 있어 다시보기용으로 [링크](https://inpa.tistory.com/entry/%F0%9F%8C%90-requestAnimationFrame-%EA%B0%80%EC%9D%B4%EB%93%9C)를 첨부해둔다.
데이터 포맷팅: Intl.DateTimeFormat API
- 메서드를 사용하기 전에 mdn을 통해서 업데이트된 내역이 있는지 한번씩 확인하면서 작업을 하는 편인데, 시간 포맷팅이 필요할 때 자주 사용하였던 toLocaleTimeString()은 현지화 문자열의 대규모 데이터베이스에서 검색을 수행해야하기에 잠재적으로 비효율적이라고 문서에 적혀있었다. 동일한 인수로 메서드가 여러 번 호출되는 경우 개체를 만들고 Intl.DateTimeFormat API 사용을 권장하고 있어 서울의 현지 시간을 포맷팅할 때 이 API를 사용하였다.
잦은 리렌더링 및 시간 업데이트: useEffect의 캡처, useRef의 사용
- useEffect의 디펜던시를 빈 배열로 주었을 때, 내부의 상태 로직이 아무리 재실행되고 업데이트 되어도 useEffect의 캡처에 의해 상태 로직들은 다 처음 값을 기준으로 동작하고 있었다. 시간 업데이트 로직에서 이를 해결해주기 위해 리렌더링에 영향을 주지 않으면서 업데이트 되기전의 시간의 값을 기억하기 위해 useRef를 사용하여 컨트롤 해주었다.
1년 이상 Vue3만 사용하다 보니, Vue의 라이프사이클과 동작 방식에 익숙해졌었는데 해당 로직을 작성하면서, 조금 잊어버렸던 React의 동작 방식과 문법을 다시 떠올렸다..
서버 컴포넌트, 클라이언트 컴포넌트 도입: 컴포넌트 간의 상태 공유 방식 다소 복잡해짐
- 이전에 React를 사용했을 때에는 상태 끌어올리기 또는 props drilling이 너무 복잡해질 경우 전역 상태로 관리하였는데, next14로 개발을 하다보니 서버 컴포넌트에서는 상태를 관리할 수 없어 작업하는데에 까다로운 부분이 많았다.
서버 컵포넌트를 처음 사용해보면서 느낀 것은 아직 더 나은 패턴에 대해 익숙치 않아서도 있겠지만, 상태 관리에 대해 좀 더 세밀한 패턴과 전략이 필요해진 듯 하다. 또 프로젝트 특성에 따라 조금 다르겠지만 서버 컴포넌트의 장점을 살려 클라이언트 컴포넌트를 최대한으로 쪼개서 최하단에서 관리하는 패턴이 번들 크기 축소 및 컴포넌트의 재사용성이나 설계, 구조, 성능 측면에서 볼 때는 좋은 장점일 거 같다. 확실히 프레임워크라 그런지 리액트가 가진 확장성의 장점을 살려 규격을 잡아준다는 느낌이 들었다. 프레임워크인 Vue3를 사용했을 때의 느낌과 조금 흡사한 느낌을 받았다.
다만 props를 주고받을 때 서버 컴포넌트에서 -> 클라이언트 컴포넌트 흐름으로 전달해야한다는 점, 또 클라이언트 컴포넌트 내에서만 react hook 사용이 가능하다는 점이 작업하는데에 다소 까다롭다. 해당 부분은 많은 작업을 해보면서 패턴을 터득해야할 듯 하다.
좀 더 자세한 예시로, 항목 목록이 있고 사용자가 선택한 항목(있는 경우)에 대한 데이터를 가져오고 표시한다고 가정할 때, 일반적으로 목록(클라이언트) 구성 요소를 생성하고 useState예를 들어 반응을 사용하여 구성 요소 상태에서 사용자가 선택한 항목(있는 경우)을 추적한다고 해보자. 이 때 서버로 다시 돌아갈 방법이 없다는 점이 작업하면서 가장 골머리를 앓았던 부분이다. 이를 피해가는 방법들이 있긴한거같지만 좋은 아키텍처인지는 모르겠다. 클라이언트 구성 요소가 서버 구성 요소 내에 중첩될 수 있지만 그 반대의 경우는 불가능하므로 클라이언트에서 선택한 항목에 대한 정보를 서버 구성 요소로 전달할 수 없다는 점의 제약이 작업할 때 은근히 까다롭다.
아키텍처의 고민
- next14를 처음 사용해보면서 서버 컴포넌트 그리고 SSG의 장점을 살리기 위해서 페이지별 page.tsx는 서버 컴포넌트 구조(토큰이 포함된 API 데이터 페칭 이점 가져가기)로 가져가고 최대한 작은 단위로 쪼개서 클라이언트 컴포넌트는 하단으로 가져가는 것이 좋다고 생각하였는데 구조를 짜면서 또, 클라이언트 사이드의 상태 관리에 따라 이런 이상적인 구조로 가져가기가 쉽지 않다고 생각이 들었다. 동적인 인터랙션이 많이 필요한 프로젝트가 아니기 때문에 최대한 SSG의 장점을 살린 위 구조로 잡아가보려고 한다.
동적 라우팅에서 사용되는 파라미터의 암호화 처리
- RSC를 사용하면서도 느낀 것이 API 호출 시 토큰이나 보안적으로 취약한 부분을 굉장히 강화한 새로운 패러다임이라고 생각이 들었는데, 동적 라우팅에서 파라미터를 자동으로 암호화 처리해주는 기능도 동일하게 느껴졌다. 이전에 Vue3의 프로젝트를 진행할 때에도 파라미터 또는 쿼리로 넘겨주는 값이 암호화 처리가 되어있지 않아 보안에 약점이 있어 직접 암호화를 구현하고 디코딩했어야했는데 next에서는 자체적으로 잡아주는 점이 편하게 느껴졌다.
Troubleshooting MDX
- 마크다운 게시물 렌더링을 MDX를 통해 설정하였다.
[공식문서 링크](https://github.com/hashicorp/next-mdx-remote)
Expected a closing tag for `
` (29:78-29:82) before the end of `paragraph`- **첫째, React는 원래 DOM의 복사본을 만들고 이를 가상 DOM이라 일컫는다. 가상 DOM의 각 노드는 요소를 나타낸다.**
사용 중 문제가 있었는데, 위의 예시처럼 내가 작성했던 블로그에서 형식에 맞지 않게 작성한 글들이 많아서 mdx 컴파일링 단계에서 에러가 발생하게 되는 컨텐츠들이 있었다.
## Set up
```sh
pnpm next dev
```