[Day 24] HTTP 헤더란? + HTTPS가 필요한 이유

짱효·2026년 5월 27일

프론트엔드 기초 다시 쌓기 챌린지 24일차.
Part 3 "네트워크 기초"의 네 번째 수업.

Day 21~23에서 HTTP의 큰 틀(요청/응답 구조, 메서드, 상태 코드)을 배웠다면,
오늘은 그동안 "부가 정보"라고만 넘겼던 헤더를 자세히 보고,
HTTP에 S가 붙으면 뭐가 달라지는지 배웠다.


🍳 오늘의 비유: "주문서의 상단 메모"

주문서에 메뉴(본문)만 적는 게 아니다. 위쪽에 이것저것 적는다:

테이블 번호: 5번                → 어디로 보낼지 (Host)
회원 등급: VIP                  → 누구인지 (Authorization)
알레르기: 견과류                → 주의사항
포장 방식: 접시에 담아주세요     → 형식 지정 (Accept)
쿠폰 번호: SAVE-20             → 이전에 받은 것 (Cookie)

HTTP 헤더가 바로 이 "상단 메모"다.


📤 요청 헤더 (브라우저 → 서버)

GET /api/products HTTP/1.1
Host: www.myshop.com
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJhbGci...
Cookie: session=abc123
User-Agent: Mozilla/5.0 (Windows NT 10.0)
Cache-Control: no-cache

주요 요청 헤더 정리

Host — "어떤 서버에 보내는 건지"

하나의 서버에 여러 사이트가 있을 수 있다 (Day 9 Nginx).
Host로 어떤 사이트인지 구분.

Accept — "이런 형식으로 주세요"

Accept: application/json    → JSON으로 주세요
Accept: text/html           → HTML로 주세요
Accept: image/png           → 이미지로 주세요

Content-Type — "제가 보내는 건 이런 형식이에요"

Content-Type: application/json     → JSON 데이터
Content-Type: multipart/form-data  → 파일 업로드

Accept vs Content-Type 차이:
Accept = "이런 형식으로 주세요" (받고 싶은 형식)
Content-Type = "제가 보내는 건 이거예요" (보내는 형식)

Authorization — "저 이 사람이에요"

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Day 21에서 배운 "무상태" 때문에 매 요청마다 보내야 한다.
JWT 토큰을 여기에 넣어서 보냄. (Day 30에서 자세히!)

Cookie — "지난번에 받은 쿠키예요"

서버가 이전에 Set-Cookie로 준 값을 매번 같이 보냄.
Day 19에서 배운 CSRF가 이걸 악용하는 거였다!

User-Agent — "제 브라우저 정보예요"

어떤 브라우저, 어떤 운영체제인지 알려줌.
서버가 모바일/데스크톱을 구분할 때 사용.

Cache-Control — "캐시 어떻게 할까요?"

Day 3에서 배운 캐싱과 연결!


📥 응답 헤더 (서버 → 브라우저)

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 256
Set-Cookie: session=xyz789; HttpOnly; Secure; SameSite=Strict
Cache-Control: max-age=3600
Access-Control-Allow-Origin: https://myshop.com

주요 응답 헤더 정리

Content-Type — "보내는 데이터 형식이에요"

Set-Cookie — "이 쿠키를 저장해주세요"

Set-Cookie: session=xyz789; HttpOnly; Secure; SameSite=Strict

여기 붙는 옵션이 중요하다:

HttpOnly  → JavaScript에서 접근 불가 (XSS 방어!)
Secure    → HTTPS에서만 전송
SameSite  → 다른 사이트에서 보낼 때 제한 (CSRF 방어!)

Day 19에서 배운 XSS, CSRF 방어가 쿠키 헤더 설정으로 이루어지는 거였다!

Cache-Control — "이 응답을 캐시해도 돼요"

Cache-Control: max-age=3600  → 1시간 동안 캐시 가능
Cache-Control: no-store      → 절대 캐시 금지

Access-Control-Allow-Origin — "이 사이트에서 접근 허용"

Day 29에서 배울 CORS와 관련! 미리 맛보기.


💻 여러분 코드에서의 헤더

fetch를 쓸 때 headers를 직접 설정하는 게 바로 이거였다:

fetch('/api/products', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',     // 보내는 형식이 JSON
    'Authorization': 'Bearer ' + token,      // 인증 정보
  },
  body: JSON.stringify({ name: '새 상품' })
})

Chrome DevTools에서 확인하는 법:

F12 → Network 탭 → 요청 클릭 → Headers 탭
→ Request Headers: 브라우저가 보낸 헤더
→ Response Headers: 서버가 보낸 헤더

🔒 HTTPS가 필요한 이유

HTTP의 문제: 다 보인다

HTTP는 데이터를 평문(일반 텍스트)으로 보낸다. 중간에 누가 볼 수 있다.

[HTTP - 평문 전송]
브라우저 → "로그인: id=user1, pw=1234" → 서버
                    ↑
              해커가 중간에서 엿봄!

레스토랑 비유: 주문서를 투명한 봉투에 넣어서 배달. 배달하는 사람이 내용을 다 볼 수 있음.

HTTPS: 자물쇠로 잠근다

HTTPS = HTTP + SSL/TLS 암호화. 데이터를 암호화해서 보낸다.

[HTTPS - 암호화 전송]
브라우저 → "aX7#kL9@mQ..." → 서버
                ↑
          해커가 봐도 해독 불가!

HTTPS가 하는 3가지

1. 암호화 (Encryption)

데이터를 못 읽게 만듦. 로그인, 결제, 개인정보 보호.

2. 인증 (Authentication)

접속한 서버가 진짜인지 SSL 인증서로 확인. 피싱 사이트 구별.

레스토랑 비유: 입구에 걸린 사업자등록증.

3. 무결성 (Integrity)

데이터가 중간에 변조되지 않음을 보장.
"10,000원 결제"가 중간에 "1,000,000원"으로 바뀌지 않음.

HTTP vs HTTPS 비교

HTTPHTTPS
포트80443
암호화❌ 없음✅ SSL/TLS
URLhttp://https://
브라우저 표시⚠️ "안전하지 않음"🔒 자물쇠
레스토랑 비유투명 봉투잠금 금고

실무에서 HTTPS 설정

Day 9에서 배운 Nginx에서 HTTPS를 처리한다:

사용자 → HTTPS(443) → Nginx → HTTP(5008) → Next.js 앱

Nginx가 HTTPS를 처리하고, 내부에서는 HTTP로 통신
사용자와 Nginx 사이만 암호화되면 됨

왜 HTTPS가 필수인가?

1. 보안: 로그인, 결제 정보 보호
2. SEO: 구글이 HTTPS 사이트를 우선 노출
3. 신뢰: 브라우저가 HTTP에 "안전하지 않음" 경고
4. 기능: 카메라, 마이크, 위치 정보 등 HTTPS에서만 동작

🔗 보안 총정리: Day 16~24 연결

지금까지 배운 보안 내용이 전부 헤더와 HTTPS에서 만난다:

Day 16: NEXT_PUBLIC_ → 코드 레벨 보안
Day 17: .env 관리 → 파일 레벨 보안
Day 18: API 키 관리 → 키 레벨 보안
Day 19: XSS, CSRF → 공격 방어
Day 24: 헤더 + HTTPS → 전송 레벨 보안 (오늘!)
XSS 방어  → Set-Cookie: HttpOnly (JS에서 쿠키 접근 차단)
CSRF 방어 → Set-Cookie: SameSite=Strict (다른 사이트에서 쿠키 전송 차단)
도청 방어 → HTTPS (데이터 암호화)

🍳 레스토랑 비유 업데이트

레스토랑서버
주문서 상단 메모HTTP 헤더
"테이블 5번"Host 헤더
"접시에 담아주세요"Accept 헤더
"제가 보내는 건 이거예요"Content-Type 헤더
"VIP 회원입니다"Authorization 헤더
"지난번 쿠폰이요"Cookie 헤더
"이 쿠폰 드릴게요"Set-Cookie 헤더
투명한 봉투로 배달HTTP (평문)
잠금 금고로 배달HTTPS (암호화)
레스토랑 사업자등록증SSL 인증서

🎯 오늘 배운 것 최종 정리

  1. 요청 헤더: Host(어디로), Accept(어떤 형식으로 주세요), Content-Type(보내는 형식), Authorization(인증), Cookie(이전 값)
  2. 응답 헤더: Content-Type(데이터 형식), Set-Cookie(쿠키 저장 + 보안 옵션), Cache-Control(캐시 정책)
  3. Accept vs Content-Type: Accept는 "이렇게 주세요", Content-Type은 "이걸 보내요"
  4. Set-Cookie 보안 옵션: HttpOnly(XSS 방어), Secure(HTTPS만), SameSite(CSRF 방어)
  5. HTTPS 3가지 역할: 암호화(못 읽게) + 인증(진짜 서버 확인) + 무결성(변조 방지)
  6. HTTPS가 필수인 이유: 보안, SEO, 브라우저 신뢰, 최신 기능 지원

🧪 이해도 체크

Q1. Set-Cookie에 HttpOnly와 SameSite=Strict를 설정하면 각각 어떤 공격을 막나?
→ 정답: HttpOnly는 XSS 방어 (JavaScript에서 쿠키 접근 차단). SameSite=Strict는 CSRF 방어 (다른 사이트에서 쿠키 전송 차단).

Q2. HTTP와 HTTPS의 가장 큰 차이는?
→ 정답: 데이터 암호화 여부. HTTP는 평문(누구나 볼 수 있음), HTTPS는 SSL/TLS로 암호화(가로채도 해독 불가). HTTPS가 필수인 이유는 보안, SEO, 브라우저 신뢰, 최신 기능 지원.

Q3. fetch에서 Content-Type: application/json을 넣는 이유는?
→ 정답: 서버에게 "제가 보내는 데이터가 JSON 형식이에요"라고 알려주는 것. 서버가 이 정보를 보고 데이터를 올바르게 파싱할 수 있다.


💭 회고

fetch()에 headers를 적을 때 항상 "그냥 이렇게 쓰는 거구나" 하고 외우기만 했다.

오늘 배우고 나니 Content-Type: application/json
"서버야, 내가 보내는 데이터는 JSON이야"라는 의미였다는 걸 알았다.
Authorization: Bearer ..."나 이 사람이야, 여기 토큰"이라는 뜻이었고.

특히 Set-Cookie의 옵션(HttpOnly, SameSite)이 인상적이었다.
Day 19에서 배운 XSS, CSRF 방어가 쿠키 헤더 설정 하나로 이루어진다니.
보안이 거창한 게 아니라 헤더 옵션 하나하나가 방어막인 거였다.

HTTPS도 "그냥 보안이니까 쓰는 것" 정도로만 알고 있었는데,
암호화 + 인증 + 무결성 3가지를 해준다는 걸 알게 됐다.
그리고 Nginx에서 HTTPS를 처리한다는 것도 Day 9과 연결되는 포인트였다.


📚 다음 학습 예고

Day 25: IP 주소란? + localhost, 127.0.0.1의 정체
Week 6 시작! 포트, IP, DNS의 세계로 들어간다.
매일 쓰는 localhost가 실제로 뭔지 알게 된다.

#프론트엔드 #HTTP #HTTPS #헤더 #SSL #보안 #네트워크 #2년차개발자 #기초다시쌓기

profile
✨🌏확장해 나가는 프론트엔드 개발자입니다✏️

0개의 댓글