** πŸ“Œ3-1단계: Ajax λ„€νŠΈμ›Œν¬ μ„±λŠ₯ μ΅œμ ν™” **

πŸ’‘ Ajaxκ°€ μ„œλ²„μ™€ 톡신할 λ•Œ β€œλ” λΉ λ₯΄κ³  νš¨μœ¨μ μœΌλ‘œβ€ μž‘λ™ν•˜κ²Œ λ§Œλ“œλŠ” κΈ°μˆ λ“€μž…λ‹ˆλ‹€.


βœ… 1. μ™œ λ„€νŠΈμ›Œν¬ μ΅œμ ν™”κ°€ ν•„μš”ν• κΉŒ?

🧠 κ·Έλž˜μ„œ μš°λ¦¬λŠ” λ‹€μŒμ„ λͺ©ν‘œλ‘œ ν•΄μš”:

λͺ©ν‘œ μ„€λͺ…
⏱ λΉ λ₯΄κ²Œ λ„€νŠΈμ›Œν¬ λΉ„μš© 쀄이기 (전솑 μ‹œκ°„ 단좕)
πŸ“¦ μž‘κ²Œ 데이터 크기λ₯Ό 쀄이기 (μ••μΆ•)
πŸ” 적게 같은 μš”μ²­μ€ λ°˜λ³΅ν•˜μ§€ μ•ŠκΈ° (μΊμ‹œ ν™œμš©)

βœ… 2. HTTP Keep-Alive

πŸ“¦ κ°œλ…

ν•˜λ‚˜μ˜ μ—°κ²°λ‘œ μ—¬λŸ¬ μš”μ²­μ„ μ£Όκ³ λ°›λŠ” 기술


πŸ“Œ μ›λž˜ 방식 (λΉ„νš¨μœ¨)

[λΈŒλΌμš°μ €] ---μ—°κ²°μš”μ²­---> [μ„œλ²„]
         <---응닡--- (μ—°κ²° μ’…λ£Œ)
[λΈŒλΌμš°μ €] ---λ‹€μ‹œ μ—°κ²°---> [μ„œλ²„]
         <---응닡--- (μ—°κ²° μ’…λ£Œ)
(반볡)

πŸ‘‰ μš”μ²­ν•  λ•Œλ§ˆλ‹€ 연결을 μƒˆλ‘œ λ§Œλ“¬ β†’ 느림, λ‚­λΉ„


βœ… Keep-Alive 방식 (효율)

[λΈŒλΌμš°μ €] ---μ—°κ²°μš”μ²­ (Keep-Alive)--->
[μ„œλ²„]     <---응닡 (Keep-Alive μœ μ§€)
⏱ 이후 μš”μ²­λ„ 같은 μ—°κ²°λ‘œ 처리

πŸ”§ μž₯점


βœ… 3. Gzip μ••μΆ•

πŸ“¦ κ°œλ…

μ„œλ²„μ—μ„œ 응닡 데이터λ₯Ό μ••μΆ•ν•΄μ„œ λ³΄λ‚΄λŠ” 기술


μ˜ˆμ‹œ

μ„œλ²„ 응닡: {"user":"hong", "email":"hong@gmail.com"}
보톡: 60λ°”μ΄νŠΈ
Gzip μ‚¬μš© μ‹œ: 20λ°”μ΄νŠΈλ‘œ 압좕됨 πŸ“‰

πŸ”§ μž₯점


πŸ’‘ μ‚¬μš© 방법 (μ„œλ²„ μ„€μ •)

# Apache μ˜ˆμ‹œ
AddOutputFilterByType DEFLATE text/html text/css application/javascript
# Nginx μ˜ˆμ‹œ
gzip on;
gzip_types text/plain text/css application/json;

βœ… 4. HTTP/2 + Server Push

πŸ“¦ κ°œλ…

HTTP/2λŠ” κΈ°μ‘΄ HTTP의 μ—…κ·Έλ ˆμ΄λ“œ 버전 (더 λΉ λ₯΄κ³  병렬적)


νŠΉμ§•

기술 μ„€λͺ…
ν•˜λ‚˜μ˜ μ—°κ²°λ‘œ μ—¬λŸ¬ μš”μ²­ κ°€λŠ₯ 기쑴은 1κ°œμ”© β†’ μ΄μ œλŠ” 병렬 처리
Header μ••μΆ• μš”μ²­ 헀더도 μž‘κ²Œ 전솑
Server Push ν΄λΌμ΄μ–ΈνŠΈκ°€ μš”μ²­ν•˜μ§€ μ•Šμ•„λ„, μ„œλ²„κ°€ 미리 μžλ°”μŠ€ν¬λ¦½νŠΈ/μŠ€νƒ€μΌμ„ ν‘Έμ‹œ κ°€λŠ₯

πŸ’‘ 싀무 적용 μ˜ˆμ‹œ

λΈŒλΌμš°μ €κ°€ HTML μš”μ²­ β†’ μ„œλ²„κ°€ HTML + CSS + JS μ „λΆ€ ν•œ λ²ˆμ— 전솑
β†’ 첫 ν™”λ©΄ λ‘œλ”©μ΄ 훨씬 빨라짐 πŸš€

βœ… 5. 캐싱 μ „λž΅ (Cache-Control)

πŸ“¦ μΊμ‹œλž€?

λ˜‘κ°™μ€ 데이터λ₯Ό λ‹€μ‹œ μš”μ²­ν•˜μ§€ μ•Šλ„λ‘ 미리 μ €μž₯ν•΄λ‘λŠ” 것

πŸ“Š μ˜ˆμ‹œ

βœ… 첫 μš”μ²­ β†’ μ„œλ²„μ—μ„œ JSON λ°›μŒ
βœ… 두 번째 μš”μ²­ β†’ μ €μž₯된 μΊμ‹œμ—μ„œ λ°”λ‘œ κ°€μ Έμ˜΄ (0.001초)

πŸ”§ Cache-Control 헀더

Cache-Control: max-age=3600

βœ… 6. ETag & If-Modified-Since

πŸ“¦ ETag (Entity Tag)

β€œμ΄ 파일이 λ°”λ€Œμ—ˆλŠ”μ§€ μ•ˆ λ°”λ€Œμ—ˆλŠ”μ§€ ν™•μΈν•˜λŠ” 고유 μ½”λ“œβ€


πŸ“Š λ™μž‘ μˆœμ„œ

  1. λΈŒλΌμš°μ €κ°€ μ„œλ²„μ— μš”μ²­ β†’ μ„œλ²„κ°€ 응닡 + ETag ν•¨κ»˜ 보냄
  2. λΈŒλΌμš°μ €λŠ” ETagλ₯Ό μ €μž₯함
  3. λ‚˜μ€‘μ— 또 μš”μ²­ν•  λ•Œ:

     If-None-Match: "etag123"
    
  4. μ„œλ²„κ°€ 파일이 κ·ΈλŒ€λ‘œλΌλ©΄ β†’ 응닡 없이 304 Not Modified만 보냄

    β†’ 데이터 μž¬μ „μ†‘ 없이 μΊμ‹œ μ‚¬μš©


πŸ’‘ μž₯점


βœ… 전체 μš”μ•½ μΉ΄λ“œ

기술 μ‰½κ²Œ μ„€λͺ… μ„±λŠ₯ 효과
Keep-Alive 연결을 λŠμ§€ μ•Šκ³  μž¬μ‚¬μš© ⏱ μ—°κ²° 속도 ν–₯상
Gzip 응닡 μ••μΆ• πŸ“¦ μ „μ†‘λŸ‰ κ°μ†Œ
HTTP/2 μš”μ²­μ„ ν•œ λ²ˆμ— 병렬 처리 πŸš€ λΉ λ₯Έ 병렬 전솑
Server Push μ„œλ²„κ°€ ν•„μš”ν•œ νŒŒμΌμ„ 미리 쀌 🎁 λ‘œλ”© 속도 ν–₯상
μΊμ‹œ 같은 μš”μ²­μ„ λ‹€μ‹œ ν•˜μ§€ μ•ŠμŒ πŸ” μš”μ²­ 수 κ°μ†Œ
ETag 변경됐을 λ•Œλ§Œ μ„œλ²„ 응닡 🧠 슀마트 μš”μ²­ μ œμ–΄

βœ… λ©΄μ ‘ 질문 μ˜ˆμ‹œ + ν•΄μ„€

❓ Q. Ajax μ„±λŠ₯ μ΅œμ ν™”λ₯Ό μœ„ν•΄ μ‚¬μš©ν•  수 μžˆλŠ” λ„€νŠΈμ›Œν¬ 계측 κΈ°μˆ μ€?

βœ… A.

βœ… 3-2단계: Ajax μš”μ²­ μ΅œμ ν™” (Debounce / Throttle / 병합 / 쀑볡 제거)

μ‚¬μš©μžκ°€ λΉ λ₯΄κ²Œ νƒ€μ΄ν•‘ν•˜κ±°λ‚˜ μŠ€ν¬λ‘€ν•  λ•Œλ§ˆλ‹€ Ajaxλ₯Ό ν˜ΈμΆœν•˜λ©΄β€¦

❗ μ„œλ²„λŠ” ν„°μ§€κ³ , μ„±λŠ₯은 λ–¨μ–΄μ§€κ³ , 결과도 꼬이게 λ©λ‹ˆλ‹€.

κ·Έλž˜μ„œ μš°λ¦¬λŠ” β€œμ§€λŠ₯적으둜 μš”μ²­μ„ μ€„μ΄λŠ” 방법”을 λ°°μ›Œμ•Ό ν•΄μš”.


βœ… 1. μ™œ μš”μ²­ μ΅œμ ν™”κ°€ ν•„μš”ν• κΉŒ?

πŸ“Œ μ˜ˆμ‹œ: κ²€μƒ‰μ°½μ—μ„œ 타이핑할 λ•Œλ§ˆλ‹€ Ajax μš”μ²­μ„ 보낸닀면?

πŸ’£ λ„ˆλ¬΄ λ§Žμ€ μš”μ²­ β†’ μ„œλ²„ 터짐

⚠️ 응닡 μˆœμ„œκ°€ κΌ¬μ—¬μ„œ 결과도 잘λͺ» λ‚˜μ˜¬ 수 있음


βœ… 2. Debounce (λ””λ°”μš΄μŠ€)

❗ β€œλ§ˆμ§€λ§‰ μž…λ ₯ 이후 일정 μ‹œκ°„ κΈ°λ‹€λ Έλ‹€κ°€ λ”± 1번만 싀행”


πŸ“– μ‰¬μš΄ μ„€λͺ…:

쀑학생이 검색창에 νƒ€μžλ₯Ό μΉ  λ•Œ, μž…λ ₯ 끝날 λ•ŒκΉŒμ§€ κΈ°λ‹€λ Έλ‹€κ°€ Ajaxλ₯Ό 1번만 보냄


πŸ“¦ μ˜ˆμ‹œ μ½”λ“œ

function debounce(fn, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer); // 이전 타이머 μ·¨μ†Œ
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

const searchAjax = debounce(function() {
  fetch("/search?q=" + input.value);
}, 500);


βœ… μ‚¬μš© μ˜ˆμ‹œ


βœ… 3. Throttle (μŠ€λ‘œν‹€)

❗ β€œμ΅œλŒ€ μ΄ˆλ‹Ή 1번만 μ‹€ν–‰ β€” λ„ˆλ¬΄ 자주 μ‹€ν–‰λ˜μ§€ μ•Šλ„λ‘ μ œμ–΄β€


πŸ“– μ‰¬μš΄ μ„€λͺ…

β€œμ‚¬μš©μžκ°€ 아무리 마우슀λ₯Ό νœ˜μ €μ–΄λ„, 1μ΄ˆμ— ν•œ 번만 Ajax μš”μ²­ 보내기”


πŸ“¦ μ˜ˆμ‹œ μ½”λ“œ

function throttle(fn, limit) {
  let lastCall = 0;
  return function (...args) {
    const now = Date.now();
    if (now - lastCall >= limit) {
      lastCall = now;
      fn.apply(this, args);
    }
  };
}

const throttledScroll = throttle(function() {
  fetch("/load/more");
}, 1000);

βœ… μ‚¬μš© μ˜ˆμ‹œ


βœ… 4. μš”μ²­ 병합 (Batching)

μ—¬λŸ¬ μš”μ²­μ„ λͺ¨μ•„μ„œ ν•œ λ²ˆμ— λ³΄λ‚΄λŠ” 기술


πŸ“– μ‰¬μš΄ μ„€λͺ…

β€œμΉœκ΅¬ 10λͺ…이 μ•„μ΄μŠ€ν¬λ¦Ό ν•˜λ‚˜μ”© μ‹œν‚¬ λ•Œ,

πŸ‘‰ ν•œ μ‚¬λžŒμ΄ 10개λ₯Ό ν•œ λ²ˆμ— μ£Όλ¬Έν•˜λ©΄ λΉ λ₯΄κ³  효율적!”


πŸ“¦ μ˜ˆμ‹œ

// 3개의 μš”μ²­μ„ 1개둜 λ¬ΆκΈ°
fetch("/batch", {
  method: "POST",
  body: JSON.stringify([
    { type: "search", keyword: "JavaScript" },
    { type: "recommend", userId: "abc123" },
    { type: "popular", category: "tech" }
  ])
});

βœ… μž₯점


βœ… 5. 쀑볡 제거 처리

같은 μš”μ²­μ΄ μ—¬λŸ¬ 번 λ°œμƒν•  경우, 이미 보낸 건 λ¬΄μ‹œν•˜κ±°λ‚˜ 쀑볡을 μ·¨μ†Œν•¨


πŸ“– μ‰¬μš΄ μ„€λͺ…

β€œμ΄λ―Έ 배달 온 짜μž₯면이 μžˆλŠ”λ° 또 μ‹œμΌ°μ–΄μš”?” β†’ 그럼 두 번째 건 μ·¨μ†Œ!


πŸ“¦ μ˜ˆμ‹œ: μš”μ²­ μ·¨μ†Œ + 쀑볡 λ°©μ§€

let controller;

function sendRequest(query) {
  if (controller) controller.abort(); // κΈ°μ‘΄ μš”μ²­ μ·¨μ†Œ
  controller = new AbortController();
  fetch(`/search?q=${query}`, { signal: controller.signal })
    .then(res => res.json())
    .then(data => console.log(data))
    .catch(err => {
      if (err.name === "AbortError") {
        console.log("쀑볡 μš”μ²­ 쀑단됨");
      }
    });
}

βœ… μ‹€μ œ UI μ‘°ν•© μ˜ˆμ‹œ

κΈ°λŠ₯ Debounce Throttle μ€‘λ³΅μ œκ±° 병합
검색 μžλ™μ™„μ„± βœ… ❌ βœ… ❌
λ¬΄ν•œ 슀크둀 ❌ βœ… βœ… ❌
μ²΄ν¬λ°•μŠ€ 선택 ν›„ μš”μ²­ βœ… ❌ βœ… βœ…

βœ… λ©΄μ ‘ 질문 μ˜ˆμ‹œ + ν•΄μ„€

❓ Q. μ‚¬μš©μžκ°€ λΉ λ₯΄κ²Œ μž…λ ₯ν•  λ•Œ μ„œλ²„μ— λ§Žμ€ μš”μ²­μ΄ λ°œμƒν•©λ‹ˆλ‹€. μ–΄λ–»κ²Œ μ²˜λ¦¬ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?

βœ… A.


βœ… 전체 μš”μ•½ μΉ΄λ“œ

기술 μ„€λͺ… μ‚¬μš© 예
Debounce μž…λ ₯이 멈좘 λ’€ 일정 μ‹œκ°„ ν›„ 1번 μ‹€ν–‰ 검색창
Throttle 일정 μ‹œκ°„λ§ˆλ‹€ μ΅œλŒ€ 1번 μ‹€ν–‰ 슀크둀 이벀트
Batching μš”μ²­μ„ λ¬Άμ–΄μ„œ ν•œ λ²ˆμ— 보냄 λ©€ν‹° μš”μ²­ 처리
쀑볡 제거 동일 μš”μ²­μ΄ 겹치면 ν•˜λ‚˜λ§Œ 처리 λΉ λ₯Έ 클릭/μž…λ ₯ λ°©μ§€

βœ… 3-3단계: Ajax 응닡 μ΅œμ ν™”

μ‚¬μš©μžκ°€ μš”μ²­ν•œ 데이터λ₯Ό μ„œλ²„κ°€ λΉ λ₯΄κ³  κ°€λ³κ²Œ, λ”± ν•„μš”ν•œ 만큼만 λ³΄λ‚΄μ€˜μ•Ό ν•©λ‹ˆλ‹€.

πŸ‘‰ 이게 λ°”λ‘œ β€œμ‘λ‹΅ μ΅œμ ν™”(Response Optimization)β€μž…λ‹ˆλ‹€!


βœ… 1. Lazy Rendering vs Pre-rendering


πŸ“Œ Lazy Rendering (μ§€μ—° λ Œλ”λ§)

❗ β€œλ³΄μ΄κΈ° μ „κΉŒμ§€λŠ” 화면에 그리지 말자!”


πŸ‘¦πŸ» μ‰¬μš΄ μ„€λͺ…

유튜브처럼 μ•„λž˜λ‘œ μŠ€ν¬λ‘€ν•˜κΈ° μ „μ—” 썸넀일이 μ•ˆ λœ¨λŠ” 것!

β†’ λˆˆμ— 보일 λ•Œλ§Œ 그리기 = μ„±λŠ₯ κ΅Ώ!


πŸ”§ 싀무 μ½”λ“œ μ˜ˆμ‹œ

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.src = entry.target.dataset.src; // 이미지 λ‘œλ”©
    }
  });
});

document.querySelectorAll('img.lazy').forEach(img => observer.observe(img));

βœ… λ©”λͺ¨λ¦¬ 쀄고, λ‘œλ”© 속도 ν–₯상!


πŸ“Œ Pre-rendering (μ„  λ Œλ”λ§)

❗ β€œν•„μš”ν•  것 κ°™μœΌλ‹ˆ 미리 화면에 κ·Έλ €λ‘μž!”


πŸ‘¦πŸ» μ‰¬μš΄ μ„€λͺ…

λ‹€μŒ νŽ˜μ΄μ§€ λ‚΄μš©μ„ 미리 λ°±κ·ΈλΌμš΄λ“œμ—μ„œ 뢈러였기

β†’ ν΄λ¦­ν•˜μžλ§ˆμž 팍 뜸! 속도 체감은 졜고!


πŸ”§ 싀무 μ˜ˆμ‹œ

// λ‹€μŒ νŽ˜μ΄μ§€ 미리 μš”μ²­
fetch("/page/2").then(res => res.text()).then(html => {
  sessionStorage.setItem("preloaded", html);
});

βœ… 비ꡐ 정리

ν•­λͺ© Lazy Rendering Pre-rendering
μ–Έμ œ κ·Έλ¦¬λ‚˜? μ‚¬μš©μžκ°€ λ³Ό λ•Œ 미리
속도 체감 μ•½κ°„ 느림 β†’ 점점 빠름 μ²˜μŒλΆ€ν„° 빠름
λ©”λͺ¨λ¦¬ μ‚¬μš© 적음 많음 (미리 λ Œλ”λ§ ν•˜λ‹ˆκΉŒ)
μ‚¬μš© 예 λ¬΄ν•œ 슀크둀, 이미지 리슀트 λ‹€μŒ νŽ˜μ΄μ§€, μΆ”μ²œ 기사 λ“±

βœ… 2. 응닡 데이터 μ΅œμ†Œν™” (μž‘κ²Œ λ§Œλ“€κΈ°)


πŸ”₯ μ™œ ν•„μš”ν•œκ°€μš”?

Ajax 응닡 데이터가 λ„ˆλ¬΄ 크면…


πŸ“¦ μ΅œμ†Œν™” μ „λž΅ 1: ν•„μš”ν•œ ν•„λ“œλ§Œ μ£ΌκΈ°

❌ λ‚˜μœ μ˜ˆμ‹œ

{
  "id": 1,
  "title": "κ²Œμ‹œκΈ€ 제λͺ©",
  "content": "λ‚΄μš©",
  "writer": "κ΄€λ¦¬μž",
  "writerEmail": "admin@gdu.com",
  "writerPhone": "010-0000-0000"
}

β†’ ν™”λ©΄μ—” 제λͺ©, μž‘μ„±μžλ§Œ μ“°λŠ”λ° 5개 ν•„λ“œλ₯Ό λ‹€ 쀌 ❌


βœ… 쒋은 μ˜ˆμ‹œ

{
  "id": 1,
  "title": "κ²Œμ‹œκΈ€ 제λͺ©",
  "writer": "κ΄€λ¦¬μž"
}

β†’ ν•„μš”ν•œ κ²ƒλ§Œ! β†’ λΉ λ₯΄κ³  가벼움!


πŸ“¦ μ΅œμ†Œν™” μ „λž΅ 2: JSON ν•„λ“œ 짧게 λ§Œλ“€κΈ°

{
  "i": 1,
  "t": "κ²Œμ‹œκΈ€ 제λͺ©",
  "w": "κ΄€λ¦¬μž"
}

β†’ βœ… 단좕 ν‚€μ²˜λŸΌ μ‚¬μš©ν•˜λ©΄ 전솑 크기 ↓


βœ… 3. Pagination (νŽ˜μ΄μ§• 처리)


πŸ“Œ κ°œλ…

❗ β€œν•œ λ²ˆμ— 10개만 λ³΄μ—¬μ£Όμžβ€


πŸ‘¦πŸ» μ‰¬μš΄ μ„€λͺ…

μΈμŠ€νƒ€κ·Έλž¨μ—μ„œ ν•œ λ²ˆμ— λͺ¨λ“  사진을 λ‹€ 보여주지 μ•Šμ£ ?

β†’ μŠ€ν¬λ‘€ν•  λ•Œλ§ˆλ‹€ μ‘°κΈˆμ”© λ‘œλ”©!


πŸ“¦ μ˜ˆμ‹œ μš”μ²­

GET /posts?page=1&size=10

βœ… μž₯점

ν•­λͺ© 효과
응닡 속도 쀄어듦
λ Œλ”λ§ μ„±λŠ₯ 빨라짐
데이터 μ „μ†‘λŸ‰ ν™• 쀄어듦

βœ… 4. μ„œλ²„ μ„±λŠ₯을 μœ„ν•œ 응닡 ꡬ쑰 섀계 팁

μ „λž΅ μ„€λͺ…
데이터 필터링 ν”„λ‘ νŠΈμ—μ„œ μ•ˆ μ“°λŠ” 건 μ„œλ²„μ—μ„œ 미리 제거
νŽ˜μ΄μ§€λ„€μ΄μ…˜ limit, offset λ˜λŠ” cursor 방식
μš”μ•½ 데이터 제곡 전체 κΈ€ 수, 총 νŽ˜μ΄μ§€ 수 등을 ν•¨κ»˜ λ°˜ν™˜
쑰건뢀 응닡 예: If-None-Match, 304 Not Modified

βœ… 5. λ©΄μ ‘ 질문 μ˜ˆμ‹œ + ν•΄μ„€

❓ Q. Ajax 응닡 μ΅œμ ν™”λ₯Ό μœ„ν•΄ μ–΄λ–€ μ „λž΅μ„ μ‚¬μš©ν•˜μ‹œλ‚˜μš”?

βœ… A.


βœ… 전체 μš”μ•½ μΉ΄λ“œ

μ „λž΅ μ„€λͺ… 효과
Lazy Rendering 보일 λ•Œλ§Œ λ Œλ”λ§ λ©”λͺ¨λ¦¬ μ ˆμ•½, μ„±λŠ₯ ν–₯상
Pre-rendering 미리 λ Œλ”λ§ UX ν–₯상, λΉ λ₯Έ μ „ν™˜
JSON ν•„λ“œ μ΅œμ†Œν™” ν•„μš”ν•œ μ •λ³΄λ§Œ 전달 응닡 크기 ↓
Pagination 일정 개수만 응닡 속도 ↑, λΆ€ν•˜ ↓