๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Lect & Tip/React by GPT

์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(SSR)๊ณผ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ์ตœ์ ํ™” ์ „๋žต

by st๊ณต๊ฐ„ 2025. 6. 5.
๋ฐ˜์‘ํ˜•

์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(SSR)๊ณผ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ์ตœ์ ํ™” ์ „๋žต

ํ˜„๋Œ€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์ดˆ๊ธฐ ๋กœ๋”ฉ ์†๋„์™€ ๊ฒ€์ƒ‰ ์—”์ง„ ์ตœ์ ํ™”(SEO)๊ฐ€ ๋งค์šฐ ์ค‘์š”ํ•œ ์š”์†Œ๋กœ ๋ถ€๊ฐ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ, ๋ฆฌ์•กํŠธ ๊ธฐ๋ฐ˜์˜ SPA(Single Page Application)๋Š” ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(CSR)์„ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ดˆ๊ธฐ ํŽ˜์ด์ง€ ๋กœ๋”ฉ ์‹œ ๋นˆ ํ™”๋ฉด์„ ๋ณด์—ฌ์ฃผ๊ฑฐ๋‚˜ ๊ฒ€์ƒ‰ ์—”์ง„ ํฌ๋กค๋Ÿฌ๊ฐ€ ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๋Œ€๋กœ ์ธ์‹ํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Next.js์™€ ๊ฐ™์€ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(SSR) ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ™œ์šฉํ•˜๋ฉด, ์„œ๋ฒ„์—์„œ ๋ฏธ๋ฆฌ HTML์„ ์ƒ์„ฑํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋กœ ์ธํ•ด ๋น ๋ฅธ ์ดˆ๊ธฐ ๋ Œ๋”๋ง๊ณผ SEO ์ตœ์ ํ™”๋ฅผ ๋™์‹œ์— ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SSR์˜ ๊ฐœ๋…๊ณผ ํ•„์š”์„ฑ

์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์€ ์‚ฌ์šฉ์ž๊ฐ€ ์›น ํŽ˜์ด์ง€์— ์ ‘์†ํ•  ๋•Œ, ์„œ๋ฒ„์—์„œ ๋ฏธ๋ฆฌ ์™„์„ฑ๋œ HTML ์ฝ˜ํ…์ธ ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ „์†กํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ด์™€ ๋‹ฌ๋ฆฌ CSR์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฒˆ๋“ค์ด ๋กœ๋“œ๋œ ํ›„ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋™์ ์œผ๋กœ ๋ Œ๋”๋ง๋˜๋ฏ€๋กœ, ์ดˆ๊ธฐ ๋กœ๋”ฉ ์‹œ๊ฐ„์ด ๊ธธ์–ด์ง€๊ณ  SEO ์ธก๋ฉด์—์„œ ๋ถˆ๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. SSR์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์žฅ์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • ๋น ๋ฅธ ์ดˆ๊ธฐ ๋ Œ๋”๋ง: ์„œ๋ฒ„์—์„œ ์ด๋ฏธ ์™„์„ฑ๋œ HTML์„ ์ „๋‹ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์‚ฌ์šฉ์ž๋Š” ํŽ˜์ด์ง€์— ๋น ๋ฅด๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • SEO ์ตœ์ ํ™”: ๊ฒ€์ƒ‰ ์—”์ง„ ํฌ๋กค๋Ÿฌ๊ฐ€ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋œ HTML์„ ๋ฐ”๋กœ ์ธ์‹ํ•  ์ˆ˜ ์žˆ์–ด, ๊ฒ€์ƒ‰ ์ˆœ์œ„์™€ ๋…ธ์ถœ์— ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ์†Œ์…œ ๋ฏธ๋””์–ด ๋ฏธ๋ฆฌ๋ณด๊ธฐ: ๋งํฌ๋ฅผ ๊ณต์œ ํ•  ๋•Œ, ๋ฉ”ํƒ€ ํƒœ๊ทธ ๋“ฑ ํ•„์š”ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋œ HTML์ด ์ œ๊ณต๋˜์–ด ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ด๋ฏธ์ง€๋‚˜ ์„ค๋ช…์ด ์ œ๋Œ€๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Next.js๋ฅผ ํ™œ์šฉํ•œ SSR ์ ์šฉ

Next.js๋Š” ๋ฆฌ์•กํŠธ ๊ธฐ๋ฐ˜์˜ SSR ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, ๊ฐ„๋‹จํ•œ ์„ค์ •๋งŒ์œผ๋กœ SSR ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Next.js๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŽ˜์ด์ง€๋ณ„๋กœ ๋ฐ์ดํ„ฐ ํŽ˜์นญ๊ณผ ๋ Œ๋”๋ง์„ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํŒŒ์ผ ๊ธฐ๋ฐ˜ ๋ผ์šฐํŒ…๊ณผ ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ… ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ๊ณผ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ๋™์‹œ์— ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Next.js ํ”„๋กœ์ ํŠธ ๊ตฌ์„ฑ ๋ฐ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

Next.js ํ”„๋กœ์ ํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ pages ํด๋” ๋‚ด์— ์กด์žฌํ•˜๋Š” ๊ฐ ํŒŒ์ผ์„ ํ•˜๋‚˜์˜ ๋ผ์šฐํŠธ๋กœ ์ธ์‹ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, pages/index.tsx ํŒŒ์ผ์€ ํ™ˆํŽ˜์ด์ง€ ์—ญํ• ์„ ํ•˜๊ณ , ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋“ค๋„ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” Next.js๋ฅผ ์ด์šฉํ•œ ๊ฐ„๋‹จํ•œ SSR ํŽ˜์ด์ง€ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

// pages/index.tsx
import React from 'react';
import { GetServerSideProps, NextPage } from 'next';

interface HomeProps {
  data: string;
}

const Home: NextPage<HomeProps> = ({ data }) => {
  return (
    <div style={{ padding: '20px', fontFamily: 'Arial, sans-serif' }}>
      <h2>Next.js SSR ์˜ˆ์ œ</h2>
      <p>์„œ๋ฒ„์—์„œ ๋ฏธ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ํŒจ์นญํ•˜์—ฌ ์ „๋‹ฌ๋ฐ›์€ ๋‚ด์šฉ: {data}</p>
    </div>
  );
};

export const getServerSideProps: GetServerSideProps = async (context) => {
  // ์‹ค์ œ API ํ˜ธ์ถœ์ด๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋“ฑ ๋ณต์žกํ•œ ๋กœ์ง์ด ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์Œ
  const data = '์•ˆ๋…•ํ•˜์„ธ์š”, SSR ํ™˜๊ฒฝ์—์„œ ๋ Œ๋”๋ง๋œ ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.';
  return {
    props: { data },
  };
};

export default Home;

์œ„ ์˜ˆ์ œ์—์„œ getServerSideProps ํ•จ์ˆ˜๋Š” ํŽ˜์ด์ง€๊ฐ€ ์š”์ฒญ๋  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„์—์„œ ํ˜ธ์ถœ๋˜๋ฉฐ, ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ํŒจ์นญํ•œ ํ›„ ์ปดํฌ๋„ŒํŠธ์˜ props๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋Š” ํŽ˜์ด์ง€ ์ ‘์† ์‹œ ๋ฏธ๋ฆฌ ์ค€๋น„๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฆ‰์‹œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SSR ํ™˜๊ฒฝ์—์„œ์˜ ์ปดํฌ๋„ŒํŠธ ์„ค๊ณ„ ์ „๋žต

SSR ํ™˜๊ฒฝ์—์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ๋Š” ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ๊ณผ ์ƒํƒœ ๊ด€๋ฆฌ์— ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ฃผ์š” ์ „๋žต์ž…๋‹ˆ๋‹ค.

1. ๋ฐ์ดํ„ฐ ํŽ˜์นญ ์ตœ์ ํ™”

  • ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๋ถ„๋ฆฌ: SSR ์‹œ ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ํŽ˜์นญํ•˜์—ฌ ๋ Œ๋”๋งํ•  ๋•Œ์™€ ํด๋ผ์ด์–ธํŠธ์—์„œ ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•  ๋•Œ์˜ ์ฐจ์ด๋ฅผ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. Next.js์—์„œ๋Š” getServerSideProps ๋˜๋Š” getStaticProps๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” SWR(React Hooks ๊ธฐ๋ฐ˜ ๋ฐ์ดํ„ฐ ํŽ˜์นญ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)์ด๋‚˜ React Query๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์—…๋ฐ์ดํŠธ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์บ์‹ฑ ์ „๋žต: ๋ฐ์ดํ„ฐ ํŽ˜์นญ ์‹œ ์บ์‹ฑ ์ „๋žต์„ ๋„์ž…ํ•˜๋ฉด, ๋ฐ˜๋ณต๋˜๋Š” ์š”์ฒญ์— ๋Œ€ํ•ด ์„œ๋ฒ„ ๋ถ€ํ•˜๋ฅผ ์ค„์ด๊ณ  ์‘๋‹ต ์†๋„๋ฅผ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. CDN, ์„œ๋ฒ„ ์บ์‹œ, ํ˜น์€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ์บ์‹ฑ์„ ์ ์ ˆํžˆ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.

2. ์ปดํฌ๋„ŒํŠธ ์ตœ์ ํ™”

  • ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ…: Next.js๋Š” ์ž๋™์œผ๋กœ ํŽ˜์ด์ง€๋ณ„ ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ…์„ ์ง€์›ํ•˜์ง€๋งŒ, ํ•„์š”์— ๋”ฐ๋ผ ๋™์  ์ž„ํฌํŠธ(dynamic import)๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ๋กœ๋”ฉ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ดˆ๊ธฐ ๋ฒˆ๋“ค ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ํ•„์š”ํ•œ ์‹œ์ ์—๋งŒ ์ถ”๊ฐ€ ์ฝ”๋“œ๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ ์บ์‹ฑ: React.memo, useMemo, useCallback ๋“ฑ์„ ํ™œ์šฉํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ์ตœ์†Œํ™”ํ•˜๊ณ , SSR๊ณผ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„œ ์ผ๊ด€๋œ ๊ฒฐ๊ณผ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” ๋™์  ์ž„ํฌํŠธ๋ฅผ ํ™œ์šฉํ•œ ์ปดํฌ๋„ŒํŠธ ๋กœ๋”ฉ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

// components/DynamicComponent.tsx
import React from 'react';

const DynamicComponent: React.FC = () => {
  return (
    <div style={{ padding: '10px', backgroundColor: '#f0f0f0', borderRadius: '8px' }}>
      <h3>๋™์  ์ž„ํฌํŠธ ์ปดํฌ๋„ŒํŠธ</h3>
      <p>์ด ์ปดํฌ๋„ŒํŠธ๋Š” ํ•„์š”ํ•  ๋•Œ๋งŒ ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค.</p>
    </div>
  );
};

export default DynamicComponent;
// pages/feature.tsx
import React, { Suspense, lazy } from 'react';
import { NextPage } from 'next';

const DynamicComponent = lazy(() => import('../components/DynamicComponent'));

const FeaturePage: NextPage = () => {
  return (
    <div style={{ padding: '20px' }}>
      <h2>ํŠน์ • ๊ธฐ๋Šฅ ํŽ˜์ด์ง€</h2>
      <Suspense fallback={<div>์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค...</div>}>
        <DynamicComponent />
      </Suspense>
    </div>
  );
};

export default FeaturePage;

์œ„ ์˜ˆ์ œ๋Š” DynamicComponent๋ฅผ ๋™์  ์ž„ํฌํŠธ๋ฅผ ํ†ตํ•ด ํ•„์š”ํ•œ ์‹œ์ ์—๋งŒ ๋กœ๋“œํ•˜๋„๋ก ๊ตฌ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค. Suspense ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•จ์œผ๋กœ์จ, ์‚ฌ์šฉ์ž์—๊ฒŒ ์›ํ™œํ•œ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

3. SEO ์ตœ์ ํ™” ๊ณ ๋ ค

  • ๋ฉ”ํƒ€ ํƒœ๊ทธ ๊ด€๋ฆฌ: Next.js์˜ Head ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ฐ ํŽ˜์ด์ง€๋ณ„๋กœ ์ ์ ˆํ•œ ๋ฉ”ํƒ€ ํƒœ๊ทธ(title, description, og ํƒœ๊ทธ ๋“ฑ)๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ฒ€์ƒ‰ ์—”์ง„์ด ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ์„ ์ •ํ™•ํžˆ ์ธ์‹ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ •์  ์‚ฌ์ดํŠธ ์ƒ์„ฑ(SSG) ํ™œ์šฉ: ์ฝ˜ํ…์ธ  ๋ณ€๊ฒฝ์ด ์žฆ์ง€ ์•Š์€ ๊ฒฝ์šฐ, Next.js์˜ getStaticProps๋ฅผ ํ†ตํ•ด ์ •์  ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๋”์šฑ ๋น ๋ฅธ ์‘๋‹ต ์†๋„์™€ SEO ์ตœ์ ํ™”๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ ‘๊ทผ์„ฑ ๋ฐ ์„ฑ๋Šฅ ๊ฐœ์„ : ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋œ ํŽ˜์ด์ง€๋Š” ์ดˆ๊ธฐ HTML์ด ์™„์„ฑ๋˜์–ด ์žˆ์–ด, ์Šคํฌ๋ฆฐ ๋ฆฌ๋”๋‚˜ SEO ํฌ๋กค๋Ÿฌ๊ฐ€ ์ฝ˜ํ…์ธ ๋ฅผ ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋ถˆํ•„์š”ํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰์„ ์ค„์—ฌ ํŽ˜์ด์ง€ ๋กœ๋”ฉ ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ ํ”„๋กœ์ ํŠธ ์ ์šฉ ์‚ฌ๋ก€ ๋ฐ ํ˜‘์—… ์ „๋žต

Next.js์™€ SSR์„ ํ™œ์šฉํ•œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋””์ž์ธ ์‹œ์Šคํ…œ, API ์„œ๋ฒ„, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ ์—ฌ๋Ÿฌ ์š”์†Œ๊ฐ€ ๋ณตํ•ฉ์ ์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ํŒ€ ๋‚ด ํ˜‘์—…์€ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

  • API ์„ค๊ณ„์™€ ๋ฐ์ดํ„ฐ ํŽ˜์นญ ํ˜‘์—…: ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ ํŒ€์ด ํ˜‘์—…ํ•˜์—ฌ RESTful API ๋˜๋Š” GraphQL API๋ฅผ ์„ค๊ณ„ํ•˜๊ณ , ๋ฐ์ดํ„ฐ ํŽ˜์นญ ์ „๋žต์„ ์‚ฌ์ „์— ๋…ผ์˜ํ•ฉ๋‹ˆ๋‹ค.
  • ๋””์ž์ธ ์‹œ์Šคํ…œ๊ณผ ์ปดํฌ๋„ŒํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ: Storybook๊ณผ ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ, ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœํ•˜๊ณ  ๋ฌธ์„œํ™”ํ•œ ํ›„, Next.js ํ”„๋กœ์ ํŠธ์— ํ†ตํ•ฉํ•ฉ๋‹ˆ๋‹ค.
  • CI/CD ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•: ์ž๋™ํ™”๋œ ํ…Œ์ŠคํŠธ์™€ ์ •์  ๋ถ„์„, ๋นŒ๋“œ ๋ฐ ๋ฐฐํฌ ๊ณผ์ •์„ ํ†ตํ•ด, SSR ํŽ˜์ด์ง€์˜ ์•ˆ์ •์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ์ง€์†์ ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

Next.js์™€ ๊ฐ™์€ SSR ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ™œ์šฉํ•œ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์€ ์ดˆ๊ธฐ ๋กœ๋”ฉ ์†๋„ ๊ฐœ์„ ๊ณผ SEO ์ตœ์ ํ™”์— ์žˆ์–ด ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. SSR ํ™˜๊ฒฝ์—์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ๋Š” ๋ฐ์ดํ„ฐ ํŽ˜์นญ, ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ…, ์บ์‹ฑ ์ „๋žต ๋“ฑ ๋‹ค์–‘ํ•œ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์„ ์ ์ ˆํžˆ ๋„์ž…ํ•˜์—ฌ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๊ทน๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋ฉ”ํƒ€ ํƒœ๊ทธ ์„ค์ • ๋ฐ ์ •์  ์‚ฌ์ดํŠธ ์ƒ์„ฑ์„ ํ†ตํ•œ SEO ๊ฐœ์„ ์€ ๊ฒ€์ƒ‰ ์—”์ง„์—์„œ์˜ ๋…ธ์ถœ ํšจ๊ณผ๋ฅผ ๋†’์ด๋ฉฐ, ์ „๋ฐ˜์ ์ธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ’ˆ์งˆ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์•ž์œผ๋กœ ๋ฆฌ์•กํŠธ ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ ์‹œ SSR ํ™˜๊ฒฝ์„ ์ ๊ทน ๊ณ ๋ คํ•˜๊ณ , Next.js์˜ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜์—ฌ ์•ˆ์ •์ ์ด๊ณ  ํ™•์žฅ์„ฑ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋น ๋ฅธ ์ดˆ๊ธฐ ๋ Œ๋”๋ง, ํšจ์œจ์ ์ธ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ, ๊ทธ๋ฆฌ๊ณ  ์šฐ์ˆ˜ํ•œ SEO ์ตœ์ ํ™”๋ฅผ ๋™์‹œ์— ๋‹ฌ์„ฑํ•˜์—ฌ, ์‚ฌ์šฉ์ž์™€ ๊ฒ€์ƒ‰ ์—”์ง„ ๋ชจ๋‘์—๊ฒŒ ๋งŒ์กฑ์Šค๋Ÿฌ์šด ์›น ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€