# 쿠키 보안 옵션 (httpOnly, Secure, SameSite)
## 빠른 비교표
| 옵션 | 목적 | 기본값 | 설정 | 효과 |
|——|——|——–|——|——|
| **httpOnly** | XSS 공격 방지 | false | `httpOnly: true` | JavaScript 접근 불가 |
| **Secure** | 중간자 공격 방지 | false | `secure: true` | HTTPS만 전송 |
| **SameSite** | CSRF 공격 방지 | Lax | `sameSite: ‘strict’` | 다른 사이트 요청 차단 |
—
## 상세 설명표
### 1. httpOnly
| 항목 | 설명 |
|——|——|
| **용도** | XSS (Cross-Site Scripting) 공격 방지 |
| **설정** | `res.cookie(‘token’, val, { httpOnly: true })` |
| **기본값** | false (설정하지 않으면 JavaScript 접근 가능) |
| **효과** | JavaScript에서 `document.cookie`로 접근 불가 |
| **읽기** | ❌ JavaScript 불가 / ✅ HTTP 요청에 자동 포함 |
| **쓰기** | ❌ JavaScript에서 설정 불가 |
| **공격 방어** | 악성 스크립트가 실행되어도 쿠키 탈취 불가 |
| **권장** | ⭐⭐⭐⭐⭐ (Refresh Token 저장 시 필수) |
| **예시** | `httpOnly: true` |
#### httpOnly 예시
“`javascript
// 서버
res.cookie(‘refreshToken’, token, { httpOnly: true });
// 클라이언트 – 접근 시도
document.cookie; // ❌ 쿠키 보이지 않음
// “”
// 하지만 HTTP 요청에는 자동 포함
GET /api/user HTTP/1.1
Cookie: refreshToken=xyz789 // ✅ 자동 포함
// 서버에서는 받을 수 있음
req.cookies.refreshToken // ✅ “xyz789”
“`
—
### 2. Secure
| 항목 | 설명 |
|——|——|
| **용도** | 중간자 공격(Man-in-the-Middle) 방지 |
| **설정** | `res.cookie(‘token’, val, { secure: true })` |
| **기본값** | false (HTTP도 전송) |
| **효과** | HTTPS 연결에서만 쿠키 전송 |
| **HTTP** | ❌ HTTP 요청에 쿠키 포함 안 됨 |
| **HTTPS** | ✅ HTTPS 요청에 쿠키 포함 |
| **공격 방어** | 암호화되지 않은 연결로 쿠키 탈취 방지 |
| **권장** | ⭐⭐⭐⭐⭐ (프로덕션 필수) |
| **예시** | `secure: process.env.NODE_ENV === ‘production’` |
#### Secure 예시
“`javascript
// 서버
res.cookie(‘token’, token, { secure: true });
// 개발 환경 (localhost:3000 – HTTP)
GET http://localhost:3000/api/user
Cookie: (없음) // ❌ 전송 안 됨
// 프로덕션 (https://api.example.com – HTTPS)
GET https://api.example.com/api/user
Cookie: token=xyz789 // ✅ 전송됨
“`
—
### 3. SameSite
| 항목 | 설명 |
|——|——|
| **용도** | CSRF (Cross-Site Request Forgery) 공격 방지 |
| **설정** | `res.cookie(‘token’, val, { sameSite: ‘strict’ })` |
| **기본값** | ‘Lax’ (일부 크로스 사이트 요청에 포함) |
| **값 – Strict** | ❌ 모든 크로스 사이트 요청에서 쿠키 미포함 (가장 안전) |
| **값 – Lax** | ⚠️ 안전한 메서드(GET)의 크로스 사이트만 포함 (기본값) |
| **값 – None** | ✅ 모든 크로스 사이트 요청에 포함 (Secure 필수) |
| **공격 방어** | 악의적인 웹사이트에서의 자동 요청 차단 |
| **권장** | ⭐⭐⭐⭐⭐ (‘strict’ 또는 ‘lax’ 권장) |
| **예시** | `sameSite: ‘strict’` |
#### SameSite 값 비교
| SameSite | 같은 사이트 | 크로스 사이트 (GET) | 크로스 사이트 (POST) | 보안 |
|———|———–|——————|——————-|——|
| **Strict** | ✅ | ❌ | ❌ | ⭐⭐⭐ (매우 강함) |
| **Lax** (기본) | ✅ | ✅ | ❌ | ⭐⭐ (중간) |
| **None** | ✅ | ✅ | ✅ | ⭐ (약함, Secure 필수) |
#### SameSite 예시
“`javascript
// 서버
res.cookie(‘token’, token, { sameSite: ‘strict’ });
// 정상 요청 (같은 사이트)
GET https://example.com/api/user
Cookie: token=xyz789 // ✅ 포함됨
// 악의적인 요청 (다른 사이트에서)
// hacker.com에서 example.com으로 자동 요청
GET https://example.com/api/user
Cookie: token=xyz789 // ❌ Strict이면 미포함
“`
—
## CSRF 공격 예시 (SameSite로 방어)
### SameSite 없을 때 (위험)
“`html
GET https://bank.com/api/transfer?amount=1000&to=hacker
Cookie: sessionToken=xyz789 // ❌ 자동 포함 (위험!)
“`
### SameSite: strict 설정 시 (안전)
“`html
GET https://bank.com/api/transfer?amount=1000&to=hacker
Cookie: (없음) // ✅ 쿠키 미포함 (안전!)
“`
—
## 실제 구현 코드
### 개발 환경 설정
“`javascript
// server.js
app.post(‘/api/login’, (req, res) => {
const token = jwt.sign({ userId: 1 }, SECRET);
// 개발/프로덕션 구분
const isProduction = process.env.NODE_ENV === ‘production’;
res.cookie(‘refreshToken’, token, {
httpOnly: true, // ✅ XSS 방지
secure: isProduction, // ✅ HTTPS에서만 전송 (프로덕션)
sameSite: ‘strict’, // ✅ CSRF 방지
maxAge: 7 * 24 * 60 * 60 * 1000 // 7일
});
res.json({ accessToken: token });
});
“`
### 프로덕션 환경 권장 설정
“`javascript
res.cookie(‘refreshToken’, token, {
httpOnly: true, // 필수
secure: true, // HTTPS만
sameSite: ‘strict’, // 크로스 사이트 차단
domain: ‘example.com’, // 특정 도메인만
path: ‘/’, // 루트 경로
maxAge: 7 * 24 * 60 * 60 * 1000
});
“`
—
## 공격 유형별 방어 정리
| 공격 유형 | 설명 | 방어 방법 | 옵션 |
|———-|——|———|——|
| **XSS** | JavaScript로 쿠키 탈취 | JavaScript 접근 차단 | `httpOnly: true` |
| **중간자 공격** | 암호화 없는 연결에서 탈취 | 암호화 통신만 허용 | `secure: true` |
| **CSRF** | 다른 사이트에서 자동 요청 | 크로스 사이트 요청 차단 | `sameSite: ‘strict’` |
—
## 요약 표
### 각 옵션의 필요성
“`
httpOnly
├─ 보호: XSS 공격
├─ 원리: JavaScript 접근 불가
├─ 자동 전송: ✅ (HTTP 요청에 자동 포함)
└─ 필수도: ⭐⭐⭐⭐⭐
Secure
├─ 보호: 중간자 공격
├─ 원리: HTTPS만 전송
├─ 자동 전송: ✅ (HTTPS 연결에서만)
└─ 필수도: ⭐⭐⭐⭐⭐
SameSite
├─ 보호: CSRF 공격
├─ 원리: 크로스 사이트 요청 차단
├─ 자동 전송: ⚠️ (설정값에 따라 다름)
└─ 필수도: ⭐⭐⭐⭐
“`
—
## 결론: 권장 설정
“`javascript
// ✅ 프로덕션 환경 최상의 보안
res.cookie(‘refreshToken’, token, {
httpOnly: true,
secure: true,
sameSite: ‘strict’,
maxAge: 7 * 24 * 60 * 60 * 1000
});
// ✅ 개발 환경 (localhost)
res.cookie(‘refreshToken’, token, {
httpOnly: true,
secure: false, // localhost에서는 필요 없음
sameSite: ‘lax’, // 개발 편의성
maxAge: 7 * 24 * 60 * 60 * 1000
});
“`