
Mac M1 + Express 서버 테스트 기반
웹을 하다 보면 브라우저에서 “이 사이트는 안전하지 않습니다” 같은 경고를 볼 때가 있죠.
또한 웹 개발을 배우다 보면 “HTTP는 위험하니 반드시 HTTPS를 써야 한다”는 말을 수도 없이 듣습니다.
그런데, 혹시 이렇게 생각해 본 적 없나요?
“정말 HTTP 요청은 암호화가 전혀 안 돼서,
중간에서 보면 그대로 다 보일까?
이번 글에서는 Wireshark를 활용해
• HTTP 요청을 중간에서 가로채 평문을 확인하고
• HTTPS 요청이 암호화되는 과정을 직접 테스트해보겠습니다.
• HTTP 요청 → Wireshark에서 ID/PW가 평문으로 노출되는 것 확인
• HTTPS 요청 → Wireshark에서 암호화돼서 내용을 알 수 없는 것 확인

폴더 구조
express-tls-test/ ← 프로젝트 루트
├── cert/ ← 인증서 폴더
│ ├── key.pem ← 개인 키 (비밀)
│ └── cert.pem ← 공개 인증서
├── index.js ← Express 서버 코드
├── package.json
└── node_modules/
mkdir express-tls-test
cd express-tls-test
npm init -y
npm install express
mkdir cert
cd cert
openssl genrsa -out key.pem 2048
✅ 명령어 구조
• openssl
→ OpenSSL 툴을 실행하는 명령어
• genrsa
→ RSA 개인 키(private key) 생성 명령
• -out key.pem
→ 생성된 개인 키를 key.pem 파일로 저장
• 2048
→ 키 길이를 2048비트로 설정 (기본 보안 권장값)
🔹 동작 원리
• HTTPS 서버는 대칭키 + 비대칭키 혼합 암호화를 사용해요.
• 여기서 생성하는 개인 키(private key) 는 TLS 핸드셰이크에서 사용되는 비대칭키 중 하나예요.
• 개인 키는 서버에서만 보관하며, 절대로 외부에 노출되면 안 돼요.
openssl req -new -x509 -key key.pem -out cert.pem -days 365
✅ 명령어 구조
• openssl
→ OpenSSL 툴 실행
• req
→ X.509 인증서 요청 및 생성 관련 명령
• -new
→ 새 인증서 생성
• -x509
→ 인증기관(CA)에 요청하지 않고 자체 서명(self-signed) 인증서 생성
• -key key.pem
→ 아까 만든 개인 키를 사용
• -out cert.pem
→ 생성된 공개 인증서를 cert.pem 파일로 저장
• -days 365
→ 인증서 유효기간을 365일로 설정
• Common Name (CN) → localhost 또는 도메인 입력 필수
• 로컬 개발용이므로 localhost로 설정하는 게 안전해요.
{
"name": "https",
"version": "1.0.0",
"type": "module",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "^5.1.0"
}
}
// index.js
import fs from "fs";
import http from "http";
import https from "https";
import express from "express";
const app = express();
app.use(express.json());
// 테스트용 라우트
app.post("/login", (req, res) => {
const { username, password } = req.body;
console.log("📩 요청 도착:", username, password);
res.json({ message: "로그인 요청 수신 완료", username });
});
// HTTP 서버 실행
const httpPort = 8080;
http.createServer(app).listen(httpPort, () => {
console.log(`🔓 HTTP 서버 실행 중: http://localhost:${httpPort}`);
});
// HTTPS 서버 실행
const httpsPort = 8443;
const options = {
key: fs.readFileSync("./cert/key.pem"),
cert: fs.readFileSync("./cert/cert.pem"),
};
https.createServer(options, app).listen(httpsPort, () => {
console.log(`🔐 HTTPS 서버 실행 중: https://localhost:${httpsPort}`);
});
• [Wireshark](https://www.wireshark.org/#download) 공식 사이트
• Mac M1 (Apple Silicon) → macOS Arm Disk
Wireshark 실행 후 Capture > Options:
• localhost 트래픽 캡처 → lo0 선택 ✅

curl -X POST http://localhost:8080/login \
-H "Content-Type: application/json" \
-d '{"username":"kimsh","password":"mypassword123"}'
tcp.port == 8080

• Hypertext Transfer Protocol → Request Body에서 평문 그대로 노출:
curl -k -X POST https://localhost:8443/login \
-H "Content-Type: application/json" \
-d '{"username":"kimsh","password":"mypassword123"}'
tcp.port == 8443

Wireshark로 실습해보니 HTTPS의 중요성을 다시금 실감했습니다.
• HTTP 요청 → 패킷 평문 그대로 노출 ❌
• HTTPS 요청 → 암호화로 안전하게 보호 ✅
결론:
HTTP 사이트에서는 로그인, 결제 등 민감한 정보 입력을 절대 하지 마세요.
HTTPS는 선택이 아니라 필수입니다.