refactor(WEB): Server Action 공통화 및 보안 강화

- executeServerAction 공통 유틸 도입으로 actions.ts 대폭 간소화 (50+개 파일)
- sanitize 유틸 추가 (XSS 방지)
- middleware CSP 헤더 추가 및 Open Redirect 방지
- 프록시 라우트 로깅 개발환경 한정으로 변경
- 프로덕션 불필요 console.log 제거

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-02-09 16:14:06 +09:00
parent d014227e9c
commit 55e0791e16
85 changed files with 7211 additions and 17638 deletions

View File

@@ -285,15 +285,21 @@ export async function middleware(request: NextRequest) {
// 7⃣ 기본 정책: 모든 페이지는 인증 필요
// guestOnlyRoutes와 publicRoutes가 아닌 모든 경로는 보호됨
if (!isAuthenticated) {
console.log(`[Auth Required] Redirecting to /login from ${pathname}`);
if (process.env.NODE_ENV === 'development') {
console.log(`[Auth Required] Redirecting to /login from ${pathname}`);
}
const url = new URL('/login', request.url);
url.searchParams.set('redirect', pathname);
// Open Redirect 방지: 내부 경로만 허용
const isInternalPath = pathname.startsWith('/') && !pathname.startsWith('//') && !pathname.includes('://');
if (isInternalPath) {
url.searchParams.set('redirect', pathname);
}
return NextResponse.redirect(url);
}
// 8⃣ 인증 모드 로깅 (디버깅용)
if (isAuthenticated) {
// 8⃣ 인증 모드 로깅 (디버깅용 - 개발환경만)
if (process.env.NODE_ENV === 'development' && isAuthenticated) {
console.log(`[Authenticated] Mode: ${authMode}, Path: ${pathname}`);
}
@@ -305,6 +311,17 @@ export async function middleware(request: NextRequest) {
intlResponse.headers.set('X-Content-Type-Options', 'nosniff');
intlResponse.headers.set('X-Frame-Options', 'DENY');
intlResponse.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
intlResponse.headers.set('Content-Security-Policy', [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://maps.googleapis.com",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: blob: https:",
"font-src 'self' data: https://fonts.gstatic.com",
"connect-src 'self' https://maps.googleapis.com",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'",
].join('; '));
// Bot 로깅 (모니터링용)
if (isBotRequest) {