DevToolBox무료
블로그

HTTP 헤더 완전 가이드: 요청, 응답 및 보안 헤더

12분by DevToolBox

HTTP 헤더는 웹의 보이지 않는 뼈대입니다. 이 가이드는 요청 헤더, 응답 헤더, 보안 헤더, CORS 설정을 다룹니다.

필수 요청 헤더

요청 헤더는 클라이언트에서 서버로 전송되며 요청에 대한 메타데이터를 전달합니다.

// Common HTTP Request Headers

GET /api/users HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Content-Type: application/json
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
Cache-Control: no-cache
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d"
If-Modified-Since: Thu, 01 Jan 2026 00:00:00 GMT
Origin: https://myapp.com
Referer: https://myapp.com/dashboard
X-Request-ID: 550e8400-e29b-41d4-a716-446655440000

// Setting headers with fetch API
const response = await fetch('https://api.example.com/users', {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Accept': 'application/json',
    'X-Request-ID': crypto.randomUUID(),
  },
});

HTTP 보안 헤더

보안 헤더는 XSS, 클릭재킹, 중간자 공격으로부터 사용자를 보호합니다.

// Essential Security Headers for Express.js
import express from 'express';

const app = express();

app.use((req, res, next) => {
  // Prevent XSS attacks
  res.setHeader('X-XSS-Protection', '1; mode=block');

  // Prevent MIME type sniffing
  res.setHeader('X-Content-Type-Options', 'nosniff');

  // Prevent clickjacking
  res.setHeader('X-Frame-Options', 'DENY');

  // Force HTTPS for 1 year (include subdomains)
  res.setHeader(
    'Strict-Transport-Security',
    'max-age=31536000; includeSubDomains; preload'
  );

  // Content Security Policy
  res.setHeader(
    'Content-Security-Policy',
    [
      "default-src 'self'",
      "script-src 'self' 'nonce-{RANDOM}' https://cdn.example.com",
      "style-src 'self' 'unsafe-inline'",
      "img-src 'self' data: https:",
      "font-src 'self'",
      "connect-src 'self' https://api.example.com",
      "frame-ancestors 'none'",
    ].join('; ')
  );

  // Control referrer information
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');

  // Control browser features
  res.setHeader(
    'Permissions-Policy',
    'camera=(), microphone=(), geolocation=(self)'
  );

  next();
});

CORS: 교차 출처 리소스 공유

CORS는 서버가 리소스에 접근할 수 있는 출처를 지정할 수 있게 합니다.

// CORS Configuration — Express.js

import cors from 'cors';

// Simple CORS for public API
app.use(cors({
  origin: '*',
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
}));

// Strict CORS for production
const allowedOrigins = [
  'https://myapp.com',
  'https://www.myapp.com',
  process.env.NODE_ENV === 'development' ? 'http://localhost:3000' : null,
].filter(Boolean);

app.use(cors({
  origin: (origin, callback) => {
    // Allow requests with no origin (mobile apps, curl, etc.)
    if (!origin) return callback(null, true);

    if (allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error(`CORS: Origin ${origin} not allowed`));
    }
  },
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization', 'X-Request-ID'],
  exposedHeaders: ['X-Total-Count', 'X-RateLimit-Remaining'],
  credentials: true,       // Allow cookies
  maxAge: 86400,           // Cache preflight for 24 hours
}));

// Manual preflight handling
app.options('*', cors()); // Enable pre-flight across all routes

캐시 헤더

올바른 캐시 헤더는 브라우저와 CDN이 응답을 재사용하여 성능을 크게 향상시킵니다.

// HTTP Caching Headers

// 1. Cache-Control directives
Cache-Control: no-store          // Never cache (sensitive data)
Cache-Control: no-cache          // Revalidate before using cache
Cache-Control: private           // Browser cache only (not CDN)
Cache-Control: public, max-age=31536000  // Cache for 1 year (immutable assets)
Cache-Control: public, max-age=3600, stale-while-revalidate=60

// 2. ETag for conditional requests (server generates a hash of the content)
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d"
// Client sends back on subsequent requests:
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d"
// Server responds 304 Not Modified if unchanged

// 3. Last-Modified
Last-Modified: Thu, 23 Feb 2026 10:00:00 GMT
If-Modified-Since: Thu, 23 Feb 2026 10:00:00 GMT

// Setting cache headers in Next.js
export async function GET() {
  return new Response(JSON.stringify(data), {
    headers: {
      'Content-Type': 'application/json',
      'Cache-Control': 'public, max-age=3600, stale-while-revalidate=60',
      'ETag': `"${hash(data)}"`,
    },
  });
}

// Strategy by asset type:
// HTML pages:     Cache-Control: no-cache (always revalidate)
// CSS/JS bundles: Cache-Control: public, max-age=31536000, immutable
// API responses:  Cache-Control: private, no-cache
// Images:         Cache-Control: public, max-age=86400

자주 묻는 질문

Authorization과 Authentication 헤더의 차이점은?

HTTP에는 전용 Authentication 헤더가 없습니다. 자격 증명은 Authorization 헤더를 통해 전송됩니다.

CORS 프리플라이트가 실패하는 이유는?

서버가 올바른 Access-Control-Allow-* 응답 헤더를 반환하지 않으면 OPTIONS 프리플라이트가 실패합니다.

Content-Security-Policy 헤더란?

CSP는 브라우저에 어떤 콘텐츠 소스가 신뢰할 수 있는지 알려주는 강력한 보안 헤더입니다.

HTTP 헤더로 HTTPS를 강제하는 방법은?

Strict-Transport-Security(HSTS) 헤더를 max-age=31536000으로 사용하세요.

관련 도구

𝕏 Twitterin LinkedIn
도움이 되었나요?

최신 소식 받기

주간 개발 팁과 새 도구 알림을 받으세요.

스팸 없음. 언제든 구독 해지 가능.

Try These Related Tools

🔓CORS Tester

Related Articles

REST API 설계 가이드: 2026년 모범 사례

견고한 REST API 설계 종합 가이드: 리소스 명명, HTTP 메서드, 페이지네이션, 에러 처리, 인증, 캐싱, OpenAPI.

JWT 인증: 완벽 구현 가이드

JWT 인증을 처음부터 구현. 토큰 구조, 액세스 토큰과 리프레시 토큰, Node.js 구현, 클라이언트 측 관리, 보안 모범 사례, Next.js 미들웨어.

CORS 에러 해결 완벽 가이드

CORS 에러를 단계별로 해결하세요. Access-Control-Allow-Origin, preflight, credentials, 서버 설정을 다룹니다.