[weather-NextJS] 개발기#1

ZenTechie·2023년 8월 1일
0
post-thumbnail

7.31 (일)

참고한 레이아웃

수행한 것

  • 필요한 패키지 설치
    • TailwindCSS
    • Framer-motion
  • 레이아웃에 필요한 컴포넌트들 구성
    • 위 레이아웃에서 대기질과 강수량은 일단 제외했다. 대기질은 API 목록에서 찾지를 못했고, 강수량은 지도 API를 사용해야 하는데, Tomorrow.io가 제공은 하나 다른 기능에 먼저 집중하는 것이 개발 속도 측면에서 좋겠다고 판단했다.
    • page.tsx에 유사한 컴포넌트들끼리 묶어서 각 section 별로 구성했다.
  • 반응형 레이아웃 구상
    • 모바일과 데스크탑에서 모두 사용한다는 가정하에, 레이아웃의 변형이 예상됐다.
    • 모바일은 아이폰 날씨 어플을 참고했고, 데스크탑은 맥 날씨 어플을 참고했다.
  • API 요청 함수 작성
  • 메인 현재 날씨(사진에서 맨 위), 시간대 별 날씨, 주간 날씨 코드 작성

고민한 것

  • 아이폰 날씨 어플에서 아래로 스크롤했을 때 특이한 애니메이션을 볼 수 있는데(컴포넌트의 높이가 서서히 줄어드는 애니메이션(?)), 이를 어떻게 짜야하나?
  • 자외선 지수, 일출, 일몰 등 날씨 세부 사항들에 대해 컴포넌트를 어떻게 짜야하는가?
    • 재사용 가능한 컴포넌트로 만들수 있을 것 같다고 생각했는데, 각 데이터의 단위도 다르고, 중간에 보면 막대 그래프, 나침반이라던가 다 달라서 이를 생각해보면 재사용 가능한건가? 라는 의문이 들었다.
    • 처음에는 이들을 type별로 나눠서 해결하면 되지 않을까?라고 생각하여 고안해본 해결책은 다음과 같다.
      • if문으로 처리 : 코드가 너무 길어진다.
      • 삼항 연산자로 처리 : 이것 또한 코드가 너무 길어지고 더러워진다.
  • API 요청을 어느 위치에서 할 것인가?
    • NextJS13 버전을 사용하기로 했고 이전 NextJS12에서의 pages라우터가 아닌 app 라우터로 변경되는 등 꽤나 달라진 것이 있었기에 공부가 필요했다.

배운 것

  • 애니메이션은 나중에 해도 되는데, 항상 뭔가 꽂히면 해결책을 알고 싶어서 그것만 고민하는데 시간을 많이 허비한다. 습관을 고쳐야겠다.
  • NextJS는 Client Component와 Server Component가 있다. 각 특성에 따라 Data Fetching 방식이 다르다. 또한 NextJS의 버전13(최신버전)은 버전12와 다르다.
  • page router 방식에는 api폴더가 있는데, 나는 여기서 api를 호출해서 처리해야 하는 줄 알았다. 그런데 찾아보니, NextJS는 풀스택을 개발할 수 있는 React 프레임워크로서 api폴더는 API를 구축할 수 있게 해주는 것이었다.
  • page router 방식에는 page 레벨에서 api를 호출하는 방법이 3가지가 있다.
    • getStaticProps
    • getStaticPaths
    • getServerSideProps
  • NextJS13에서는 Data Fetch를 다음과 같이 수행할 수 있다.
    • Server 측면에서, fetch 를 사용한다.
    • Server 측면에서 서드파티 라이브러리를 사용한다.
    • Client 측면에서 서드파티 라이브러리를 사용한다.
      ➡️ 이 중 나는 1번째를 사용했다.

Data Fetching in NextJS13

NextJS는 fetch를 사용할 때 caching과 revalidating을 제공하며, Server Component에서 async/await으로 사용가능하다.

사용법은 되게 간단하다.

// Data Fetching 함수
async function getData() {
  const res = await fetch('https://api.example.com/...')
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
 
  if (!res.ok) {
    // This will activate the closest `error.js` Error Boundary
    throw new Error('Failed to fetch data')
  }
 
  return res.json()
}

// 서버 컴포넌트
export default async function Page() {
  const data = await getData()
 
  return <main></main>
}

Caching Data

Caching은 말그대로 데이터를 저장해서 매 요청마다 re-fetch하지 않아도 되도록 해준다.
기본적으로 NextJS는 자동으로 Caching을 수행한다. 이는 데이터가 build time 또는 request time에서 fetch되고 caching되며 매 요청마다 재사용 될 수 있음을 의미한다.

// 'force-cache' is the default, and can be omitted
fetch('https://...', { cache: 'force-cache' })

Revalidating Data

Revalidation(재확인, 재검증)은 데이터 캐시를 삭제하고 최신 데이터를 다시 가져오는 기능이다. 데이터가 변경되고 최신 정보를 표시해야 할 때 사용하면 유용하다.

Revalidation에도 2가지 방식이 있다.

  • Time-based revalidation : 특정 시간이 지나면 자동으로 수행하는 방식이다. 데이터가 자주 변하지 않고 꼭 데이터의 '최신성'이 엄청 중요하지 않은 경우에 사용하면 좋다.
  • On-demand revalidation : 말 그대로 요구가 있을 때 수행하는 방식이다. 이는 특정한 이벤트(event)에 따라 재검증된다. (e.g. <form> submission)
    이는 데이터가 바로바로 최신으로 변경되어야 하는 경우에 사용하면 좋다.(e.g. 블로그에 글을 쓰면 목록에서 바로 글이 보이는 것)
    또한, tag-based, path-based 접근 방식을 사용해서 데이터의 그룹을 한번에 재검증할 수 있다.

Time-based revalidation

fetch에 next.revalidate 옵션을 전달해서 사용할 수 있다.(=cache의 생명주기를 설정할 수 있다.)
이때, 단위는 이다.

// 3600초 = 1시간 뒤에 revalidate
fetch('https://...', { next: { revalidate: 3600 } })

On-demand revalidation

데이터는 Route Handler 또는 Server Action 내에서 path(revalidatePath) 또는 cache tag(revalidateTag)를 사용해서 재검증 될 수 있다고 한다.

자세한 설명은 공식 문서를 참고하자.

cache tag 사용

// collection이라는 태그 사용
export default async function Page() {
  const res = await fetch('https://...', { next: { tags: ['collection'] } })
  const data = await res.json()
  // ...
}

path 사용

// URL
https://<your-site.com>/api/revalidate?tag=collection&secret=<token>
// path 사용
import { NextRequest, NextResponse } from 'next/server'
import { revalidateTag } from 'next/cache'
 
// e.g a webhook to `your-website.com/api/revalidate?tag=collection&secret=<token>`
export async function GET(request: NextRequest) {
  // Check for secret to confirm this is a valid request
  if (
    request.nextUrl.searchParams.get('secret') !== process.env.MY_SECRET_TOKEN
  ) {
    return res.status(401).json({ message: 'Invalid token' })
  }
 
  const tag = request.nextUrl.searchParams.get('tag')
  revalidateTag(tag)
  return NextResponse.json({ revalidated: true, now: Date.now() })
}

Data Fetching에 관한 자세한 설명은 공식 문서로..

profile
데브코스 진행 중.. ~ 2024.03

0개의 댓글