ToolActToolAct

데모

도구 데모 페이지

데이터SSR
rettrue
msgnull
statusCode0
dataHello World

SSR이란?

Demo 페이지는 일반 사용자를 위한 실용 도구라기보다 서버 사이드 렌더링 경로를 확인하기 위한 작은 참고 페이지입니다. Next.js App Router 페이지가 서버에서 데이터를 가져오고, 그 결과를 첫 HTML 응답에 렌더링하며, 현재 언어의 번역 문구도 함께 불러올 수 있음을 보여 줍니다. 환경 변수, 서버 측 서명 요청, API 응답 형식, locale 라우팅, 번역 로딩 같은 공통 기반이 올바르게 연결되어 있는지 확인하는 데 적합합니다. 이 페이지가 정상 동작하면 복잡한 도구 페이지를 디버깅하기 전에 기본 SSR 경로가 건강하다고 볼 수 있습니다. 실패한다면 개별 도구보다 공통 서버 설정이나 API 연결 문제를 먼저 의심해야 합니다.

사용 방법

사용 방법

  1. 페이지가 서버에서 백엔드 API를 자동으로 호출합니다
  2. HTML에 미리 렌더링된 콘텐츠가 포함되어 있어 클라이언트 요청이 필요 없습니다
  3. API에서 반환한 데이터를 확인하세요
  4. SEO 최적화가 필요한 페이지에 적합합니다

개발 참고사항

  • 이 페이지를 SSR, 로케일 로딩, 서명된 서버 요청, API 연결에 대한 스모크 테스트로 활용하세요.
  • 이 페이지가 작동하지 않으면 특정 도구 페이지를 디버깅하기 전에 공유 서버 설정을 확인하세요.

활용 사례

서명된 서버 사이드 API 경로 검증데모 페이지를 열어 SSR 데이터가 현재 locale과 API_BASE_URL 설정으로 serverPageFetch를 통해 가져올 수 있는지 확인하세요. 페이지는 강제 동적(force-dynamic)이므로 렌더링된 ret, msg, statusCode, data 필드는 항상 최신 서버 응답을 반영하며, 이것이 스모크 테스트에 필요한 것입니다. 이 경로의 정상 응답은 공유 서명 키, nonce 저장소, locale 협상이 모두 양호하다는 것을 의미합니다.
백엔드 응답 필드가 앱 셸에서 어떻게 렌더링되는지 확인페이지는 SSR 배지와 함께 ret, msg, statusCode, data를 표시하므로, 개발자가 응답 형식과 오류 상태 표현을 위한 간결한 스모크 테스트를 할 수 있습니다. 서버에서 렌더링되므로 i18n 메시지 로딩, locale 세그먼트, 서명된 fetch 래퍼가 수동으로 클라이언트를 계측하지 않고도 작동하는지 확인할 수 있습니다.
내부 통합 참고 자료로 활용강제 동적이고 서버 렌더링이므로, 이 페이지는 순수 클라이언트 사이드 처리가 아닌 서명된 서버 API 접근이 필요한 미래 도구를 위한 간결한 예시입니다. 백엔드를 호출하는 SSR 페이지를 추가할 때 작업 참고 자료로 활용하세요. 데모의 표면을 의도적으로 최소한으로 유지하세요. 작고 예측 가능한 응답 형식이 스모크 테스트의 신뢰성을 만드는 것이며, 지나치게 확장된 데모는 실제로 어떤 하위 시스템이 실패했는지를 모호하게 만듭니다.
이 SSR 검사로 locale 라우팅 회귀 감지여러 locale 접두사에서 데모를 방문하여 번역된 라벨과 ret/msg/data 필드가 여전히 서버 사이드에서 렌더링되는지 확인하세요. 하나의 locale 아래에서 누락된 번역 키나 세그먼트 오프바이원은 사용자-facing 도구가 테스트되기 전에 여기서 먼저 나타납니다. 데모가 한 locale에서는 깨지고 다른 locale에서는 통과하면, 회귀는 거의 항상 서명된 fetch 래퍼가 아닌 locale 세그먼트, 메시지 로더, 또는 라우팅 트리에 있습니다.
와이어 로그에서 X-Timestamp, X-Nonce, X-Sign 헤더 확인데모 페이지에서 나가는 요청을 검사하여 서명된 서버 fetch가 예상 헤더를 포함하는지 확인하세요. 이것이 실제 API의 401/403 오류를 디버깅하는 가장 빠른 방법입니다. 로컬 개발 서버를 통해 프록시할 때 동일한 헤더가 브라우저 DevTools에도 표시되므로 서명된 fetch 래퍼를 종단 간 검증할 수 있습니다. 서명이 올바른 것 같은데 업스트림이 여전히 거부하면, 서버의 시계 편차(X-Timestamp) 또는 nonce 충돌(X-Nonce)이 원인인 경우가 대부분이며, 백엔드 티켓을 열기 전에 데모의 요청 로그에서 둘 다 확인하는 것이 가장 깔끔합니다.

기술 원리

이 데모 페이지는 Next.js 16 App Router 기반으로 기본적으로 서버 사이드 렌더링(SSR)을 사용합니다. 사용자가 페이지를 요청하면 Node.js 서버가 먼저 React 컴포넌트를 실행하고, 백엔드 API를 호출하여 데이터를 가져온 뒤 완전히 렌더링된 HTML을 단일 응답으로 브라우저에 반환합니다. 브라우저는 즉시 HTML 파싱과 페인팅을 시작하므로, JavaScript가 다운로드되고 실행될 때까지 기다리지 않고 첫 프레임에서 완전한 콘텐츠를 볼 수 있습니다. 이는 전통적인 클라이언트 사이드 렌더링(CSR)과 대조됩니다. CSR에서는 서버가 거의 빈 HTML 셸과 JS 링크만 반환하고, 브라우저가 JS 번들을 다운로드하고, 프레임워크 초기화를 실행하고, API를 호출하여 데이터를 가져온 뒤에야 페이지를 렌더링합니다. 사용자 관점에서는 "한동안 빈 화면"이며, 검색 엔진 크롤러에게는 더 나쁩니다. 대부분의 크롤러는 JavaScript를 실행하지 않고 빈 셸만 보게 됩니다. SSR 후 Next.js는 "하이드레이션"을 수행하기 위한 JavaScript 청크도 주입합니다. 기존 DOM을 React 컴포넌트 트리에 연결하고 이벤트 리스너를 바인딩하여 페이지를 대화형으로 만듭니다. 전체 흐름은 HTML 파싱 -> CSS 로드 -> JS 다운로드 -> 하이드레이션 -> 대화형입니다. Core Web Vitals 중 LCP(Largest Contentful Paint)와 CLS(Cumulative Layout Shift)는 SSR에서 보통 더 좋고, INP(Interaction to Next Paint)는 하이드레이션 속도와 이벤트 핸들러 구현 품질에 따라 달라집니다.

  • Next.js App Router: App Router의 페이지는 기본적으로 서버 컴포넌트로, 서버에서 실행되고 추가 설정 없이 자동으로 HTML을 반환합니다.
  • SSR vs CSR: SSR은 서버 자원을 사용하는 대신 빠른 첫 페인트와 SEO 친화성을 제공합니다. CSR은 SEO가 필요 없는 내부 대시보드 등 대화형 시나리오에 적합합니다.
  • 첫 페인트 흐름: HTML 파싱 -> CSS 로드 및 렌더링 -> JS 다운로드 및 실행 -> React 하이드레이션 -> 페이지 대화형. 각 단계가 LCP에 영향을 줍니다.
  • SEO 크롤링 친화성: Googlebot, Bingbot 등 주요 크롤러는 HTML 텍스트를 직접 읽습니다. SSR의 완전한 콘텐츠 출력은 크롤링 범위를 보장합니다.
  • Web Vitals 기준값: LCP < 2.5초, INP < 200ms, CLS < 0.1이 Google의 권장 "양호" 기준입니다. SSR은 LCP와 CLS를 달성하기 쉽게 만듭니다.
  • 서명된 요청: 데모 페이지는 서버에서 serverApiFetch를 통해 백엔드 API를 호출하며, X-Timestamp, X-Nonce, X-Sign을 자동으로 전달하여 인증을 완료합니다.

예시

SSR (서버 사이드 렌더링)

// app/page.tsx (기본 서버 컴포넌트)
export default async function Page() {
  const data = await fetch('/api/info').then(r => r.json());
  return <div>{data.title}</div>;
}
// HTML에 <div>실제 콘텐츠</div>가 이미 포함되어 전송됨

CSR (클라이언트 사이드 렌더링)

'use client';
import { useEffect, useState } from 'react';

export default function Page() {
  const [data, setData] = useState(null);
  useEffect(() => {
    fetch('/api/info').then(r => r.json()).then(setData);
  }, []);
  return <div>{data?.title || 'Loading...'}</div>;
}
// 첫 페인트 HTML에는 <div>Loading...</div>만 포함됨

첫 페인트 속도 비교

# SSR
FCP: 0.4s  LCP: 0.8s  TTI: 1.2s
SEO: 크롤러가 완전한 콘텐츠를 즉시 받아감

# CSR
FCP: 0.6s  LCP: 1.8s  TTI: 2.4s
SEO: 크롤러가 콘텐츠를 얻으려면 JS를 실행해야 함

자주 묻는 질문

이 데모 페이지는 실제로 무엇을 보여주는 건가요?

Next.js App Router 페이지가 서버에서 데이터를 가져와 첫 HTML 응답에 결과를 포함시키면서 동시에 올바른 다국어 라벨을 로드하는 방식을 보여주는 서버 사이드 렌더링(SSR) 참조 라우트입니다. 최종 사용자용 도구가 아니라 개발자를 위한 동작 확인용 테스트 페이지입니다.

데이터는 서버에서 가져오나요, 브라우저에서 가져오나요?

서버에서 가져옵니다. 페이지는 React Server Component 내부에서 serverApiFetch(src/lib/sign.ts의 서명 요청 헤더 포함)를 호출하므로, 브라우저는 이미 데이터가 포함된 HTML 페이지를 받게 됩니다. 첫 로딩 시 클라이언트 측 fetch는 발생하지 않습니다.

왜 가끔 오래된 데이터가 표시되나요?

Next.js는 revalidate 설정에 따라 SSR 응답을 캐시할 수 있습니다. 매 요청마다 최신 데이터가 필요하다면 'export const dynamic = "force-dynamic"'을 설정하거나 fetch에 {cache: 'no-store'}를 전달하세요. 데모 라우트는 예시를 단순하게 유지하기 위해 기본 동작을 사용합니다.

이 패턴을 자체 페이지에 복사해서 사용해도 되나요?

네, 그렇게 사용하라고 만든 것입니다. 이 라우트는 next-intl의 getTranslations와 서버 측 데이터 fetch를 결합하고 그 결과를 Client Component에 전달하여 상호작용을 구현하는 방법을 보여줍니다. layout.tsx와 page.tsx를 복사한 다음 데이터 소스만 교체하세요.

내부 API에도 요청 서명이 왜 필요한가요?

X-Timestamp / X-Nonce / X-Sign은 재전송 공격을 차단하고, 공개 웹에서 들어오는 요청이 실제로 신뢰된 클라이언트로부터 왔음을 보장합니다. 서명 키는 로그인 사용자의 경우 세션별로 발급되고, 그 외에는 기본값을 사용합니다. 구현 내용은 src/lib/sign.ts와 src/lib/fetch.ts를 참고하세요.

이 페이지가 프로덕션 빌드에도 포함되나요?

참조용으로 배포된 앱에 포함되어 있지만, 홈 페이지나 도구 목록에서 링크되지 않으며 사용자용 도구로 노출되지도 않습니다. 라우트 형태로 렌더링된 개발자 문서로 이해하시면 됩니다.

프로젝트 구조를 익히고 싶다면 어디부터 봐야 하나요?

이 페이지의 layout.tsx와 page.tsx부터 시작한 다음, src/i18n.ts(로케일 설정), src/i18n/request.ts(전역 번역 로딩), src/lib/load-page-messages.ts(페이지별 번역), src/lib/fetch.ts(서명 요청 래퍼)를 차례로 읽어보세요.