TechFeedTechFeed
Security

프록시, matcher, 서버 액션, 관리자 경로 | 화면만 잠그면 저장이 열릴까?

관리 화면이 로그인으로 튕겨도 서버 액션 POST는 남을 수 있다. 넥스트 16 프록시는 미들웨어 자리이고, matcher가 api나 그 경로를 빼면 그 칸의 액션은 안 탄다. 페이지 권한은 화면만 가리고, 액션 안에서 세션을 다시 본다. 개발자, Next.js, 보안, API, 백엔드, 프론트엔드, 서버 액션 기준으로 matcher와 액션 칸만 보고 세임사이트 글, 폼 훅 글과 자리를 섞지 않는다. 2026년 8월 공식 문서.

by

어제 관리 화면이 로그인으로 튕겼는데, 같은 경로로 POST를 보내니 문의 행이 지워졌습니다. 프록시는 GET 화면만 막았고, 매처가 api와 그 경로를 빼면 서버 액션은 그 칸을 안 탑니다. 넥스트 16부터 미들웨어 파일은 프록시로 이름이 바뀝니다. 문서는 권한을 서버 함수 안에서 다시 보라고 적습니다.


저는 12개 사이트 파트너십 관리를 쿠키만으로 잠근 날이 있습니다. 화면은 막혔고 저장은 열렸습니다. 쿠키 세임사이트는 세임사이트 글, 폼 이중 제출은 폼 훅 글입니다. 여기는 매처와 액션 칸만 봅니다.


숫자는 2026년 8월 넥스트 프록시 파일 문서데이터 보안 가이드 기준입니다.


화면이 로그인으로 가도 저장은 별 입구다

관리 페이지가 로그인으로 보내도, 그 페이지에 붙은 서버 액션은 따로 열립니다. 페이지 권한은 화면만 가리고, 액션은 직접 POST로 들어옵니다.


파트너십 목록을 쿠키 없으면 로그인으로 돌렸습니다. 그날 삭제 버튼은 화면에서 안 보였습니다. 그런데 액션 아이디로 POST를 넣으니 행이 사라졌습니다. 서버 액션 자리 자체는 서버 액션 글입니다. 오늘은 프록시가 그 입구를 안 닫는 칸입니다.


막는 것못 막는 것오늘 할 일
프록시매처에 걸린 GET 화면, 리다이렉트매처 밖 경로, 액션 안 권한관리 경로를 매처에 넣고, 쿠키만 본다
레이아웃첫 페인트의 껍데기클라이언트 이동, 중첩 세그먼트, 액션권한을 레이아웃에만 두지 않는다
페이지그 HTML이 그려질 때같은 파일의 서버 액션 POST액션 안에서 세션을 다시 본다
서버 액션직접 POST로 오는 저장, 삭제화면 리다이렉트만으로는 안 닫힘세션, 역할, 행 주인을 여기서 본다
라우트 핸들러app/api 아래 GET, POST매처가 api를 빼면 프록시가 안 탐핸들러 안에서도 세션을 본다

넥스트 데이터 보안 문서는 페이지 권한 검사가 그 안의 서버 액션까지 이어지지 않는다고 적습니다. 액션은 공개 API와 같이 취급합니다. 헤더 칸은 보안 헤더 글입니다. 자리는 섞지 않습니다.


화면이 비어도 액션은 살아 있습니다 | 버튼을 숨기거나 로그인으로 보내도, 액션 아이디를 아는 POST는 그대로 들어옵니다. 문서도 쓰이지 않는 액션만 빌드에서 지운다고 적습니다.


매처가 api를 빼면 그 칸은 안 돈다

매처가 없으면 프록시는 정적 파일까지 탑니다. 그래서 많은 예가 api와 정적 경로를 빼습니다. 그 순간 app/api 아래는 프록시 밖입니다.


저는 문서 예제의 부정 매처를 그대로 붙인 적이 있습니다. 관리 화면은 막히고, 같은 권한의 제이슨 핸들러는 열렸습니다. 카카오 콜백 주소는 터널 글입니다. 여기는 매처가 빼는 문자열만 봅니다.


문서 매처 값은 빌드 때 상수여야 합니다. 변수로 넣으면 무시됩니다. 경로는 슬래시로 시작하고, 이름 매개변수 별표는 그 아래를 포함합니다. 대시보드만 적고 하위 경로를 includes로 비교하면, 설정 페이지는 빠져 나갑니다.


문서 예처럼 api를 빼면 그 칸의 프록시는 안 돈다
// https://nextjs.org/docs/app/api-reference/file-conventions/proxy // 이 매처는 예제일 뿐, 관리 API를 잠그지 않는다 export const config = { matcher: [ '/((?!api|_next/static|_next/image|.*\\.png$).*)', ], } // 관리 화면과 그 아래만 프록시에 태운다 export const configAdmin = { matcher: ['/admin/:path*', '/partnership/:path*'], }
넥스트 프록시 매처가 관리 화면과 API 경로를 다르게 거르는 흐름
매처가 api를 빼면 그 칸의 POST는 프록시를 안 탄다

서버 액션은 그 페이지 POST라 빼면 같이 빠진다

서버 함수는 별 라우트가 아닙니다. 쓰인 페이지로 가는 POST입니다. 매처가 그 경로를 빼면 액션도 프록시를 안 탑니다.


문서는 매처를 바꾸거나 액션을 다른 경로로 옮기면 프록시 커버가 조용히 사라진다고 적습니다. 그래서 각 서버 함수 안에서 인증과 권한을 다시 보라고 합니다. 저는 삭제 액션을 공통 파일로 옮긴 뒤, 매처가 그 화면만 보고 있던 줄을 나중에 찾았습니다.


소유하지 않은 행 아이디를 그대로 지우면 아이도르입니다. 세션이 있어도 그 행의 주인을 봅니다. 업로드 앞 바이트는 매직 바이트 글입니다. 액션 권한과 자리를 섞지 않습니다.


페이지 권한이 있어도 액션 안에서 세션과 행 주인을 다시 본다
// https://nextjs.org/docs/app/guides/data-security 'use server' import { cookies } from 'next/headers' import { redirect } from 'next/navigation' import { eq } from 'drizzle-orm' import { decrypt } from '@/app/lib/session' import { db } from '@/app/lib/db' import { inquiry } from '@/app/schema' export async function deleteInquiry(id) { const raw = (await cookies()).get('session')?.value const session = await decrypt(raw) if (!session?.userId) { redirect('/login') } const row = await db.query.inquiry.findFirst({ where: (t, { eq: e }) => e(t.id, id), }) if (!row || row.ownerId !== session.userId) { throw new Error('forbidden') } await db.delete(inquiry).where(eq(inquiry.id, id)) return { ok: true } }

페이지 리다이렉트는 액션을 닫지 않습니다 | 데이터 보안 문서가 강조한 줄입니다. 화면에서 로그인을 보내도, 액션 함수는 별 입구입니다. 세션 확인을 액션 첫 줄에 둡니다.


레이아웃에서 숨겨도 액션은 산다

레이아웃은 클라이언트 이동 때 다시 안 그려질 수 있습니다. 중첩 세그먼트와 액션은 레이아웃이 가렸다고 멈추지 않습니다.


인증 문서는 공유 레이아웃에서 세션만 보고 자식을 숨기는 패턴을 말립니다. 넥스트는 입구가 여러 개라, 껍데기를 비워도 안쪽 세그먼트와 서버 액션이 남습니다. 폼 버튼 잠금은 폼 훅 글입니다. 오늘은 레이아웃이 권한 칸이 아닌 이유입니다.


정적 경로를 여러 사용자가 나눠 보면, 빌드 때 데이터가 들어갑니다. 그때만 프록시가 화면 입구를 막는 데 쓸모가 있습니다. 저장은 여전히 액션입니다.


레이아웃이 관리 화면을 가려도 서버 액션 POST가 따로 들어오는 그림
레이아웃 숨김은 화면만 가린다. 액션은 페이지 POST다

프록시는 모든 경로와 프리페치에도 탑니다. 문서는 쿠키의 세션만 보고, 디비 조회는 넣지 말라고 합니다. 느린 조회는 프록시 자리가 아닙니다.


인증 가이드는 프록시를 낙관 확인으로 둡니다. 화면을 로그인으로 보내는 빠른 칸입니다. 진짜 권한은 데이터 접근 층에서 세션을 풀고, 필요하면 디비와 맞춰 봅니다. 시크릿 자리는 환경변수 글입니다.


프록시 런타임은 노드입니다. 설정으로 엣지를 고르면 에러가 납니다. 16.0부터 기본이 노드고, 세션 라이브러리가 노드에서 도는지 먼저 봅니다. 응답 뒤 메일은 after 글입니다. waitUntil 은 프록시 이벤트에도 있지만, 권한 칸과 섞지 않습니다.


프록시는 쿠키만 보고 관리 경로를 로그인으로 보낸다
// https://nextjs.org/docs/app/guides/authentication import { NextResponse } from 'next/server' import { decrypt } from '@/app/lib/session' export default async function proxy(req) { const path = req.nextUrl.pathname const isAdmin = path.startsWith('/admin') || path.startsWith('/partnership') const raw = req.cookies.get('session')?.value const session = await decrypt(raw) if (isAdmin && !session?.userId) { return NextResponse.redirect(new URL('/login', req.nextUrl)) } return NextResponse.next() } export const config = { matcher: ['/admin/:path*', '/partnership/:path*', '/login'], }

프록시만으로 저장을 잠그지 않습니다 | 문서는 권한의 대부분을 데이터 가까이에 두라고 합니다. 프록시는 화면 입구, 액션은 저장 입구입니다.


미들웨어 파일을 프록시로 옮기는 한 줄

16.0부터 미들웨어 파일 규약은 폐기입니다. 이름은 프록시입니다. 동작은 같고, 런타임 기본은 노드입니다.


문서가 이름을 바꾼 이유는 익스프레스 미들웨어와 헷갈리지 말라는 것입니다. 네트워크 앞단이고, 마지막 수단이라고 적습니다. 코드모드는 파일 이름과 함수 이름을 바꿉니다. 매처와 액션 권한은 코드모드가 안 고칩니다.


서버 액션은 오리진과 호스트가 같아야 합니다. 리버스 프록시 뒤면 allowedOrigins 에 그 호스트를 적습니다. 2026년 6월 설정 문서는 아직 experimental 칸입니다. 세임사이트 쿠키는 세임사이트 글입니다. 오늘은 파일 이름과 매처만 옮깁니다.


미들웨어 파일을 프록시로 바꾸고, 오리진은 설정에 적는다
// https://nextjs.org/docs/messages/middleware-to-proxy npx @next/codemod@canary middleware-to-proxy . // next.config.js // https://nextjs.org/docs/app/api-reference/config/next-config-js/serverActions module.exports = { experimental: { serverActions: { allowedOrigins: ['tech.ambitstock.com'], }, }, }
미들웨어 파일을 프록시 파일로 옮기고 매처 경로를 적는 체크 화면
파일 이름만 바꿔도 매처와 액션 권한은 그대로다

오늘 액션 하나에 세션 확인을 넣는다

오늘 할 일은 삭제 액션 첫 줄에 세션 확인입니다. 프록시 매처에 관리 경로를 넣고, api를 뺀 채 핸들러를 믿던 줄은 지웁니다. 레이아웃 숨김은 그대로 두지 않습니다.


저는 파트너십 삭제부터 넣었습니다. 화면이 로그인으로 가도 POST가 막히는지 curl로 한 번 더 봤습니다. 문의 봇은 턴스타일 글입니다. 프록시와 액션 칸만 닫으면 됩니다.


오늘 한 줄 | 화면 잠금은 프록시, 저장 잠금은 액션입니다. 매처가 빼는 경로는 그 안의 POST도 빠집니다.


참고 자료


내부 연계: 서버 액션, 세임사이트, 폼 훅, 보안 헤더, 환경변수, 매직 바이트, 터널, after


프록시 파일과 액션 첫 줄이 표보다 우선입니다. 위 동작은 2026년 8월 공개 문서 기준입니다.


자주 묻는 질문

관리 화면이 로그인으로 가면 삭제도 막히나?

아닙니다. 페이지 권한은 그 HTML만 가립니다. 서버 액션은 같은 경로의 POST라 별 입구입니다. 데이터 보안 문서가 액션 안에서 세션을 다시 보라고 적습니다. 로그인 없이 POST를 한 번 넣어 보면 바로 드러납니다.


매처에서 api를 빼도 되나?

정적 파일과 이미지 최적화를 빼는 건 맞습니다. api를 빼면 그 아래 핸들러는 프록시를 안 탑니다. 핸들러 안에서 세션을 보거나, 관리 API 경로를 매처에 따로 넣습니다. 문서 부정 매처를 그대로 붙이면 그 칸이 열립니다.


미들웨어 파일을 그대로 둬도 되나?

16.0부터 미들웨어 파일 규약은 폐기입니다. 코드모드가 파일과 함수 이름을 프록시로 바꿉니다. 동작은 같고 런타임 기본은 노드입니다. 이름만 바꿔도 매처와 액션 권한은 그대로라, 액션 첫 줄은 따로 손봅니다.


레이아웃에서 세션을 보면 충분한가?

충분하지 않습니다. 레이아웃은 클라이언트 이동 때 다시 안 그려질 수 있고, 중첩 세그먼트와 액션을 멈추지 않습니다. 인증 문서는 껍데기를 비우는 패턴을 말립니다. 페이지와 액션, 데이터 접근 층에서 다시 봅니다.


프록시에서 디비로 세션을 확인하면 안 되나?

문서는 프리페치까지 프록시가 타므로 쿠키만 보라고 합니다. 디비 조회는 느려지고, 프록시는 권한의 전부가 아닙니다. 화면 리다이렉트는 쿠키, 저장은 액션과 데이터 접근 층입니다.


오리진 설정과 세임사이트는 같은가?

다릅니다. 서버 액션은 오리진과 호스트가 다르면 요청을 끊습니다. 리버스 프록시 뒤면 allowedOrigins 를 적습니다. 쿠키 SameSite 는 브라우저가 다른 사이트 요청에 쿠키를 붙이는 칸이라 세임사이트 글입니다.


프록시matcher서버 액션관리자 경로넥스트보안개발자Next.jsAPI백엔드프론트엔드미들웨어권한

함께 보면 좋은 문제 해결

EXPLORE / Security

이어서 읽어보기

전체 토픽 둘러보기