Next.js

4강 — 서버 액션과 배포

슬라이드 보는 법

→ / Space다음으로
이전으로
↓ / ↑같은 주제 안에서 단계 이동
O전체 슬라이드 한눈에 보기
F전체화면

아래쪽 화살표가 보이면 그 주제는 단계별로 이어집니다

지금까지

1강폴더가 주소, layout
2강서버 컴포넌트와 'use client'
3강async fetch, loading, 캐싱

오늘은 데이터를 보내고 세상에 내놓습니다

오늘 끝나면 할 수 있는 것

  • API 주소를 만든다
  • 폼 제출을 서버에서 바로 처리한다
  • 검색 결과에 잘 나오게 만든다
  • 이미지와 폰트를 최적화한다
  • 배포해서 링크를 낸다

오늘 배울 것

  • 17. 라우트 핸들러
  • 18. 서버 액션
  • 19. revalidate와 redirect
  • 20. 메타데이터
  • 21. 이미지와 폰트
  • 22. 빌드와 배포

17. 라우트 핸들러

API 주소를 만들려면

17. 라우트 핸들러

app/ └─ api/ └─ posts/ └─ route.js /api/posts

page.js 대신 route.js를 두면 API가 된다

17. 라우트 핸들러 GET · POST

            app/api/posts/route.js
            
              export async function GET() {
                const posts = await db.getPosts();
                return Response.json(posts);
              }

              export async function POST(request) {
                const body = await request.json();
                return Response.json({ ok: true });
              }
            
          
GET /api/posts
POST /api/posts

17. 정리

  • 같은 폴더에 page.jsroute.js 를 함께 둘 수 없다
  • 외부에서 부를 API가 필요할 때 쓴다
  • 내 앱 안에서만 쓸 거라면 서버 액션이 더 편하다

18. 서버 액션

폼을 서버에서 바로 처리하려면

18. 서버 액션 전에는

            
              'use client';

              function Form() {
                async function onSubmit(e) {
                  e.preventDefault();
                  await fetch('/api/posts', {
                    method: 'POST',
                    body: JSON.stringify({ title }),
                  });
                }
              }
            
          
API 만들고
fetch 붙이고
상태 관리하고…

글 하나 저장하는 데 몇 군데를 고쳐야 할까요?

18. 서버 액션

            
              export default function NewPost() {
                async function create(formData) {
                  'use server';
                  const title = formData.get('title');
                  await db.insert({ title });
                }

                return (
                  <form action={create}>
                    <input name="title" />
                    <button>저장</button>
                  </form>
                );
              }
            
          

18. 정리

  • 함수 안에 'use server'
  • <form action={함수}> 로 연결
  • 입력값은 formData.get() 으로 꺼낸다
  • JS가 꺼져 있어도 폼이 동작한다

19. revalidate와 redirect

저장한 뒤 화면을 맞추려면

19. revalidate 문제

            
              'use server';
              await db.insert({ title });
            
          
저장은 됐는데
목록에 안 보인다

3강의 캐시가 아직 남아 있으면?

19. revalidate와 redirect

            
              'use server';
              import { revalidatePath } from 'next/cache';
              import { redirect } from 'next/navigation';

              await db.insert({ title });
              revalidatePath('/blog');
              redirect('/blog');
            
          
  • 새로 쓴 글
  • 첫 번째 글

20. 메타데이터

검색과 공유에 잘 나오려면

20. 메타데이터

            app/layout.js
            
              export const metadata = {
                title: 'DTC 블로그',
                description: '동아리 소식을 전합니다',
              };
            
          

탭 제목 · 검색 결과 · 링크 미리보기

20. 메타데이터 동적

            
              export async function generateMetadata(props) {
                const post = await getPost(props.params.id);
                return { title: post.title };
              }
            
          

글마다 다른 제목

21. 이미지와 폰트

빠르게 보이게 하려면

21. 이미지 next/image

            
              import Image from 'next/image';

              <Image
                src="/logo.png"
                width={200}
                height={100}
                alt="로고"
              />
            
          
크기 조절자동
포맷 변환webp
늦게 불러오기자동

21. 폰트 next/font

            
              import { Noto_Sans_KR } from 'next/font/google';

              const noto = Noto_Sans_KR({ subsets: ['latin'] });

              <body className={noto.className}>
            
          
폰트를 미리 받아두어
글자가 늦게 바뀌지 않는다

22. 빌드와 배포

인터넷에 올리려면

22. 빌드

            
              npm run build
            
          
Route (app)
┌ ○ / 정적
├ ● /blog/[id] 정적 생성
└ ƒ /search 동적

22. 배포 Vercel

  1. 깃허브에 저장소를 만들고 올린다
  2. vercel.com 에서 깃허브로 로그인
  3. 저장소를 고르고 Deploy
  4. 주소가 나온다

Next.js를 만든 곳이 Vercel이라 설정이 필요 없습니다

22. 배포 환경 변수

  • API 키는 .env.local 에 두고 깃허브에 올리지 않는다
  • Vercel 설정 화면에 같은 값을 등록한다
  • NEXT_PUBLIC_ 이 붙은 값은 브라우저까지 간다

정리

Next.js 4강 전체

한눈에

1강폴더가 주소, [id], layout
2강서버 컴포넌트, 'use client'
3강async fetch, loading, error, 캐싱
4강route.js, 서버 액션, 메타데이터, 배포

미니 프로젝트

배운 것을 전부 써봅시다

미니 프로젝트 조건

  • 글 목록과 상세 화면 — 동적 라우트
  • 서버에서 데이터 가져오기 — async 컴포넌트
  • 글쓰기 폼 — 서버 액션
  • 배포해서 링크 공유

미니 프로젝트 주제

  1. 동아리 블로그 — 글 목록, 상세, 글쓰기
  2. 스터디 모집 게시판
  3. 맛집 지도 — 목록과 상세

React 5강에서 만든 것을 Next로 옮겨도 좋습니다

더 볼 것

수고하셨습니다