콘텐츠로 이동

Functions: after

Source URL: https://nextjs.org/docs/app/api-reference/functions/after

Copy page

Last updated February 20, 2026

after는 응답(또는 사전 렌더링)이 완료된 뒤에 실행할 작업을 예약할 수 있게 해 줍니다. 이는 로깅, 분석처럼 응답을 차단하면 안 되는 작업 및 부수 효과에 유용합니다.

Server Components(generateMetadata 포함), Server Functions, Route Handlers, Proxy에서 사용할 수 있습니다.

이 함수는 응답(또는 사전 렌더링)이 끝난 후 실행될 콜백을 받습니다:

app/layout.tsx

JavaScriptTypeScript

import { after } from 'next/server'
// Custom logging function
import { log } from '@/app/utils'
export default function Layout({ children }: { children: React.ReactNode }) {
after(() => {
// Execute after the layout is rendered and sent to the user
log()
})
return <>{children}</>
}

알아 두면 좋아요: after는 Dynamic API가 아니며, 이를 호출해도 라우트가 동적으로 변하지 않습니다. 정적 페이지에서 사용하면 콜백은 빌드 시점 또는 페이지가 재검증될 때 실행됩니다.

  • 응답(또는 사전 렌더링)이 완료된 뒤 실행될 콜백 함수.

after는 라우트에 설정된 플랫폼 기본값 또는 구성된 최대 기간 동안 실행됩니다. 플랫폼이 지원한다면 maxDuration 라우트 세그먼트 구성을 사용해 타임아웃 한도를 설정할 수 있습니다.

  • 응답이 정상적으로 완료되지 않아도 after는 실행됩니다. 오류가 발생하거나 notFound, redirect가 호출된 경우도 포함됩니다.
  • after 내부에서 호출되는 함수를 중복 제거하려면 React cache를 사용할 수 있습니다.
  • after는 다른 after 호출 안에 중첩할 수 있습니다. 예를 들어, 추가 기능을 붙이기 위해 after 호출을 감싸는 유틸리티 함수를 만들 수 있습니다.

cookies나 headers 같은 요청 API를 after 내부에서 사용할 수 있는지는 after가 어디에서 호출되는지에 따라 달라집니다.

Route Handlers, Server Functions에서는 after 콜백 안에서 cookies, headers를 직접 호출할 수 있습니다. 이는 변형이나 API 요청 뒤에 활동을 기록할 때 유용합니다. 예:

app/api/route.ts

JavaScriptTypeScript

import { after } from 'next/server'
import { cookies, headers } from 'next/headers'
import { logUserAction } from '@/app/utils'
export async function POST(request: Request) {
// Perform mutation
// ...
// Log user activity for analytics
after(async () => {
const userAgent = (await headers()).get('user-agent') || 'unknown'
const sessionCookie =
(await cookies()).get('session-id')?.value || 'anonymous'
logUserAction({ sessionCookie, userAgent })
})
return new Response(JSON.stringify({ status: 'success' }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})
}

Server Components(페이지, 레이아웃, generateMetadata 포함)에서는 after 내부에서 cookies, headers, 기타 Dynamic APIs를 사용할 수 없습니다. Next.js가 Partial Prerendering과 Cache Components를 지원하려면 컴포넌트 트리의 어떤 부분이 요청 데이터를 읽는지 알아야 하지만, after는 React 렌더링 라이프사이클 이후에 실행되기 때문입니다.

Server Component에서 after 콜백에 요청 데이터가 필요하다면 먼저 읽은 뒤 값을 전달하세요:

app/page.tsx

JavaScriptTypeScript

import { after } from 'next/server'
import { cookies, headers } from 'next/headers'
import { logUserAction } from '@/app/utils'
export default async function Page() {
// Read request data before `after` — this is allowed
// These calls will be read during the component's rendering lifecycle
const userAgent = (await headers()).get('user-agent') || 'unknown'
const sessionCookie =
(await cookies()).get('session-id')?.value || 'anonymous'
after(() => {
// Use the values read above
logUserAction({ sessionCookie, userAgent })
})
return <h1>My Page</h1>
}

Server Component에서 after 콜백 내부에서 cookies()나 headers()를 호출하면 런타임 오류가 발생합니다.

Cache Components를 사용할 때는 cookies, headers처럼 요청 데이터를 읽는 컴포넌트를 <Suspense>로 감싸야 페이지 나머지를 정적 셸로 사전 렌더링할 수 있습니다.

요청 데이터를 동적 컴포넌트에서 읽고 after에 전달하는 방식으로 이 패턴을 after와 결합할 수 있습니다:

app/page.tsx

JavaScriptTypeScript

import { Suspense } from 'react'
import { after } from 'next/server'
import { cookies } from 'next/headers'
import { logUserAction } from '@/app/utils'
export default function Page() {
return (
<>
<h1>Part of the static shell</h1>
<Suspense fallback={<p>Loading...</p>}>
<DynamicContent />
</Suspense>
</>
)
}
async function DynamicContent() {
const sessionCookie =
(await cookies()).get('session-id')?.value || 'anonymous'
// Schedule work after the response is sent
after(() => {
logUserAction({ sessionCookie })
})
return <p>Your session: {sessionCookie}</p>
}

이 예시에서 <h1>과 <Suspense> 폴백은 정적 셸에 포함됩니다. DynamicContent는 렌더링 중 쿠키를 읽고 클로저를 통해 after에 전달합니다. cookies() 호출이 after 콜백 외부(컴포넌트 렌더링 시)에 있기 때문에 제대로 동작합니다.

Deployment OptionSupported
Node.js serverYes
Docker containerYes
Static exportNo
AdaptersPlatform-specific

Next.js를 셀프 호스팅할 때 after 구성 방법을 알아보세요.

Reference: serverless 플랫폼에서 after 지원

서버리스 환경에서 after를 사용하려면 응답이 전송된 뒤 비동기 작업이 완료될 때까지 기다려야 합니다. Next.js와 Vercel에서는 waitUntil에 전달된 모든 Promise가 완료될 때까지 서버리스 호출 수명을 연장하는 waitUntil(promise)라는 기본기를 사용합니다.

사용자도 after를 실행할 수 있도록 하려면 유사하게 동작하는 waitUntil 구현을 제공해야 합니다.

after가 호출되면 Next.js는 다음과 같이 waitUntil에 접근합니다:

const RequestContext = globalThis[Symbol.for('@next/request-context')]
const contextValue = RequestContext?.get()
const waitUntil = contextValue?.waitUntil

이는 globalThis[Symbol.for('@next/request-context')]가 다음과 같은 객체를 포함해야 함을 의미합니다:

type NextRequestContext = {
get(): NextRequestContextValue | undefined
}
type NextRequestContextValue = {
waitUntil?: (promise: Promise<any>) => void
}

구현 예시는 다음과 같습니다.

import { AsyncLocalStorage } from 'node:async_hooks'
const RequestContextStorage = new AsyncLocalStorage<NextRequestContextValue>()
// Define and inject the accessor that next.js will use
const RequestContext: NextRequestContext = {
get() {
return RequestContextStorage.getStore()
},
}
globalThis[Symbol.for('@next/request-context')] = RequestContext
const handler = (req, res) => {
const contextValue = { waitUntil: YOUR_WAITUNTIL }
// Provide the value
return RequestContextStorage.run(contextValue, () => nextJsHandler(req, res))
}
VersionChanges
v15.1.0after가 안정화되었습니다.
v15.0.0-rcunstable_after가 도입되었습니다.

Was this helpful?

supported.

Send