프론트엔드 기초 다시 쌓기 챌린지 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: 서버가 보낸 헤더
HTTP는 데이터를 평문(일반 텍스트)으로 보낸다. 중간에 누가 볼 수 있다.
[HTTP - 평문 전송]
브라우저 → "로그인: id=user1, pw=1234" → 서버
↑
해커가 중간에서 엿봄!
레스토랑 비유: 주문서를 투명한 봉투에 넣어서 배달. 배달하는 사람이 내용을 다 볼 수 있음.
HTTPS = HTTP + SSL/TLS 암호화. 데이터를 암호화해서 보낸다.
[HTTPS - 암호화 전송]
브라우저 → "aX7#kL9@mQ..." → 서버
↑
해커가 봐도 해독 불가!
1. 암호화 (Encryption)
데이터를 못 읽게 만듦. 로그인, 결제, 개인정보 보호.
2. 인증 (Authentication)
접속한 서버가 진짜인지 SSL 인증서로 확인. 피싱 사이트 구별.
레스토랑 비유: 입구에 걸린 사업자등록증.
3. 무결성 (Integrity)
데이터가 중간에 변조되지 않음을 보장.
"10,000원 결제"가 중간에 "1,000,000원"으로 바뀌지 않음.
| HTTP | HTTPS | |
|---|---|---|
| 포트 | 80 | 443 |
| 암호화 | ❌ 없음 | ✅ SSL/TLS |
| URL | http:// | https:// |
| 브라우저 표시 | ⚠️ "안전하지 않음" | 🔒 자물쇠 |
| 레스토랑 비유 | 투명 봉투 | 잠금 금고 |
Day 9에서 배운 Nginx에서 HTTPS를 처리한다:
사용자 → HTTPS(443) → Nginx → HTTP(5008) → Next.js 앱
Nginx가 HTTPS를 처리하고, 내부에서는 HTTP로 통신
사용자와 Nginx 사이만 암호화되면 됨
1. 보안: 로그인, 결제 정보 보호
2. SEO: 구글이 HTTPS 사이트를 우선 노출
3. 신뢰: 브라우저가 HTTP에 "안전하지 않음" 경고
4. 기능: 카메라, 마이크, 위치 정보 등 HTTPS에서만 동작
지금까지 배운 보안 내용이 전부 헤더와 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 인증서 |
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년차개발자 #기초다시쌓기