목차
새로운 팀에 합류해서 신규 프로젝트 작업을 하고 있는데 마침 app directory로 환경설정을 하고 있는 단계라 nextjs를 문서로만 공부하다가 실무에 적용해 볼 수 있었다.
문서로만 공부하다가 직접 써보니 너무 재밌었다.
시행착오도 겪었지만 문서를 찾아보면서 하나씩 해결해 나갔고 지금은 어느 정도 기초 설정이 안정되었다!
그래서 좀 기록해놓고 싶은 내용을 정리해보려고 한다~!
server action
- 서버에서만 실행시킬 함수를 server action이라고 한다.
공식문서에서는 노출되면 안 되는 데이터를 사용해야 할 때 server action을 사용하면 된다고 설명한다.
지금 진행 중인 프로젝트에서 네트워크 요청 시 유저의 토큰정보를 헤더에 넣어서 요청을 전송하려고 하는데, 요청자체를 브라우저에 노출이 되지 않도록 하자고 방향이 정해져서 이때 server action을 적용했다.
cookie 정보를 server action에서 받아와서 요청 header에 심어준다.
흐름을 정리해 보자면 요렇다!
컴포넌트에서 data fetching 훅을 호출하고, data fetching hook에서 server action을 호출한다.
(물론 컴포넌트에서 바로 server action을 호출할 순 있지만, 요건 다른 관점에서 패턴을 맞춘 거라 저렇게 쓰고 있음)
server action에서 fetch작업을 호출하는데, 이게 로컬에서 테스트할 때는 괜찮았는데 배포를 하니 데이터 요청이 안 가는 문제가 있었다ㅠㅜㅠㅜ
배포서버의 로그를 확인해 보니 아래와 같은 에러가 찍혀있음
`x-forwarded-host` header does not match `origin`
그래서 공식문서에서 좀 찾아보니 요런 내용이 있었다. host 정보를 추가해줘야 했나 보다
Next.js에서 allowedOrigins 설정은 Cross-Origin Resource Sharing(CORS) 정책을 구현하는 데 중요한 역할을 합니다.
보안 강화: 특정 도메인만 API에 접근할 수 있도록 제한함으로써 무단 접근을 방지합니다
CORS 정책 구현: 서버가 어떤 출처(origin)의 요청을 허용할지 명시적으로 정의합니다
크로스 도메인 요청 관리: 다른 도메인에서 오는 API 요청을 안전하게 처리할 수 있게 해 줍니다
CSRF 공격 방지: 신뢰할 수 있는 도메인만 서버 액션을 호출할 수 있도록 제한하여 CSRF(Cross-Site Request Forgery) 공격을 예방합니다
유연한 접근 제어: 필요에 따라 여러 도메인을 허용 목록에 추가할 수 있어, 다양한 환경에서의 접근을 관리할 수 있습니다
그래서 next.config.js에 allowedOrigin 정보를 추가해 주면 된다!
const nextConfig = {
experimental: {
serverActions: {
allowedOrigins: [],
},
},
}
Image
Nextjs에서 제공해 주는 Image 컴포넌트는 최적화가 되어있기 때문에 Layout Shift 같은 문제를 방지하기도 하고,
Image컴포넌트는 width, height 사이즈 정보를 필수로 받기 때문에 빌드 때 이미지 최적화도 된다!
nextjs 캐시파일에 사이즈가 최적화된 이미지가 추가된다.
지금 프로젝트에서 사용자가 프로필 이미지를 업로드하면 aws s3에 올려서 사용자의 정보 조회 시 img url정보가 받아와 진다.
Nextjs Image 컴포넌트를 사용할 때, src에 외부 이미지 URL을 넣으면 에러가 난다(dev모드 기준).
만약 외부 이미지를 사용해야 한다면 next.config.js파일에 이미지의 도메인 정보를 설정해줘야 한다.
이미지 관리 도메인이 많다면 모두 추가해줘야 한다...!
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 's3.ap-northeast-2.amazonaws.com',
},
],
},
}
config를 위 방식으로 수정하고 나서도 이미지게 제대로 그려지지 않는 이슈가 있었다. 그래서 네트워크탭을 확인해 봤는데, 이미지 링크가 https://~~로 시작하는 게 아니라 http://localhost:3000/_next/~~~~https:// 이런 식으로 구성되어 있었다...
그래서 문서를 좀 찾아보니 외부 URL을 사용할 때는 최적화를 꺼주면 된다.
import Image from 'next/image'
const UnoptimizedImage = (props) => {
return <Image {...props} unoptimized />
}
unoptimized props를 넘겨주니 이미지가 정상적으로 떴다.
dynamic import (Lazy Loading)
동적으로 import 하는 방법은 공식문서를 보면 된다!
컴포넌트가 렌더링 되는 방식은 크게 3가지로 나뉜다.
1. 서버 컴포넌트 - 서버에서 Pre-Render
2. 클라이언트 컴포넌트 - 서버에서 Pre-Render + 브라우저에서 hydration
3. lazy loading 클라이언트 컴포넌트 - 브라우저에서 JS로 렌더 (서버에서 Pre-Render 되지 않음)
1, 2는 import로 컴포넌트 호출하면 사용할 수 있는데, 3 방식으로 사용하려면 아래처럼 dynamic + ssr : false 처리를 해줘야 한다.
const ComponentC = dynamic(() => import('../components/C'), { ssr: false })
동적 임포트는 외부 라이브러리를 쓸 때 Nextjs를 지원해주지 않으면 동적으로 import 해서 사용해도 되고, client component로 감싸서 사용해도 된다.
나는 외부 라이브러리를 사용할 때 계속 hydration에러가 발생해서 저렇게 동적 import를 해서 사용하니 hydration에러가 사라졌다.
그래서 단순히 라이브러리가 nextjs를 지원해주지 않는구나라고 생각했었는데, 알고 보니 원인은 다른 거였다......
렌더 할 때 Date정보를 초단위로 그리는 부분이 있었는데, Pre-render 되는 시간과 client component가 hydration 되는 시점이 달라서 계속 text hydration 에러가 발생했던 거였다...
요것도 공식문서에 해결방법이 있었다
Text content does not match server-rendered HTML
위와 같은 케이스일 때 해결할 수 있는 방식이다
여러 방법 중 나는 suppressHydrationWarning 이 기능을 사용했다
아래처럼 설정해 주면 그려지는 데이터가 달라지더라도 hydration에러가 발생하지 않는다!
<time datetime="2016-10-25" suppressHydrationWarning />
사실 이것 말고도 배운 건 많지만, 큼지막한 기능은 기본적으로 공식문서에 나오기 때문에 나는 실제 사용 시 발생했던 문제들과 해결방법 위주로 정리해 봤다.
문서로만 공부하는 것과 실제로 써보면서 만나는 문제는 차이가 컸다.
그래도 문서에서 해결책도 잘 설명해 주기 때문에 아직까지는 큰 문제없이 잘 쓰고 있다~!
'개발' 카테고리의 다른 글
Deep Link란 무엇일까? (1) | 2024.08.18 |
---|---|
저의 훼이보릿 라이브러리 zod에 대해 정리해보겠어요(+ 실제 사용 예시) (0) | 2024.08.04 |
[GIT] 실무에서 자주쓰는 Git 명령어 정리 (21) | 2024.07.26 |
Error 객체를 JSON.stringify에 넣으면 빈객체가 출력되는건에 대하여 (1) | 2024.04.27 |
10분만에 npm cli 명령어로 자기소개하기 (1) | 2023.09.28 |