HTTP와 HTTPS의 차이점
중요도: ⭐⭐⭐⭐⭐
웹 보안의 기본이 되는 핵심 개념입니다.
기본 개념
HTTP (HyperText Transfer Protocol)
HTTP는 서버/클라이언트 모델을 따라 데이터를 주고받기 위한 프로토콜입니다.
HTTPS (HTTP Secure)
HTTPS는 HTTP에 데이터 암호화가 추가된 프로토콜입니다.
HTTP의 문제점
1. 평문 통신으로 인한 도청 가능
HTTP는 모든 통신이 평문으로 이루어져 중간자 공격(Man-in-the-Middle Attack)에 취약합니다.
// HTTP 요청 예시 (평문)
GET /api/users HTTP/1.1
Host: example.com
Authorization: Bearer abc123token
Content-Type: application/json
{
"username": "user123",
"password": "mypassword"
}
// 이 모든 정보가 네트워크를 통해 평문으로 전송됨2. 통신 상대 확인 불가능 (위장 가능)
// 악의적인 서버가 정상 서버로 위장 가능
// 클라이언트는 실제 서버인지 확인할 방법이 없음
fetch("http://fake-bank.com/api/login", {
method: "POST",
body: JSON.stringify({ username, password }),
});3. 완전성 증명 불가능 (변조 가능)
// 중간에서 응답 데이터 변조 가능
// 원본: { balance: 10000 }
// 변조: { balance: 0 }
// 클라이언트는 변조 여부를 알 수 없음HTTPS의 특징
1. 데이터 암호화
SSL/TLS 프로토콜을 사용하여 데이터를 암호화합니다.
// HTTPS는 전송 계층에서 암호화
// 클라이언트 ↔ [TLS 암호화] ↔ 서버
// 실제 전송되는 데이터는 암호화됨
// 예: "Hello World" → "A1B2C3D4E5F6..."2. 서버 신원 확인
// SSL/TLS 인증서를 통해 서버 신원 확인
const checkCertificate = () => {
// 브라우저가 자동으로 수행
// 1. 인증서 유효성 검사
// 2. 인증서 발급기관(CA) 신뢰성 확인
// 3. 도메인 일치 여부 확인
// 4. 인증서 만료일 확인
};3. 데이터 무결성 보장
// MAC (Message Authentication Code)으로 데이터 무결성 확인
// 데이터가 전송 중에 변조되면 MAC 값이 달라져 탐지 가능TLS/SSL 핸드셰이크 과정
1. Client Hello
- 지원하는 TLS 버전, 암호화 스위트 목록 전송
2. Server Hello
- 선택된 TLS 버전, 암호화 스위트 전송
- 서버 인증서 전송
3. Certificate Verification
- 클라이언트가 서버 인증서 검증
4. Key Exchange
- 대칭키 생성을 위한 키 교환
5. Finished
- 핸드셰이크 완료, 암호화 통신 시작실제 구현 예시
Node.js HTTPS 서버
const https = require("https");
const fs = require("fs");
// SSL 인증서 로드
const options = {
key: fs.readFileSync("private-key.pem"),
cert: fs.readFileSync("certificate.pem"),
};
// HTTPS 서버 생성
https
.createServer(options, (req, res) => {
res.writeHead(200, {
"Content-Type": "application/json",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
});
res.end(
JSON.stringify({
message: "Secure connection established",
encrypted: true,
}),
);
})
.listen(443, () => {
console.log("HTTPS Server running on port 443");
});클라이언트에서 HTTPS 요청
// 최신 브라우저는 기본적으로 HTTPS 우선
fetch("https://api.example.com/users", {
method: "GET",
headers: {
Authorization: "Bearer token",
"Content-Type": "application/json",
},
})
.then((response) => {
// connection.encrypted로 암호화 상태 확인 가능 (Node.js)
console.log("Secure connection:", response.url.startsWith("https://"));
return response.json();
})
.catch((error) => {
console.error("HTTPS request failed:", error);
});HTTPS 보안 헤더
HSTS (HTTP Strict Transport Security)
// 서버 응답 헤더
app.use((req, res, next) => {
// HTTPS로만 접속하도록 강제
res.setHeader(
"Strict-Transport-Security",
"max-age=31536000; includeSubDomains; preload",
);
next();
});Content Security Policy (CSP)
app.use((req, res, next) => {
res.setHeader(
"Content-Security-Policy",
"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'",
);
next();
});성능 고려사항
TLS 핸드셰이크 오버헤드
// HTTP/2를 통한 성능 개선
const http2 = require("http2");
const server = http2.createSecureServer({
key: fs.readFileSync("private-key.pem"),
cert: fs.readFileSync("certificate.pem"),
});
// 멀티플렉싱으로 여러 요청을 동시에 처리
server.on("stream", (stream, headers) => {
stream.respond({
":status": 200,
"content-type": "text/html",
});
stream.end("<h1>HTTP/2 + HTTPS</h1>");
});인증서 캐싱
// TLS 세션 재사용
const tlsOptions = {
key: privateKey,
cert: certificate,
// 세션 캐시 활성화
sessionIdContext: "myapp",
sessionTimeout: 300, // 5분
};개발 환경에서의 HTTPS
로컬 개발용 자체 서명 인증서
# OpenSSL로 자체 서명 인증서 생성
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
# 또는 mkcert 사용 (권장)
mkcert localhost 127.0.0.1webpack-dev-server HTTPS 설정
// webpack.config.js
module.exports = {
devServer: {
https: true,
// 또는 인증서 지정
https: {
key: fs.readFileSync("/path/to/server.key"),
cert: fs.readFileSync("/path/to/server.crt"),
},
port: 443,
},
};마이그레이션 전략
HTTP에서 HTTPS로 전환
// 1. HTTP 요청을 HTTPS로 리다이렉트
app.use((req, res, next) => {
if (!req.secure && req.get("x-forwarded-proto") !== "https") {
return res.redirect(301, "https://" + req.get("host") + req.url);
}
next();
});
// 2. Mixed Content 경고 해결
// HTTP 리소스를 HTTPS로 변경
// <script src="http://example.com/script.js">
// → <script src="https://example.com/script.js">
// 3. HSTS 헤더 점진적 적용
app.use((req, res, next) => {
// 처음에는 짧은 기간으로 시작
res.setHeader("Strict-Transport-Security", "max-age=300");
// 안정화되면 1년으로 증가
// res.setHeader('Strict-Transport-Security', 'max-age=31536000');
next();
});면접 팁
HTTP와 HTTPS의 차이를 설명할 때는 단순히 "암호화 여부"만 언급하지 말고, 구체적인 보안 위협과 TLS 핸드셰이크 과정, 성능 영향 등을 함께 설명할 수 있어야 합니다.