1. http
HTTP(HyperText Transfer Protocol) 는 웹에서 클라이언트(브라우저) 가 서버 에 “리소스(HTML, JSON, 이미지 등)를 달라”라고 요청하고, 서버가 응답하는 통신 규칙(프로토콜).
즉, 웹의 기본 대화 방식.
HTTP가 하는 일 (역할)
- 브라우저 → 서버로 요청(Request) 을 보냄
- 서버 → 브라우저로 응답(Response) 을 보냄
- 이 과정을 통해 페이지가 뜨거나(HTML), API 응답(JSON)을 받습니다.
HTTP의 핵심 특징
1) 요청/응답 구조
- 요청: 메서드 + 경로 + 헤더 + 바디
- 응답: 상태코드 + 헤더 + 바디
예) API 호출의 전형적인 흐름
- GET /users/1 → 유저 정보 달라
- 서버 응답: 200 OK + JSON 바디
2) Stateless (무상태)
HTTP 자체는 이전 요청을 기억하지 않음.
그래서 로그인 같은 “상태”는 보통 아래로 보완합니다.
- 쿠키/세션
- 토큰(JWT 등)
3) 사람이 읽기 쉬운 텍스트 기반
요청 라인/헤더는 텍스트로 표현됩니다(그래서 디버깅이 쉬움).
4) 기본 포트
- HTTP 기본 포트: 80
(단, 실제 서비스는 리버스 프록시/로드밸런서 구성에 따라 달라질 수 있어요.)
HTTP에서 자주 쓰는 메서드
- GET: 조회
- POST: 생성/처리
- PUT: 전체 수정(또는 대체)
- PATCH: 부분 수정
- DELETE: 삭제
상태코드(응답 코드) 감 잡기
- 2xx 성공: 200 OK, 201 Created
- 3xx 리다이렉트: 301, 302
- 4xx 클라이언트 오류: 400, 401, 403, 404
- 5xx 서버 오류: 500, 502, 503
2. https
HTTPS(HyperText Transfer Protocol Secure) 는 HTTP에 보안 계층(TLS/SSL) 을 붙인 통신 방식.
즉, “HTTP로 주고받되, 그 내용을 안전하게(암호화/검증/인증) 주고받는 프로토콜”
HTTPS는 아래 3가지를 보장하려고 만들어졌습니다.
- 기밀성(Confidentiality): 전송 내용이 암호화되어 중간에서 훔쳐봐도 읽기 어려움
- 무결성(Integrity): 데이터가 중간에서 변조되면 감지/차단
- 인증(Authentication): 접속한 서버가 진짜 그 서버인지(가짜 서버 방지) 확인
HTTPS는 어떻게 동작하나? (큰 흐름)
HTTPS는 “HTTP 요청/응답”을 하기 전에, 먼저 TLS 핸드셰이크로 안전한 통신 준비를 합니다.
1) TLS 핸드셰이크(보안 통로 만들기)
- 브라우저(클라이언트)가 서버에게 “보안 연결하자” 요청
- 서버가 인증서(서버의 신분증) 를 줌
- 브라우저는 인증서가 신뢰할 수 있는 CA(인증기관) 로부터 발급된 건지, 도메인/유효기간이 맞는지 확인
- 확인이 끝나면, 양쪽이 같은 대칭키(세션키) 를 안전하게 합의
- 이후부터는 그 세션키로 데이터가 빠르게 암호화되어 오감
핵심은:
- 인증서로 ‘진짜 서버’인지 확인
- 이후 세션키로 실제 데이터 암호화 (대칭키가 빠르기 때문)
2) 그 다음에 “그냥 HTTP처럼” 통신
보안 통로 위에서
- GET /…, POST /… 같은 HTTP 요청/응답이 그대로 오가는데
- 내용은 전부 암호화된 상태로 전송됩니다.
HTTPS의 특징
1) 기본 포트
- HTTPS 기본 포트: 443
2) URL 표기
- https:// 로 시작
- 브라우저 자물쇠 아이콘(인증서 유효 + 안전 연결)
3) 성능은?
예전엔 “HTTPS는 느리다” 인식이 있었는데, 지금은:
- TLS 최적화, 세션 재사용, HTTP/2/HTTP/3 등으로
실사용에서 큰 차이 없거나 오히려 더 나은 경우도 많습니다.
(단, 최초 연결 시 핸드셰이크 비용은 존재)
단 HTTPS가 있어도 “완벽”은 아니다
- HTTPS는 전송 구간을 보호합니다.
서버 자체가 털리거나, 사용자 PC가 악성코드에 감염되면 별개 문제. - HTTPS라고 해서 “그 사이트가 무조건 안전한 서비스/정상 기업”을 의미하진 않습니다.
도메인 소유를 증명하는 인증서도 많아서(기본 DV) 피싱에 악용될 수도 있어요.
다만 중간자 공격/도청/변조는 크게 막아줍니다.
http를 사용하면 발생할수있는 취약점
1) 도청 스니핑 (Packet Sniffing)
- 같은 네트워크(공용 와이파이, 사내망 등)에서 공격자가 트래픽을 가로채서 읽는 방식
- HTTP는 평문이라 로그인 ID/PW, 쿠키, 폼 입력값, API 응답(JSON) 등이 그대로 보일 수 있음
- 예: 공용 와이파이에서 HTTP 로그인 → 계정 정보 노출
2) 중간자 공격 (MITM)
- 공격자가 사용자↔서버 사이에 끼어들어 보거나/바꾸거나/가짜로 응답함
- HTTP는 “서버가 진짜인지” 확인이 약해서 더 쉽습니다.
- 예: 로그인 페이지를 가짜로 바꿔서 비밀번호를 빼감
3) 트래픽 변조 (Content Injection / Ad Injection)
- 통신 내용을 중간에서 수정해서 악성 스크립트/광고/리다이렉트를 끼워 넣음
- 예: HTTP로 받는 웹페이지에 <script>를 주입 → 악성 사이트로 유도, 추가 악성코드 다운로드 유도
4) 세션 하이재킹 (Session Hijacking)
- 로그인 후에 서버가 “너 로그인 됐어”라고 식별하는 값이 보통 세션 쿠키인데,
- HTTP에서는 이 쿠키가 노출될 수 있어서 비번 없이도 로그인 상태를 탈취 가능
- 예: 쿠키를 훔쳐서 그대로 재사용 → 내 계정으로 접속된 것처럼 행동
5) 세션 고정 (Session Fixation)
- 공격자가 특정 세션 ID를 피해자에게 쓰게 만든 뒤(링크/주입 등),
- 피해자가 로그인하면 그 세션이 “로그인된 세션”이 되어서 공격자가 그대로 탈취
- HTTP 환경에서 세션 관리가 허술하면 더 위험해질 수 있음
“HTTP 환경에서 더 쉽게 악용되지만, 근본 원인은 세션 재발급/검증 로직 미흡”
6) 다운그레이드/SSL Stripping (HTTPS를 HTTP로 떨어뜨리기)
- 사용자가 원래 HTTPS로 갈 상황인데, 공격자가 중간에서 “HTTP로 접속하게” 유도/강제
- 예: 첫 접속이 HTTP인 사이트에서 301/302를 가로채 HTTPS 이동을 막고 계속 HTTP로 사용하게 만들기
- (HSTS 적용이 약하면 특히 위험)
7) DNS 스푸핑/피싱 결합
- DNS 응답을 속이거나 공유기/와이파이에서 DNS를 조작해 가짜 서버로 보내는 방식
- HTTP면 그 가짜 서버가 진짜처럼 보이기 쉬움(인증서 검증이 없으니까)
- 예: bank.example.com을 가짜 IP로 연결 → 똑같은 로그인 화면 제공 → 정보 탈취
“DNS 조작 자체는 HTTPS에도 발생할 수 있으나, HTTPS는 인증서 검증으로 피해를 크게 줄인다.”
https를 사용하지 않고 해당 취약점에 의한 피해를 줄이거나 일부 막을수 있는 우회방법
1) 애플리케이션 레벨 암호화 (Payload 자체를 암호화)
전송 내용(바디) 을 앱에서 직접 암호화해서 보내는 방식입니다.
- 예: 클라이언트가 AES-GCM 같은 대칭키로 JSON 바디를 암호화 → 서버에서 복호화
- 장점: 네트워크에서 바디를 훔쳐봐도 내용은 읽기 어려움
- 한계(치명적):
- 헤더/URL/도메인은 여전히 노출(무슨 API를 호출하는지, 어떤 서버인지 등)
- 서버 인증이 없으면 키 교환 과정 자체가 MITM에 뚫림(키를 중간자가 갈아끼울 수 있음)
- 구현 실수(키 관리/nonce 재사용/검증 누락)로 오히려 취약해질 가능성이 큼
→ 보통 “HTTPS 위에 추가로” 쓰는 방식이지, 대체재로는 비추천
2) HMAC/서명으로 변조 감지 (무결성만 확보)
요청/응답에 서명(HMAC 또는 공개키 서명) 을 붙여서 중간 변조를 감지하는 방식입니다.
- 예: HMAC(secret, timestamp + body) 를 헤더로 보내고 서버가 검증
- 장점: 변조는 막거나 탐지 가능
- 한계:
- 내용은 여전히 도청 가능(기밀성 없음)
- 비밀키 공유/배포 문제가 남음
- 재전송 공격(replay) 방지용 timestamp/nonce가 필요
→ “변조 방지”에는 도움되지만, ‘보는 것’은 못 막음
3) 세션 탈취 완화 (쿠키/세션 운용으로 피해 줄이기)
HTTPS 없이도 세션 하이재킹 위험을 낮추는 운영은 가능해요(완전 차단은 아님).
- 쿠키에 HttpOnly (JS로 쿠키 읽기 차단)
- 세션을 IP/UA/디바이스 지문에 바인딩(환경 바뀌면 세션 폐기)
- 세션 수명 짧게 + 민감 기능은 재인증(비밀번호/2FA)
- 요청마다 CSRF 토큰/Origin 검사 등
- 한계:
- 네트워크에서 쿠키가 보이면 그대로 탈취 가능
- 공용망/NAT 환경에서 IP 바인딩은 오탐/불편 증가
→ “탈취 후 악용”을 줄이는 수준
4) 네트워크를 ‘사설화’해서 통로 자체를 믿는 방식
“HTTP를 쓰되, 그 통신이 흐르는 망을 암호화/격리”하는 접근입니다.
- VPN(사이트-투-사이트 / 클라이언트 VPN)
- 전용망, 사내망, 프라이빗 APN
- SSH 터널링(포트포워딩)
- 장점: 인터넷 구간 노출을 줄임(외부 스니핑/변조 난이도 상승)
- 한계:
- 결국 “TLS를 다른 형태로 쓰는 것”이지, HTTP 자체가 안전해지는 건 아님
- VPN/터널 종단이 뚫리면 동일 문제 재발
- 공용 사용자 대상 서비스엔 적용이 어렵거나 운영 부담이 큼
5) “사용자 실수/다운그레이드”만 줄이는 장치
- HTTPS를 쓰지 않는다고 했으니 이건 제한적이지만,
- 최소한 “HTTP로 넘어가게 만드는 공격”을 줄이려면 HSTS 같은 게 필요함
(다만 HSTS는 HTTPS가 전제라 여기선 실질적 해결책이 아님)
즉
기밀성(도청 방지) + 무결성(변조 방지) + 서버 인증을 동시에 해결하려면 사실상 TLS(=HTTPS) 가 정답
HTTPS 없이 할 수 있는 건:
- (a) 앱 데이터만 암호화해서 “내용만” 가리기
- (b) 서명으로 변조만 막기
- (c) 세션 정책으로 피해를 줄이기
- (d) VPN/터널로 망을 감싸기
HTTP의 실질적인 장점(HTTPS 대비)
1) 설정이 단순함
- 인증서 발급/갱신, 체인 문제, SNI, TLS 설정 같은 게 없음
- “로컬에서 잠깐 띄워서 확인” 같은 용도에 편합니다.
2) 최초 연결 오버헤드가 더 적음(아주 미세)
- TLS 핸드셰이크가 없어서 이론상 더 가볍습니다.
- 다만 요즘은 TLS 1.3, 세션 재개, HTTP/2/3 최적화로 체감 차이는 거의 없거나 오히려 HTTPS가 더 빠른 경우도 많습니다(HTTP/2/3는 보통 TLS와 같이 쓰이니까).
3) 디버깅/패킷 분석이 쉬움(보안 장비 없이)
- 네트워크에서 그냥 캡처하면 내용이 보이니 트러블슈팅이 쉽습니다.
- 물론 이건 **“장점”이라기보다 “보안이 없어서 생기는 편의”**에 가깝습니다.
- HTTPS도 개발 환경에서는 프록시(Charles/Fiddler), 로컬 CA, 로그 등으로 충분히 디버깅 가능합니다.
4) 아주 제한된 환경에서의 적용 용이성
- 극도로 단순한 장치/레거시 시스템에서 TLS 스택이 부담될 수 있음(메모리/CPU/라이브러리).
- 다만 요즘 IoT도 경량 TLS가 많고, 외부망이면 TLS가 사실상 필수에 가까워요.
5) “민감 정보가 전혀 없는 내부 폐쇄망”에선 비용 대비 효율
- 인터넷과 완전히 분리된 망(진짜 폐쇄)에서
- 테스트용, 상태 페이지(health check) 등 민감정보 0인 경우엔 HTTP가 운영 단순성 면에서 선택될 수 있습니다.
- HTTP의 장점 = 단순함/편의/레거시 호환
- HTTPS의 가치 = 인터넷에서 서비스를 ‘성립’시키는 안전장치
개발 서버를 https로 사용하는법
A. mkcert로 “신뢰되는 로컬 인증서” 만들기 (가장 추천)
장점: 크롬/엣지에서 경고 없이 정상 HTTPS, 설정도 단순
개요: 내 PC에 로컬 CA를 설치하고, localhost용 인증서를 발급해서 서버에 붙입니다.
1) 인증서 발급
- mkcert 설치 후:
- mkcert -install
- mkcert localhost 127.0.0.1 ::1
- 그러면 대개 이런 파일이 생깁니다:
- localhost+2.pem (인증서)
- localhost+2-key.pem (개인키)
2) Spring Boot(내장 톰캣)에 HTTPS 붙이기
Spring Boot는 보통 PKCS12(.p12) 키스토어를 씁니다. pem을 p12로 변환.
openssl pkcs12 -export \
-in localhost+2.pem \
-inkey localhost+2-key.pem \
-out localhost.p12 \
-name local-https \
-passout pass:changeit
src/main/resources/localhost.p12로 넣고 application.yml:
server:
port: 8443
ssl:
enabled: true
key-store: classpath:localhost.p12
key-store-type: PKCS12
key-store-password: changeit
key-alias: local-https
3) React(dev server)도 HTTPS로 띄우고 싶으면
- Vite/CRA 각각 방법이 다른데, 핵심은 “인증서/키를 지정해서 https로 구동”입니다.
- 다만 보통은 프론트는 http로 두고, API만 https로 붙이는 경우도 많아요(프록시 설정으로 해결).
B. “로컬은 HTTP 그대로 + 프록시/리버스 프록시로만 HTTPS” (현업에서도 자주)
로컬에서 HTTPS가 꼭 필요한 경우가 쿠키 Secure, 일부 브라우저 기능(권한/보안 컨텍스트), OAuth 리다이렉트 URI 때문이면,
- 프론트/백엔드 자체는 http 유지
- 앞단 프록시(예: nginx, caddy)에서만 https로 종단처리
이 방식이 가장 덜 번거롭습니다.
서버 배포후 https를 사용하는 법
A. 가장 흔한 구조: Nginx(443) → Spring Boot(8080)
장점: 운영 안정적, 인증서 갱신 자동화 쉬움, 리다이렉트/HSTS/압축/정적파일 처리 유리
1) DNS 설정
- 도메인의 A 레코드(또는 CNAME)를 서버 IP로 연결
2) 인증서 발급 (Certbot + Nginx)
Ubuntu 기준으로 보통:
- certbot --nginx -d example.com -d www.example.com
- 자동으로 Nginx 설정에 SSL 적용 + 갱신 스케줄(renew)까지 잡히는 경우가 많습니다.
3) HTTP → HTTPS 리다이렉트 (필수)
Nginx에서 80은 무조건 443로 보내기:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
4) 443에서 프록시로 백엔드 연결
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location /api/ {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
# 리액트 정적 빌드 서빙 또는 별도 프론트 서버로 프록시
}
}
B. 클라우드 쓰는 경우: 로드밸런서(ALB) / Cloudflare에서 HTTPS 종료
- AWS ALB에 ACM 인증서 붙이고, ALB → EC2(또는 ECS)로 HTTP 전달
- Cloudflare 사용 시 “Full(strict)” 등 모드로 종단 처리
포인트: 이 경우에도 “외부는 HTTPS”, 내부는 HTTP일 수 있습니다(내부망이면 보통 OK).
C. Spring Boot에 인증서 직접 붙여서 443로 띄우는 방식(가능은 함)
- 단독 서버/간단 배포면 가능하지만,
- 운영에서는 보통 Nginx/ALB 앞단을 둡니다(갱신/보안헤더/성능/라우팅이 편함).
배포에서 꼭 같이 해야 하는 보안/동작 체크
- 리다이렉트: 80 → 443 (301/308)
- HSTS(선택이지만 권장): HTTPS 강제(다운그레이드 공격 방지)
- 쿠키 설정: Secure, HttpOnly, SameSite (특히 세션/로그인)
- 혼합 콘텐츠 제거: 모든 리소스(API/이미지/CDN) URL을 https로 통일
https를 사용하여 추가 비용이 발생하는 경우
1) 로드밸런서(ALB)를 새로 쓰게 되는 경우
- 단일 서버에 Nginx+Let’s Encrypt로 붙이면 추가비용 없음
- 그런데 “HTTPS 처리를 ALB에서 하겠다”로 가면
- ALB 사용료가 추가될 수 있음 (인증서는 ACM으로 무료여도 ALB 자체가 유료)
2) 유료 인증서(상용 CA)를 쓰는 경우
- 회사 정책/특수 요구로 EV/OV 인증서 등을 요구하면 유료
- 일반 개인/프로젝트/대부분 서비스는 Let’s Encrypt로 충분
3) CDN/WAF/보안 서비스 유료 플랜을 쓰는 경우
- Cloudflare 같은 걸 “기능 때문에” 유료로 올릴 수는 있는데
- 이것도 HTTPS 자체 때문이라기보단 “부가 기능” 때문에 비용이 발생
SSL 인증 (정확히는 TLS 인증)
- 어디에 쓰나: 브라우저 ↔ 웹서버, API 통신(HTTPS)
- 목적:
- 통신 암호화(도청 방지)
- 데이터 변조 방지
- “이 서버가 진짜 그 도메인의 서버인지” 서버 신원 확인
- 신뢰의 근거: CA(인증기관) 가 발급한 인증서(서버의 신분증)
- 브라우저/OS는 “신뢰하는 CA 목록”을 기본으로 가지고 있고, 그 체인을 검증해서 믿습니다.
- 대표 포트: 443 (HTTPS)
- 핵심 포인트: “서버가 example.com 맞아?”를 공인 구조(CA)로 검증하는 체계
SSH 인증
- 어디에 쓰나: 서버 원격 접속(터미널), 파일 전송(SCP/SFTP), Git 접속(git@…)
- 목적:
- 원격 접속 통신 암호화
- 접속하는 주체(사용자/클라이언트) 인증
- 신뢰의 근거: 보통 공개키/개인키 키페어(내가 만든 키)
- 서버는 “이 사용자의 공개키를 허용한다”를 authorized_keys에 등록해둠
- 클라이언트는 개인키로 “내가 그 키의 주인”임을 증명
- 서버 자체의 신원도 확인은 하는데, 방식이 TLS와 달라요:
- 처음 접속 때 서버가 host key를 보여주고, 클라이언트가 그 지문을 저장(known_hosts)
- 이후 값이 바뀌면 경고(중간자 공격 의심)
- 대표 포트: 22
- 핵심 포인트: CA 같은 공인 구조보다는 키 등록/지문 고정(TOFU) 중심
한 줄로 비교
- TLS(SSL): “이 도메인의 서버가 진짜인지”를 CA 인증서로 보증하면서 웹 통신을 안전하게.
- SSH: “서버에 접속하는 사용자가 누구인지”를 키 기반 로그인으로 안전하게.
- HTTPS 배포: TLS 인증서(Let’s Encrypt 등) 필요
- 서버 배포/관리 접속: SSH 키 필요 (ssh ubuntu@서버IP, GitHub SSH 키 등)
TLS인증서를 발급 받을수 있는 방법
1) Let’s Encrypt로 발급 (무료, 실무 표준)
준비물
- 도메인(예: example.com)이 내 서버 IP를 가리키도록 DNS 설정
- 외부에서 80(HTTP) 또는 DNS 설정 변경이 가능해야 함
인증(검증) 방식 2개
A. HTTP-01 (가장 흔함)
- Let’s Encrypt가 도메인이 정말 본인것 인지 확인하기 위해
http://example.com/.well-known/acme-challenge/... 경로로 접근해 검증 - 그래서 80 포트가 외부에서 열려 있어야 합니다.
B. DNS-01 (와일드카드/80 막힌 환경에 유리)
- DNS에 _acme-challenge TXT 레코드를 넣어 검증
- *.example.com 와일드카드 인증서가 필요하면 보통 이 방식이 필요합니다(일반적으로).
(DNS-01은 TXT 레코드로 검증한다는 설명 참고. )
발급 도구(ACME 클라이언트)
A. Certbot (가장 대중적)
- Nginx/Apache 플러그인으로 “발급 + 설정”까지 자동으로 해주는 경우가 많아요.
- 갱신도 certbot renew로 자동화가 잘 되어 있습니다(드라이런도 지원).
B. acme.sh (가볍고, DNS-01 자동화에 강함)
- 임베디드/공유기/도커 등에서도 많이 씁니다(standalone/webroot/dns 등 모드).
2) AWS 같은 클라우드에서 “관리형 인증서”로 발급 (대개 무료지만 제약 있음)
AWS ACM (Amazon Certificate Manager)
- ACM에서 퍼블릭 인증서를 요청할 수 있고,
CloudFront/ELB/API Gateway 같은 AWS 통합 서비스에 붙이면 갱신까지 관리형으로 굴릴 수 있어요. - 단, 일반적으로 “EC2에 파일로 내려받아 설치” 같은 건 제약이 있습니다(통합 서비스용으로 쓰는 형태).
(그래서 EC2 단독이면 보통 Let’s Encrypt + Nginx로 처리합니다.)
3) 자체 서명(Self-signed) 인증서 (무료, 로컬/내부망용)
- 내가 직접 서명한 인증서
- 브라우저에 ‘안전하지 않음’ 경고가 뜨는 게 정상이라, 보통 로컬 개발/내부 테스트에만 씁니다.
http의 버전별 차이점과 성능
HTTP/0.9
- 아주 초기 형태. GET만 있고 헤더/상태코드 같은 개념이 거의 없음.
- 성능/기능 비교 대상으로는 거의 안 씀(역사 수준).
HTTP/1.0
특징
- 요청/응답에 헤더 개념이 생기고, 상태코드도 정착.
- 기본적으로 요청 1번 = TCP 연결 1번(짧게 끊김).
성능
- 리소스(이미지/CSS/JS)가 많은 웹페이지는 연결을 계속 새로 열어야 해서 느림.
- TCP 핸드셰이크(3-way) 비용이 매 요청마다 반복.
HTTP/1.1
핵심 개선
- 지속 연결(Keep-Alive): TCP 연결을 재사용.
- 파이프라이닝(pipelining): 여러 요청을 연달아 보내는 시도(하지만 실전에서는 문제 때문에 거의 비활성/비권장).
- Host 헤더로 가상호스팅 가능(하나의 IP에서 여러 도메인).
성능 특징
- 1.0보다 훨씬 좋아짐(연결 재사용).
- 하지만 여전히 “한 연결에서 요청/응답이 사실상 순서대로” 처리되는 성격이 강해 병목이 생김.
대표 병목: HOL(Head-of-Line) Blocking (애플리케이션 레벨)
- 하나의 큰 응답이 앞에 걸리면 뒤의 작은 파일들이 줄줄이 대기.
- 그래서 브라우저가 “병렬 다운로드”하려고 여러 TCP 연결을 동시에 여는 방식으로 우회(도메인당 6개 내외 같은 제한 관행).
HTTP/2
핵심 목표: “한 연결에서 진짜 병렬로 처리하자”
- 바이너리 프레이밍: 텍스트가 아니라 프레임 단위로 쪼개 전송.
- 멀티플렉싱: 하나의 TCP 연결 위에서 여러 요청/응답을 동시에 섞어 보내기 가능.
- 헤더 압축(HPACK): 중복 헤더를 줄여 전송량 감소.
- 서버 푸시(Server Push): 서버가 필요 리소스를 미리 푸시(요즘은 운영에서 꺼두는 경우가 많음).
성능이 좋아지는 이유
- HTTP/1.1의 핵심 병목이던 애플리케이션 레벨 HOL을 크게 줄임.
- 여러 연결을 억지로 열 필요가 줄어 TCP 연결 수 감소 → 서버/네트워크 효율 증가.
- 헤더가 큰 API 환경에서 HPACK이 체감될 때가 많음.
하지만 남는 병목: TCP 레벨 HOL
- HTTP/2는 여전히 TCP 위에서 동작.
- TCP는 패킷 손실이 나면 그 이후 데이터도 “정렬/재전송” 때문에 대기 → 한 패킷 손실이 전체 스트림에 영향을 줄 수 있음(특히 모바일/무선).
HTTP/3 (QUIC 기반)
핵심 목표: “TCP 때문에 생기는 HOL도 없애자”
- HTTP/3는 TCP가 아니라 QUIC(UDP 위에서 동작) 를 사용.
- QUIC은 내부적으로 암호화(TLS 1.3)와 전송제어를 포함.
핵심 개선점(성능)
- 스트림 단위 전송: 한 스트림에서 손실이 나도 다른 스트림은 영향이 훨씬 적음 → TCP HOL 완화.
- 연결 성립이 빠름: 보통 TLS 1.3과 결합하여 RTT를 줄이는 데 유리.
- Connection Migration: IP가 바뀌어도(와이파이↔LTE) 연결을 더 잘 이어감(모바일 강점).
- 손실 회복/혼잡제어가 애플리케이션 레벨에서 더 유연하게 설계됨.
체감이 큰 환경
- 모바일, 무선, 패킷 손실/지연이 있는 네트워크
- 리소스/요청이 많은 웹앱
- 1.0 → 1.1: 연결 재사용으로 기본 성능 개선
- 1.1 → 2: 한 연결에서 멀티플렉싱 + 헤더 압축으로 병렬성/효율 개선
- 2 → 3: TCP HOL을 QUIC으로 줄여 특히 불안정한 네트워크에서 강함
https는 버전이 없는지?
- HTTP 버전: HTTP/1.1, HTTP/2, HTTP/3
- TLS 버전(= HTTPS에서의 보안 프로토콜 버전): TLS 1.0, 1.1, 1.2, 1.3
즉 HTTPS = (어떤 HTTP 버전) + TLS 조합이고, “HTTPS 2.0” 같은 식으로 말하진 않는 편.
그럼 HTTP/2에서 HTTPS vs HTTP/3에서 HTTPS는 뭐가 다른지?
둘 다 “암호화된 웹 통신”이지만 아래가 다릅니다.
1) 밑바닥 전송 계층이 다름
- HTTP/2 over HTTPS: HTTP/2 + TLS 가 TCP 위에서 동작
- HTTP/3 over HTTPS: HTTP/3 + TLS 1.3 이 QUIC(UDP 기반) 위에서 동작
- QUIC 안에 TLS 1.3 핸드셰이크가 통합돼 있다고 보면 됩니다.
결과적으로 “HTTPS를 쓰느냐”보다, TCP냐 QUIC이냐가 체감 차이를 만듭니다.
**HTTP/2(=TCP 기반)**는 “한 연결에서 멀티플렉싱”은 되지만,
- TCP 특성상 패킷 손실이 나면 그 연결의 데이터가 대기하는 TCP 레벨 HOL(Head-of-Line) 문제가 생길 수 있어요.
**HTTP/3(=QUIC 기반)**는 스트림을 더 분리해서 다루므로,
- 한 스트림에서 손실이 나도 다른 스트림 영향이 상대적으로 적고
- 특히 모바일/무선/손실 많은 환경에서 유리한 경우가 많습니다.
- HTTP/2: 표준상 TLS 없이도 가능(h2c) 하지만, 브라우저 웹에선 사실상 HTTPS(h2)만 쓴다고 봐도 됨.
- HTTP/3: 구조상 TLS 1.3이 사실상 필수라서 브라우저 환경에선 항상 암호화라고 보면 됨.
TLS의 버전별 차이는?
TLS 1.0 (1999) / TLS 1.1 (2006)
- 현황: IETF에서 공식적으로 폐기(Historic) 되었고, 산업 표준/브라우저도 대부분 비활성화했습니다.
- 왜 위험한가(요지): 최신 권고 암호/메커니즘 지원이 부족하고, 현대 보안 프로파일에서 요구하는 수준을 충족하기 어렵습니다(그래서 “피해야 한다”가 표준 결론).
* 신규 구축/배포에서 TLS1.0/1.1은 옵션에서 빼는게 원칙
TLS 1.2 (2008)
- 현황: 아직도 가장 널리 호환되는 “현역” 버전(레거시 호환용으로 유지되는 경우 많음).
- 핵심 개선 방향
- 암호 스위트 구성/해시/서명 알고리즘 선택 폭이 커지고, 현대적인 조합(AEAD 등)을 사용할 수 있는 기반이 됩니다. (표준은 TLS 1.2가 1.0/1.1을 대체했다고 명시)
- 주의점(중요): TLS 1.2는 “구식 알고리즘도 여전히 선택 가능”한 구조라서, 서버 설정이 허술하면 약한 조합으로 협상될 수 있음 → 그래서 보안 가이드는 강한 조합만 허용하도록 권장합니다.
TLS 1.3 (2018)
- 현황: 최신 표준. 보안/단순성/성능을 위해 프로토콜을 크게 정리했습니다. TLS 1.3 문서는 TLS 1.2(RFC 5246)를 “폐기/대체(obsoletes)”로 명시합니다.
- 가장 큰 차이 3가지
1) 더 빠른 핸드셰이크(지연 감소)
- 일반적으로 1-RTT로 핸드셰이크가 끝나도록 줄였고, 재접속 상황에선 0-RTT(early data) 도 가능하지만 리플레이 위험이 있어 신중히 써야 합니다.
2) “안전한 것만 남기기”로 프로토콜 단순화
- TLS 1.3는 구식 구성요소를 대거 제거해서, 운영자가 “실수로 약한 조합을 켜는” 가능성을 줄였습니다(요지는 단순+강화).
3) 더 강한 기본 보안 성질(현대적 설계)
- 최신 권고에 맞춰 TLS 1.3을 기본으로 두고, 호환 필요 시에만 TLS 1.2를 허용하라는 가이드가 일반적입니다.
HSTS란?
HTTP Strict Transport Security :
“이 도메인은 앞으로 무조건 HTTPS로만 접속해라” 를 브라우저에 강제시키는 보안 정책
왜 쓰나
HTTP→HTTPS로 리다이렉트만 해도 보통은 되지만, 공격자가 중간에서 HTTPS로 가는 리다이렉트를 막고 HTTP에 머물게 하는 공격(SSL Stripping) 을 시도할 수 있어요.
HSTS가 있으면 브라우저가 아예 HTTP로 접속 자체를 시도하지 않고 처음부터 HTTPS로 붙습니다.
어떻게 동작하나
서버가 HTTPS 응답에 아래 헤더를 실어 보냅니다.
- Strict-Transport-Security: max-age=...; includeSubDomains; preload
브라우저는 이걸 기억했다가:
- 사용자가 http://example.com을 입력해도
- 브라우저가 내부적으로 https://example.com으로 바꿔 접속합니다.
주요 옵션
- max-age: “얼마나 오래 HTTPS만 쓰도록 강제할지”(초 단위)
- 예: max-age=31536000 (1년)
- includeSubDomains: 하위 도메인도 전부 강제
- 예: api.example.com, www.example.com 포함
- preload: 브라우저에 “처음부터” 강제 목록으로 등록하는 용도(아래 주의 참고)
중요한 주의사항
- HSTS는 한 번 적용하면 되돌리기 어렵습니다.
- 특히 includeSubDomains + max-age가 길면, 하위 도메인까지 HTTPS가 준비되지 않았을 때 장애가 날 수 있어요.
- preload까지 등록하면(브라우저 내장 목록) 사실상 “되돌리기 더 어려운” 수준입니다.
그래서 preload는 모든 서브도메인까지 HTTPS 완비된 뒤에 하는 게 안전합니다.
'Daily Dev Q&A' 카테고리의 다른 글
| 데이터 베이스의 락 (0) | 2026.02.01 |
|---|---|
| JVM (0) | 2026.01.18 |
| application context (0) | 2026.01.16 |
| WAS와 웹서버 (0) | 2026.01.11 |
| Garbage Collection (0) | 2026.01.07 |