개발부터 배포까지: EdgeOne Pages에서의 Next.js 풀스택 모범 사례

Ethan MercerEthan Mercer
10 분 읽기
Spt 8, 2025

이 가이드는 고성능 Next.js 풀스택 애플리케이션 구축과 코드 품질이나 애플리케이션 속도를 저하시키지 않으면서 개발 워크플로우를 최적화하는 데 중점을 둡니다.

다음 섹션에서는 프로젝트 아키텍처, 환경 설정, 라우팅 전략, 효율적인 데이터 페칭 기법을 철저히 살펴보겠습니다. 이러한 모범 사례를 통해 EdgeOne Pages에서 Next.js 풀스택 애플리케이션을 원활하게 배포하고, 뛰어난 성능과 전 세계적인 접근성을 위해 엣지 컴퓨팅 능력을 활용할 수 있습니다.

디렉토리 구조 권장사항

다음 디렉토리 구조는 권장하는 Next.js 하이브리드 렌더링 템플릿을 나타냅니다. 이 신중하게 구성된 아키텍처는 확장 가능한 풀스택 애플리케이션을 구축하는 개발자들을 위한 최적의 기반 역할을 합니다:

next-mix-template/
├── src/                   
│   ├── app/               # Next.js App Router
│   │   ├── layout.tsx     
│   │   ├── page.tsx       # 홈 페이지 컴포넌트
│   │   ├── ssr/           # SSR 데모 페이지
│   │   ├── isr/           # ISR 데모 페이지
│   │   ├── ssg/           # SSG 데모 페이지
│   │   ├── streaming/     # 스트리밍 데모 페이지
│   │   ├── node-functions/# node function 데모 페이지
│   │   ├── edge-functions/# edge function 데모 페이지
│   │   ├── api/           # API 라우트
│   │   └── globals.css    
│   ├── components/        # React 컴포넌트
│   │   ├── ui/           
│   │   ├── Header.tsx    
│   │   ├── Hero.tsx      
│   │   ├── Features.tsx  
│   │   └── FeatureCard.tsx 
│   └── lib/              # 유틸리티 함수
├── public/               # 정적 리소스
├── package.json          # 프로젝트 설정
├── next.config.ts        # Next.js 설정
├── tailwind.config.ts    
└── components.json       # shadcn/ui 설정

이 프로젝트는 EdgeOne Pages와 원활하게 통합되는 두 개의 특수 백엔드 함수 디렉토리를 가진 표준 Next.js App Router 아키텍처를 따릅니다:

edge-functions 디렉토리는 EdgeOne Pages의 엣지 컴퓨팅 기능의 진입점 역할을 합니다. 사용자에게 가장 가까운 엣지 노드에서 직접 실행되어 빠른 응답 시간의 혜택을 받기 위해 가벼운 요청을 여기에 배치하여 탁월한 속도와 성능을 제공합니다.

EdgeOne Pages는 광범위한 Node.js 패키지 생태계를 활용할 수 있는 중앙 집중식 함수 배포 환경인 node-functions를 제공합니다. 이를 통해 간소화된 개발 경험을 유지하면서 완전한 Node.js 기능이 필요한 더 복잡한 기능을 빠르게 구현할 수 있습니다.

edge-functions과 node-functions에 대한 보다 포괄적인 자세한 내용은 공식문서를 참조하시기 바랍니다.

라우트 및 API 통합

EdgeOne Pages는 도메인 기반 경로 라우팅을 통해 페이지와 API 엔드포인트에 직접 액세스할 수 있게 합니다. 매핑은 파일 위치가 URL 경로에 직접 대응하는 일관된 패턴을 따릅니다. 예를 들어, /app/node-functions/get-users/index.js{domain}/get-users에서 액세스할 수 있습니다.

이 플랫폼은 자동 경로 매핑을 통한 직관적인 라우팅 시스템을 특징으로 합니다:

주요 기능:

  • 자동 경로 매핑: 파일 시스템 구조가 URL 라우트로 직접 변환됩니다
  • 무설정 구성: 수동 라우팅 설정이 필요하지 않습니다
  • 통합 라우트 관리: 페이지와 API 라우트의 원활한 처리
  • 포트 없는 액세스: 직접 도메인 기반 라우팅으로 포트 지정이 불필요합니다
Project structure:
/app/node-functions/get-users/index.js
/app/node-functions/create-user/index.js
/app/node-functions/products/[id].js

/app/edge-functions/get-products/index.js (edge)

Access method:
https://yourdomain.com/get-users      → run get-users/index.js
https://yourdomain.com/create-user    → run create-user/index.js
https://yourdomain.com/products/123   → run products/[id].js
https://yourdomain.com/get-products   → run get-products/index.js (edge)

페이지 렌더링 및 데이터 페칭

Next.js는 각각 고유한 데이터 페칭 메커니즘을 가진 여러 렌더링 전략을 제공합니다. EdgeOne Pages는 Next.js의 세 가지 주요 렌더링 모드인 정적 사이트 생성(SSG), 서버 사이드 렌더링(SSR), 증분 정적 재생성(ISR)에 대한 포괄적인 지원을 제공하여 개발자가 같은 애플리케이션 내에서 모든 방법을 활용할 수 있게 합니다.

1. App Router 데이터 페칭 (Next.js 13+)

새로운 App Router는 데이터 페칭에 다른 방법을 사용합니다. 포괄적인 자세한 내용은 공식 Next.js 문서를 참조하세요.

// app/products/page.js
// Default static rendering
async function getProducts() {
  const res = await fetch('https://api.example.com/products', {
    cache: 'force-cache' // Default Cache
  })
  return res.json()
}

export default async function ProductsPage() {
  const products = await getProducts()
  
  return (
    <div>
      {products.map(product => (
        <div key={product.id}>{product.name}</div>
      ))}
    </div>
  )
}

revalidate: 0을 설정하면 페이지가 모든 요청에 대해 데이터 검색에 서버 사이드 렌더링을 사용하도록 강제합니다.

// pages/dashboard.js
// 정적 및 클라이언트 사이드 데이터 페칭 결합
export async function getStaticProps() {
  // 자주 변경되 않는 데이터 가져오기
  const staticData = await fetch('https://api.example.com/config')
  const config = await staticData.json()

  return {
    props: { config },
    revalidate: 3600, // 1시간
  }
}

function Dashboard({ config }) {
  // 클라이언트가 실시간 데이터 가져오기
  const { data: liveData } = useSWR('/api/live-stats', fetcher, {
    refreshInterval: 5000
  })

  return (
    <div>
      <h1>{config.title}</h1>
      {liveData && <div>온라인 사용자: {liveData.onlineUsers}</div>}
    </div>
  )
}

2. getStaticProps (정적 생성)

빌드 프로세스 중에 데이터를 가져와 정적 HTML 페이지를 생성합니다. 비교적 안정적이고 빈번한 업데이트가 필요하지 않은 콘텐츠에 이상적입니다.

// pages/products.js
export async function getStaticProps() {
  const res = await fetch('https://api.example.com/products')
  const products = await res.json()

  return {
    props: {
      products,
    }
  }
}

export default function Products({ products }) {
  return (
    <div>
      {products.map(product => (
        <div key={product.id}>{product.name}</div>
      ))}
    </div>
  )
}

사용 사례: Next.js 공식 웹사이트 (nextjs.org)

3. getServerSideProps (서버 사이드 렌더링)

서버 사이드 렌더링(SSR)은 모든 요청에 대해 서버 측에서 데이터를 검색합니다. 이 방법은 실시간 데이터 업데이트가 필요하거나 요청별 정보에 액세스해야 하는 페이지에 이상적입니다.

// pages/user/[id].js
export async function getServerSideProps(context) {
  const { id } = context.params
  const { req, res, query } = context
  
  const cookies = context.req.cookies
  
  const userData = await fetch(`https://api.example.com/users/${id}`)
  const user = await userData.json()

  if (!user) {
    return {
      notFound: true, 
    }
  }

  return {
    props: {
      user,
    }
  }
}

export default function User({ user }) {
  return <div>Welcome, {user.name}!</div>
}

사용 사례: LinkedIn (linkedin.com)

4. ISR (Incremental Static Regeneration)

revalidate 매개변수는 Incremental Static Regeneration (ISR)을 활성화하여 규칙 기반의 온디맨드 페이지 데이터 업데이트를 제공합니다.

export async function getStaticProps() {
  const res = await fetch('https://api.example.com/blog')
  const posts = await res.json()

  return {
    props: {
      posts,
    },
    // 세 가지 ISR 전략
    revalidate: 60, // 초 단위 시간 간격 후 재생성
    // 또는
    revalidate: false, // ISR 비활성화하고 빌드 시에만 생성
    // 또는
    revalidate: true, // 온디맨드 ISR (설정 필요)
  }
}

사용 사례: Dev.to (dev.to) 인기 콘텐츠는 5분마다 업데이트

메서드 비교 및 의사결정 매트릭스

메서드실행 시간사용 사례SEO성능
getStaticProps빌드 시간정적 콘텐츠✅ 우수⚡ 최고속
getServerSideProps모든 요청동적 콘텐츠/개인화✅ 좋음🐢 느림
ISR (revalidate)빌드 시간 + 주기적 업데이트반정적 콘텐츠✅ 좋음⚡ 빠름
App Router fetch설정에 따라 결정유연함✅ 좋음🔧 설정 가능

개발자들은 의사결정 매트릭스를 사용합니다:

웹사이트 유형권장 전략대표 사이트주요 고려사항
문서/블로그SSGNext.js Docs, MDNSEO, 성능, 비용
전자상거래 플랫폼SSR/ISRAmazon, Shopify실시간 재고, 개인화
소셜 미디어SSRTwitter, LinkedIn실시간 업데이트, 개인화
뉴스 미디어ISR/SSRCNN, BBC신속성, SEO
SaaS 마케팅 사이트SSG/ISRStripe, Slack성능, 전환율
기업 웹사이트SSGApple, Microsoft브랜드 프레젠테이션, 성능
스트리밍 미디어SSRNetflix, Spotify개인화, 실시간 추천

환경 변수 관리

EdgeOne Pages는 환경 변수 관리를 위한 Next.js 규칙을 준수합니다:

  • 공개 변수 : `NEXT_PUBLIC_` 접두사가 붙은 환경 변수는 클라이언트 측 번들에 포함되어 브라우저 코드에서 접근할 수 있습니다. 이러한 변수는 민감하지 않은 정보만 포함해야 합니다.
  • 보호된 변수: API 키, 인증 토큰(예: `AI_TOKEN`) 또는 기타 자격 증명과 같은 민감한 정보의 경우 `NEXT_PUBLIC_` 접두사를 생략하세요. 이러한 변수는 서버 측에서만 유지되어 클라이언트 측 코드에 노출되지 않도록 보호됩니다.

이러한 일관된 접근 방식을 통해 표준 Next.js 환경 변수 시스템과의 호환성을 유지하면서 구성 값의 가시성과 보안을 관리할 수 있습니다.

# private env

OPENAI_API_URL=
OPENAI_API_KEY=

DB_HOST=
DB_PORT=
DB_USER=
DB_PASSWORD=
DB_NAME=

# public env

NEXT_PUBLIC_AUTHOR=
NEXT_PUBLIC_EMAIL=

일반적으로 단일 .env.local 파일이면 충분합니다. 그러나 때로는 개발(next dev) 또는 프로덕션(next start) 환경에 대해 일부 기본 설정을 별도로 추가하고 싶을 수 있습니다.

Next.js를 사용하면(0,0%,90%);">.env(모든 환경용), .env.development (개발 환경용), .env.production(프로덕션 환경용)에서 기본값을 설정할 수 있습니다..env.local은 항상 기본 설정을 재정의합니다.

EdgeOne Pages에 배포할 때는 로컬 .env 파일과 일치하는 환경 변수를 EdgeOne 콘솔에서 구성해야 합니다. EdgeOne Pages는 Next.js 규칙을 따르며, NEXT_PUBLIC_ 접두사가 붙은 변수는 클라이언트 측 코드에 포함되고, 이 접두사가 없는 변수는 서버 측에서 보호됩니다. 

참고: 보안을 위해 항상 .env* 파일을 에 추가하여 API 키와 토큰과 같은 민감한 자격 증명이 실수로 리포지토리에 커밋되는 것을 방지하세요.

결론

EdgeOne Pages는 Next.js 풀스택 프로젝트에 대한 포괄적인 네이티브 지원을 제공하며, Static Site Generation (SSG), Server-Side Rendering (SSR), Incremental Static Regeneration (ISR), API Routes를 포함한 다양한 핵심 Next.js 기능과 완벽하게 호환됩니다. 개발자는 복잡한 구성 조정 없이 Next.js 프레임워크의 모든 장점을 활용할 수 있으며, 유연한 렌더링 전략 선택과 효율적인 풀스택 개발 경험을 가능하게 합니다.

EdgeOne Pages의 간소화된 배포 프로세스 덕분에 개발팀은 EdgeOne CLI 작업이나 CI/CD 통합을 통해 Next.js 애플리케이션을 글로벌 엣지 네트워크에 빠르게 배포할 수 있습니다. 이러한 원활한 배포 경험은 운영 복잡성을 크게 줄일 뿐만 아니라 엣지 컴퓨팅 기능을 통해 뛰어난 성능과 안정성을 제공하여 개발자가 인프라 관리와 최적화에 대한 걱정 없이 비즈니스 로직 구현에 더 집중할 수 있게 해줍니다.