** πŸ“Œ PART 4.1 μ„Έμ…˜(Session) 객체의 λ©”λͺ¨λ¦¬ λ¬Έμ œμ™€ ν΄λŸ¬μŠ€ν„°λ§ μ „λž΅ **

β€œλ‘œκ·ΈμΈ μƒνƒœλ₯Ό μœ μ§€ν•˜λ©΄μ„œλ„ μ„œλ²„ λ©”λͺ¨λ¦¬λ₯Ό μ•ˆμ „ν•˜κ²Œ μ“°λŠ” 법”


🟒 1단계. μ„Έμ…˜(Session)이 뭐야?

πŸ’¬ μ„Έμ…˜μ΄λž€ μ‚¬μš©μžκ°€ μ›Ήμ‚¬μ΄νŠΈμ— 듀어왔을 λ•Œ,

μ„œλ²„κ°€ κ·Έ μ‚¬μš©μžλ₯Ό κΈ°μ–΅ν•˜κΈ° μœ„ν•΄ λ§Œλ“€μ–΄μ£ΌλŠ” μ €μž₯ 곡간이야.


βœ… μ˜ˆμ‹œλ‘œ μ‰½κ²Œ μ„€λͺ…:


βœ… μ½”λ“œ μ˜ˆμ‹œ

HttpSession session = request.getSession();
session.setAttribute("loginId", "hong123");

β†’ μ‚¬μš©μžμ˜ 둜그인 정보λ₯Ό μ„Έμ…˜μ— μ €μž₯ν•˜λŠ” μ½”λ“œ


🧠 μ„Έμ…˜μ€ μ„œλ²„ λ©”λͺ¨λ¦¬μ— μ €μž₯됨!

ν•­λͺ© μ„€λͺ…
μ €μž₯ μœ„μΉ˜ WAS (Tomcat λ“±) λ©”λͺ¨λ¦¬
관리 λŒ€μƒ μ‚¬μš©μžλ³„ 데이터 (둜그인, μž₯λ°”κ΅¬λ‹ˆ λ“±)
μ‚­μ œ μ‹œμ  λΈŒλΌμš°μ € μ’…λ£Œ or μ‹œκ°„ 초과 or session.invalidate()

πŸ”₯ 2단계. μ„Έμ…˜μ˜ λ©”λͺ¨λ¦¬ 문제 (μ‹€μ œ 싀무 이슈)

❗ 문제 상황: μ„Έμ…˜μ΄ λ„ˆλ¬΄ 많으면?


πŸ“¦ μ„Έμ…˜ λ©”λͺ¨λ¦¬ 흐름

[μ‚¬μš©μž 접속] β†’ Session 객체 생성
β†’ setAttribute("loginId", "hong123");
β†’ μ„œλ²„ λ©”λͺ¨λ¦¬μ— 둜그인 정보 μ €μž₯됨
β†’ 아무 행동 없이 30λΆ„ 지남 β†’ μ„Έμ…˜ μ‚­μ œ (GC λŒ€μƒ)

βœ… μ„Έμ…˜ μœ μ§€ μ‹œκ°„ (Session Timeout)

ν•­λͺ© μ„€λͺ…
κΈ°λ³Έ μ‹œκ°„ 30λΆ„ (μ„œλ²„ 섀정에 따라 닀름)
μ„€μ • 방법 web.xml λ˜λŠ” μ½”λ“œμ—μ„œ μ„€μ • κ°€λŠ₯
μ„€μ • μ˜ˆμ‹œ Β 
<!-- web.xml -->
<session-config>
    <session-timeout>15</session-timeout> <!-- λΆ„ λ‹¨μœ„ -->
</session-config>

βœ… μ„Έμ…˜ λ©”λͺ¨λ¦¬ λˆ„μˆ˜ λ°©μ§€ μ „λž΅

μ „λž΅ μ„€λͺ…
μžλ™ 만료 μ‹œκ°„ μ„€μ • 10~30λΆ„ μΆ”μ²œ
μˆ˜λ™ μ’…λ£Œ session.invalidate() 둜 직접 μ’…λ£Œ
μ„Έμ…˜ μ΅œμ†Œν™” 큰 데이터λ₯Ό μ„Έμ…˜μ— λ„£μ§€ μ•ŠκΈ° (이미지, λͺ©λ‘ 등은 DB에 보관)
μ „μ—­ μΊμ‹œ λŒ€μ‹  둜컬 μ„Έμ…˜ μ‚¬μš© μ„œλ²„μ— λΆˆν•„μš”ν•œ 곡용 객체 보관 κΈˆμ§€

βœ… μ‹€λ¬΄μ—μ„œ 많이 ν„°μ§€λŠ” μ‹€μˆ˜

session.setAttribute("productList", hugeList); // ❌ λ©”λͺ¨λ¦¬ ν„°μ§ˆ μˆ˜λ„ 있음

β†’ λŒ€λŸ‰ κ°μ²΄λŠ” DBλ‚˜ μΊμ‹œμ— μ €μž₯ν•˜κ³ , μ„Έμ…˜μ—λŠ” ID만 μ €μž₯ν•˜μ„Έμš”!


🌐 3단계. λŒ€κ·œλͺ¨ μ‚¬μš©μž λŒ€λΉ„: μ„Έμ…˜ ν΄λŸ¬μŠ€ν„°λ§ μ „λž΅


🧩 μ™œ ν΄λŸ¬μŠ€ν„°λ§μ΄ ν•„μš”ν•΄?

πŸ’¬ μ›Ήμ‚¬μ΄νŠΈμ— μ ‘μ†ν•œ μ‚¬μš©μžκ°€ 10만 λͺ…이라면…?

μ„œλ²„ ν•˜λ‚˜λ‘œλŠ” 감당 λΆˆκ°€! κ·Έλž˜μ„œ μ—¬λŸ¬ λŒ€μ˜ μ„œλ²„λ₯Ό λ¬Άμ–΄μ„œ μ²˜λ¦¬ν•˜λŠ”λ°,

μ΄λ•Œ μ„œλ²„λΌλ¦¬ μ„Έμ…˜μ„ κ³΅μœ ν•΄μ•Ό 둜그인 정보가 μœ μ§€λ¨.


βœ… μ„Έμ…˜ ν΄λŸ¬μŠ€ν„°λ§ ꡬ쑰

[μ‚¬μš©μž 둜그인]
β†’ μ„œλ²„ A에 접속 β†’ μ„Έμ…˜ 생성

[λ‹€μŒ μš”μ²­μ€ μ„œλ²„ B둜 갔을 λ•Œ]
β†’ B도 둜그인 μƒνƒœλ₯Ό μ•Œμ•„μ•Ό 함!

β†’ A와 Bκ°€ μ„Έμ…˜ 정보λ₯Ό κ³΅μœ ν•΄μ•Ό 함 β†’ 이것이 "μ„Έμ…˜ ν΄λŸ¬μŠ€ν„°λ§"

βœ… λŒ€ν‘œμ μΈ μ„Έμ…˜ ν΄λŸ¬μŠ€ν„°λ§ 방식

방식 μ„€λͺ… νŠΉμ§•
Sticky Session ν•œ μ‚¬μš©μžλŠ” 무쑰건 같은 μ„œλ²„λ‘œ μœ μ§€ κ΅¬ν˜„ 쉬움, λΆ€ν•˜ λΆˆκ· ν˜• λ°œμƒ
Session Replication λͺ¨λ“  μ„œλ²„κ°€ μ„Έμ…˜μ„ λ³΅μ œν•΄ 곡유 신뒰도 λ†’μŒ, λ„€νŠΈμ›Œν¬ λΆ€ν•˜ ↑
External Session Storage Redis, DB λ“± μ™ΈλΆ€ μ €μž₯μ†Œμ— μ„Έμ…˜ μ €μž₯ μ„±λŠ₯/ν™•μž₯μ„± 우수, κ°€μž₯ μΆ”μ²œ

☁️ ν΄λΌμš°λ“œ/λŒ€κΈ°μ—…μ—μ„œ μ“°λŠ” 방식

λŒ€λΆ€λΆ„ Redis + Spring Session ꡬ쑰 μ‚¬μš©

β†’ μ„œλ²„ μˆ˜μ‹­ λŒ€λ‘œ ν™•μž₯해도 μ„Έμ…˜ 곡유 OK

β†’ GC 뢀담도 쀄고, ν™•μž₯μ„± 졜고!


🎯 4단계. λ©΄μ ‘ 포인트 정리

질문 λͺ¨λ²” λ‹΅λ³€ μš”μ•½
μ„Έμ…˜μ€ 어디에 μ €μž₯λ˜λ‚˜μš”? WAS μ„œλ²„ λ©”λͺ¨λ¦¬μ— μ €μž₯λ©λ‹ˆλ‹€
μ„Έμ…˜μ΄ λ§Žμ•„μ§€λ©΄ μ–΄λ–€ λ¬Έμ œκ°€ μƒκΈ°λ‚˜μš”? λ©”λͺ¨λ¦¬ λΆ€μ‘±, GC λΆ€λ‹΄, μ„œλ²„ 느렀짐
μ„Έμ…˜ νƒ€μž„μ•„μ›ƒμ€ μ–΄λ–»κ²Œ μ„€μ •ν•˜λ‚˜μš”? web.xml λ˜λŠ” session.setMaxInactiveInterval()
λŒ€κ·œλͺ¨ μ‹œμŠ€ν…œμ—μ„œ μ„Έμ…˜ κ³΅μœ λŠ” μ–΄λ–»κ²Œ ν•˜λ‚˜μš”? μ„Έμ…˜ ν΄λŸ¬μŠ€ν„°λ§ (Replication, External Store)
μ„Έμ…˜μ„ GC둜 μ •λ¦¬ν•˜λ €λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Ό ν•˜λ‚˜μš”? νƒ€μž„μ•„μ›ƒ λ˜λŠ” invalidate() 호좜, μ°Έμ‘° 제거 ν•„μˆ˜

βœ… 마무리 μš”μ•½ν‘œ

ν•­λͺ© μ„€λͺ… λ©”λͺ¨λ¦¬ 영ν–₯
Session μ‚¬μš©μžλ³„ 데이터 μ €μž₯μ†Œ μ‚¬μš©μž 수 많으면 λ©”λͺ¨λ¦¬ 폭증
Timeout μ„€μ • μžλ™ μ‚­μ œ κ°€λŠ₯ 섀정이 μ§§μ„μˆ˜λ‘ μ•ˆμ „
ν΄λŸ¬μŠ€ν„°λ§ μ„œλ²„ κ°„ μ„Έμ…˜ 곡유 ν™•μž₯μ„± ↑, λ³΅μž‘λ„ ↑
External μ €μž₯μ†Œ Redis, DB둜 μ„Έμ…˜ 이동 λ©”λͺ¨λ¦¬ ↓, 속도 ↑

βœ… PART 4.2 응닡 μΊμ‹œ(Cache-Control)와 μ„œλ²„ λ©”λͺ¨λ¦¬ μ ˆμ•½

β€œλΈŒλΌμš°μ €μ™€ μ„œλ²„κ°€ λ˜‘λ˜‘ν•˜κ²Œ μΊμ‹œλ₯Ό μ¨μ„œ λΉ λ₯΄κ²Œ λ³΄μ—¬μ£ΌλŠ” 법 + λ©”λͺ¨λ¦¬λ„ 아끼기”


🟒 1단계. μΊμ‹œ(Cache)λž€ 뭐야?

πŸ’¬ μΊμ‹œλž€ 자주 μ“°λŠ” 데이터λ₯Ό 미리 μ €μž₯ν•΄λ‘λŠ” μ €μž₯μ†Œμ•Ό.

μ›Ήμ—μ„œλŠ” β€œλΈŒλΌμš°μ €β€ λ˜λŠ” β€œν”„λ‘μ‹œ μ„œλ²„β€κ°€

이전 κ²°κ³Όλ₯Ό μ €μž₯해두고, λ˜‘κ°™μ€ μš”μ²­μ΄ 였면 μƒˆλ‘œ μ•ˆ λΆˆλŸ¬μ˜€λŠ” κΈ°μˆ μ΄μ•Ό!


βœ… μ˜ˆμ‹œ

[처음 μš”μ²­]
β†’ μ„œλ²„μ—μ„œ 이미지 전솑 (logo.png)

[λ‹€μŒ μš”μ²­]
β†’ λΈŒλΌμš°μ €κ°€ "μ–΄? 전에 받은 κ±°λž‘ κ°™λ„€!" β†’ μ €μž₯된 κ±Έ κ·ΈλŒ€λ‘œ 씀!

β†’ μ„œλ²„μ— λ‹€μ‹œ μš”μ²­ X β†’ 속도 ↑, νŠΈλž˜ν”½ ↓

🧠 μΊμ‹œκ°€ μ€‘μš”ν•œ 이유

ν•­λͺ© 효과
속도 ↑ μ„œλ²„ μž¬μš”μ²­ 없이 λΉ λ₯΄κ²Œ λ³΄μ—¬μ€Œ
νŠΈλž˜ν”½ ↓ μ„œλ²„ λ¦¬μ†ŒμŠ€ μ ˆμ•½
λ©”λͺ¨λ¦¬ 관리 ↑ μ„œλ²„μ—μ„œ λ™μΌν•œ 데이터λ₯Ό μ—¬λŸ¬ 번 μƒμ„±ν•˜μ§€ μ•ŠμŒ

πŸ“¦ 2단계. HTTP μΊμ‹œ 헀더 + GCμ™€μ˜ 관계


βœ… 핡심 μΊμ‹œ 헀더

헀더 μ„€λͺ…
Cache-Control μ–΄λ–»κ²Œ μΊμ‹œν• μ§€ μ„€μ •
Expires μ–Έμ œκΉŒμ§€ μΊμ‹œ μœ νš¨ν•œμ§€
ETag 파일이 λ°”λ€Œμ—ˆλŠ”μ§€ ν™•μΈν•˜λŠ” ID
Last-Modified λ§ˆμ§€λ§‰ μˆ˜μ • μ‹œκ°„ (λΉ„κ΅μš©)

βœ… μ˜ˆμ‹œ: μΊμ‹œλ₯Ό 1μ‹œκ°„ μœ μ§€ν•˜λŠ” 헀더

Cache-Control: public, max-age=3600

β†’ 3600초(1μ‹œκ°„) λ™μ•ˆ λΈŒλΌμš°μ €κ°€ μƒˆλ‘œ μš”μ²­ν•˜μ§€ μ•Šκ³ , μ €μž₯된 νŒŒμΌμ„ κ·ΈλŒ€λ‘œ 씀


πŸ” μ„œλ²„ λ©”λͺ¨λ¦¬(GC) κ΄€μ μ—μ„œ μ™œ μ’‹μ„κΉŒ?

ν•­λͺ© μ„€λͺ…
정적 파일 μΊμ‹œ μ„œλ²„κ°€ 맀번 파일 읽을 ν•„μš” μ—†μŒ β†’ λ©”λͺ¨λ¦¬/CPU λΆ€λ‹΄ ↓
동적 νŽ˜μ΄μ§€ μΊμ‹œ λ™μΌν•œ 데이터 λ Œλ”λ§ κ²°κ³Όλ₯Ό μž¬μ‚¬μš© β†’ GC λŒ€μƒ 객체 생성 ↓
GC 효율 λ§€ μš”μ²­λ§ˆλ‹€ μƒˆλ‘œ 객체 생성 μ•ˆ ν•˜λ―€λ‘œ GC λ°œμƒ 횟수 ↓

βš™οΈ 3단계. 정적 λ¦¬μ†ŒμŠ€ vs 동적 νŽ˜μ΄μ§€ μΊμ‹œ μ „λž΅


βœ… 정적 λ¦¬μ†ŒμŠ€ (이미지, CSS, JS λ“±)

ν•­λͺ© νŠΉμ§•
λ°”λ€Œμ§€ μ•ŠμŒ 자주 μ•ˆ λ°”λ€œ (logo.png, app.css λ“±)
μΊμ‹œ μ „λž΅ 였래 μ €μž₯해도 μ•ˆμ „ (max-age=31536000 λ“±)
GC 영ν–₯ μΊμ‹œ μ„œλ²„ or λΈŒλΌμš°μ €μ— 있음 β†’ μ„œλ²„λŠ” λ©”λͺ¨λ¦¬ μ‚¬μš© μ•ˆ 함

πŸ’‘ μ„€μ • μ˜ˆμ‹œ (Apache / Nginx)

Cache-Control: public, max-age=31536000

β†’ 1λ…„ λ™μ•ˆ λ‹€μ‹œ μ•ˆ 받아도 됨!


βœ… 동적 νŽ˜μ΄μ§€ (JSP, 둜그인 ν™”λ©΄, 검색 κ²°κ³Ό λ“±)

ν•­λͺ© νŠΉμ§•
μš”μ²­λ§ˆλ‹€ κ²°κ³Όκ°€ λ‹€λ₯Ό 수 있음 μ‚¬μš©μž μƒνƒœλ‚˜ DB에 따라 닀름
μΊμ‹œ μ „λž΅ μ•ˆ ν•˜κ±°λ‚˜ 짧게 μ„€μ •
GC 영ν–₯ λ§€ μš”μ²­λ§ˆλ‹€ 객체 생성 β†’ GC 자주 λ°œμƒ

πŸ’‘ μΊμ‹œ κΈˆμ§€ μ„€μ •

Cache-Control: no-store
Pragma: no-cache
Expires: 0

β†’ 민감 정보(둜그인, μ£Όλ¬Έ, 결제 λ“±)λŠ” μ ˆλŒ€ μΊμ‹œν•˜λ©΄ μ•ˆ 됨!


🧠 싀무 μ „λž΅ μš”μ•½

λ¦¬μ†ŒμŠ€ μœ ν˜• μΊμ‹œ μ „λž΅
이미지, JS, CSS 였래 μΊμ‹œ (max-age)
API 응닡 ETag, Last-Modified ν™œμš©
둜그인/μž₯λ°”κ΅¬λ‹ˆ no-cache, no-store μ„€μ •
검색 κ²°κ³Ό 짧은 μΊμ‹œ or μ‚¬μš©μžλ³„ Key μΊμ‹œ (예: Redis)

πŸŽ“ 4단계. λ©΄μ ‘ 포인트 총정리

질문 λͺ¨λ²” λ‹΅λ³€ μš”μ•½
HTTP μΊμ‹œλŠ” μ™œ ν•„μš”ν•œκ°€μš”? 속도 ↑, νŠΈλž˜ν”½ ↓, μ„œλ²„ λ©”λͺ¨λ¦¬ μ‚¬μš© ↓
GC와 μΊμ‹œλŠ” μ–΄λ–€ 관계가 μžˆλ‚˜μš”? μΊμ‹œλ₯Ό μ“°λ©΄ 객체 생성 쀄어듀어 GC νšŸμˆ˜λ„ ↓
정적 λ¦¬μ†ŒμŠ€λŠ” μ™œ 였래 μΊμ‹œν•˜λ‚˜μš”? λ°”λ€Œμ§€ μ•ŠκΈ° λ•Œλ¬Έμ— λ‹€μ‹œ 받을 ν•„μš” μ—†μŒ
동적 νŽ˜μ΄μ§€λŠ” μ™œ μΊμ‹œν•˜λ©΄ μ•ˆ λ˜λ‚˜μš”? μ‚¬μš©μžλ§ˆλ‹€ κ²°κ³Όκ°€ λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— λ³΄μ•ˆ μœ„ν—˜ 있음
ETagλŠ” λ­”κ°€μš”? λ¦¬μ†ŒμŠ€ λ³€κ²½ μ—¬λΆ€ ν™•μΈμš© 고유 ID (λ³€κ²½ μ‹œ μƒˆ μš”μ²­ ν—ˆμš©)

βœ… 마무리 μš”μ•½ν‘œ

ν•­λͺ© μ„€λͺ… λ©”λͺ¨λ¦¬ 효과
Cache-Control μΊμ‹œ μ—¬λΆ€/μ‹œκ°„μ„ μ§€μ •ν•˜λŠ” HTTP 헀더 μž¬μš”μ²­ λ°©μ§€λ‘œ λ©”λͺ¨λ¦¬ ↓
정적 λ¦¬μ†ŒμŠ€ μΊμ‹œ 적극 μ‚¬μš© (max-age) μ„œλ²„ μš”μ²­ κ°μ†Œ, GC 쀄어듦
동적 νŽ˜μ΄μ§€ 민감 μ •λ³΄λŠ” no-store μ„€μ • λ³΄μ•ˆ κ°•ν™”, GC μœ λ„ κ°€λŠ₯
GC 관점 μΊμ‹œλ‘œ 인해 μƒμ„±λ˜λŠ” 객체 ↓ Full GC 횟수 κ°μ†Œ

βœ… PART 4.3 λ³΄μ•ˆ + λ©”λͺ¨λ¦¬ 관점: XSS/CSRF vs ν•„ν„° 처리 ꡬ쑰


🟒 1단계. ν•„ν„°(Filter)λž€ 뭐야? 쀑학생도 μ΄ν•΄ν•˜λŠ” 핡심 κ°œλ…

πŸ’¬ ν•„ν„°(Filter)λŠ” μ›Ή μš”μ²­(Request)κ³Ό 응닡(Response) μ‚¬μ΄μ—μ„œ

쀑간에 λΌμ–΄λ“€μ–΄μ„œ κ²€μ‚¬ν•˜κ±°λ‚˜ κ°€κ³΅ν•˜λŠ” μžλ°” μ½”λ“œμ•Ό.


πŸ“¦ λΉ„μœ 

[μ‚¬μš©μž μš”μ²­] β†’ (πŸ›‘οΈ ν•„ν„° 검사) β†’ 컨트둀러 μ‹€ν–‰ β†’ (πŸ›‘οΈ ν•„ν„° 마무리 처리) β†’ 응닡

예λ₯Ό λ“€μ–΄:


βœ… ν•„ν„° λ™μž‘ ꡬ쑰

public class MyFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        // πŸ’‘ μš”μ²­ κ°€λ‘œμ±„κΈ°
        System.out.println("μš”μ²­ μ „ 처리");

        chain.doFilter(request, response); // πŸ“Œ λ‹€μŒ λ‹¨κ³„λ‘œ 전달

        // πŸ’‘ 응닡 κ°€λ‘œμ±„κΈ°
        System.out.println("응닡 ν›„ 처리");
    }
}

🧠 2단계. ν•„ν„° 체인(Filter Chain)의 λ©”λͺ¨λ¦¬ 흐름

βœ… FilterChainμ΄λž€?

μ—¬λŸ¬ 개의 ν•„ν„°κ°€ μˆœμ„œλŒ€λ‘œ μ‹€ν–‰λ˜κ²Œ ν•΄μ£ΌλŠ” ν•„ν„° μ—°κ²° 고리


πŸ” μ˜ˆμ‹œ 흐름 (3개 ν•„ν„°κ°€ μžˆμ„ λ•Œ)

[μ‚¬μš©μž μš”μ²­]
 β†’ AuthFilter
   β†’ XSSFilter
     β†’ EncodingFilter
       β†’ Controller μ‹€ν–‰
     ← 응닡 처리
   ← 응닡 처리
 ← 응닡 처리

🧠 λ©”λͺ¨λ¦¬ 흐름 μ„€λͺ…

ν•­λͺ© μ„€λͺ…
ν•„ν„° 객체 μ„œλ²„ μ‹œμž‘ μ‹œ 1번만 생성 (싱글톀)
Request/Response 객체 μš”μ²­λ§ˆλ‹€ 생성 (λ§€ μš”μ²­λ§ˆλ‹€ μƒˆ 객체)
ν•„ν„° 체인 μ‹€ν–‰ μ‹œ 각 ν•„ν„°κ°€ request/response 객체λ₯Ό μ°Έμ‘°ν•˜κ±°λ‚˜ κ°μ‹Έμ„œ 전달

β†’ μš”μ²­μ΄ λ§Žμ•„μ§€λ©΄ ν•„ν„°κ°€ 계속 requestλ₯Ό μ‘°μž‘ν•˜λ―€λ‘œ λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰ 증가 κ°€λŠ₯


πŸ” 3단계. XSS/CSRF λ³΄μ•ˆ ν•„ν„° κ΅¬ν˜„ ꡬ쑰


βœ… XSS (Cross Site Scripting)λž€?

πŸ’₯ μ‚¬μš©μžκ°€ μž…λ ₯ν•œ 값에

λ‹€λ₯Έ μ‚¬μš©μžμ˜ λΈŒλΌμš°μ €μ—μ„œ μ‹€ν–‰λ˜κ²Œ ν•˜λŠ” 곡격

μ˜ˆμ‹œ 곡격 μ½”λ“œ:

<input value="<script>alert('ν•΄ν‚Ή!')</script>">

βœ… λ°©μ–΄ 방법: μž…λ ₯κ°’μ—μ„œ <, >, " 등을 ν•„ν„°λ‘œ 차단

public class XSSFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        // βœ… 감싼 request 객체λ₯Ό 전달
        chain.doFilter(new XSSRequestWrapper((HttpServletRequest)request), response);
    }
}

βœ… XSSRequestWrapper μ˜ˆμ‹œ

public class XSSRequestWrapper extends HttpServletRequestWrapper {
    public XSSRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        return sanitize(value);
    }

    private String sanitize(String input) {
        return input.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
    }
}

βœ… λ©”λͺ¨λ¦¬ μΈ‘λ©΄ 핡심

ν•­λͺ© μ„€λͺ…
Wrapper 객체 μš”μ²­λ§ˆλ‹€ μƒˆλ‘œ 생성됨 (XSSRequestWrapper)
λ©”λͺ¨λ¦¬ 증가 μš”μ²­ μˆ˜κ°€ λ§Žμ„μˆ˜λ‘ Wrapper 객체도 λ§Žμ•„μ§
GC 영ν–₯ 응닡 ν›„ GC λŒ€μƒμ΄ λ˜μ§€λ§Œ, 응닡 쀑 였λ₯˜ λ°œμƒ μ‹œ λˆ„μˆ˜ κ°€λŠ₯μ„± 쑴재

βœ… CSRF (Cross Site Request Forgery)λž€?

πŸ’₯ μ‚¬μš©μžκ°€ λͺ¨λ₯΄κ²Œ λ‹€λ₯Έ μ‚¬μ΄νŠΈμ—μ„œ μœ„μ‘°λœ μš”μ²­μ„ 보냄

예: 둜그인 μƒνƒœμ—μ„œ κ³΅κ²©μžκ°€ μžλ™ μš”μ²­μ„ 보내 데이터 μ‚­μ œ


βœ… λ°©μ–΄ 방법: CSRF 토큰을 λ°œκΈ‰ν•˜κ³ , μš”μ²­ μ‹œ 검증

String token = UUID.randomUUID().toString();
session.setAttribute("CSRF_TOKEN", token);

🧠 ν•„ν„°μ—μ„œ λ³΄μ•ˆ 검사 μ‹œ μ£Όμ˜ν•  λ©”λͺ¨λ¦¬ 포인트

ν•­λͺ© μ„€λͺ…
XSS ν•„ν„° λ§€ μš”μ²­λ§ˆλ‹€ request 래퍼 객체 생성 β†’ GC λΆ€λ‹΄ 주의
CSRF ν•„ν„° μ„Έμ…˜μ— 토큰 μ €μž₯ β†’ μ„Έμ…˜ λ©”λͺ¨λ¦¬ λ‚­λΉ„ λ°©μ§€ ν•„μˆ˜
닀단계 ν•„ν„° ꡬ쑰 FilterChain이 κΉŠμ„μˆ˜λ‘ 응닡 속도/λ©”λͺ¨λ¦¬ μ†ŒλΉ„β†‘

πŸŽ“ 4단계. λ©΄μ ‘ 포인트 정리

질문 λͺ¨λ²” λ‹΅λ³€ 포인트
ν•„ν„°λŠ” λ©”λͺ¨λ¦¬μ μœΌλ‘œ μ–΄λ–€ κ΅¬μ‘°μΈκ°€μš”? ν•„ν„° μžμ²΄λŠ” 싱글톀, request/responseλŠ” μš”μ²­λ§ˆλ‹€ μƒˆλ‘œ 생성됨
XSS ν•„ν„°λŠ” μ–΄λ–»κ²Œ λ™μž‘ν•˜λ‚˜μš”? requestλ₯Ό κ°μ‹ΈλŠ” Wrapper 객체λ₯Ό λ§Œλ“€μ–΄ input 값을 정리함
ν•„ν„° 체인은 μ–΄λ–»κ²Œ μž‘λ™ν•˜λ‚˜μš”? μ—¬λŸ¬ ν•„ν„°κ°€ μˆœμ„œλŒ€λ‘œ μ—°κ²°λ˜μ–΄ ν•˜λ‚˜μ”© μš”μ²­μ„ μ²˜λ¦¬ν•˜κ³  λ„˜κΉ€
ν•„ν„°κ°€ λ§Žμ•„μ§€λ©΄ μ–΄λ–€ λ¬Έμ œκ°€ μƒκΈ°λ‚˜μš”? 처리 μ‹œκ°„ 증가 + μš”μ²­ 객체가 계속 κ°μ‹Έμ§€λ―€λ‘œ λ©”λͺ¨λ¦¬ λΆ€ν•˜β†‘
λ³΄μ•ˆ ν•„ν„°λ₯Ό λ§Œλ“€ λ•Œ μ£Όμ˜ν•  점은? μ“°λ ˆλ“œ μ„Έμ΄ν”„ν•˜κ²Œ μ„€κ³„ν•˜κ³ , Wrapper 객체 생λͺ…μ£ΌκΈ° κ³ λ €

βœ… 마무리 μš”μ•½ν‘œ

ν•­λͺ© μ„€λͺ… λ©”λͺ¨λ¦¬ 영ν–₯
Filter μš”μ²­ μ „/후에 μ‹€ν–‰λ˜λŠ” 검사기 객체 감싸기 λ§Žμ•„μ§€λ©΄ λ©”λͺ¨λ¦¬ μ‚¬μš© ↑
FilterChain 순차 μ—°κ²° ꡬ쑰 ν•„ν„° λ§Žμ„μˆ˜λ‘ μŠ€νƒ 깊이 ↑
XSS Wrapper μš”μ²­λ§ˆλ‹€ 생성 정리 μ•ˆ ν•˜λ©΄ λˆ„μˆ˜ κ°€λŠ₯
CSRF 토큰 μ„Έμ…˜μ— μ €μž₯ 유효 μ‹œκ°„ μ œν•œ μ„€μ • ν•„μˆ˜