최신글

프론트엔드

🧨 우당탕탕 Axios 인터셉터 만들기

-- 토큰 만료와의 혈투 기록 -- 프론트엔드를 하다보면, 그 어떤 api보다도 나를 가장 괴롭히는게 등장한다 바로 토큰 만료(401) 이번 글은 “처음에 대충 회사 코드 ctrl c + ctrl v 했다가 혼나서 결국 프로젝트 갈아엎고 다시 처음부터 axios 인터셉터 설계하게 된 이야기” 시작은 항상 \복붙이었다. 솔직히 말하면 인터셉터 만들 여유보다는 화면 구성하고싶은 맘이 조급했다. 백오피스를 마이그레이션 하라는 지시를 받았고, 인터셉터 그까이거 그냥 사용하던거 쓰면 되는거 아님? 당연히 이렇게 시작했다. 나는 그냥 옛날 코드 가져와 붙였고, 아무 생각 없이 진행하고 있었다. 근데 코드리뷰에서 멘토님이 한 말씀 기존거 가져다쓰지 마시고 처음부터 머리 박아가면서 만들어보시죠. 네..? 다시요..? 그렇게 나는 다시 401을 맞았다. 그래서 진짜로 인터셉터가 어떤 구조로 작동해야 하는지, 토큰 로직은 어떻게 구성해야 하는지 기본부터 다시 뜯어보기로 했다. 사실 이번 인턴 면접에서 토큰 기반 인증에 관한 질문이 있었고, (현 멘토님이 내 면접관이셨다) 한 페이지에서 여러 요청이 동시에 401 에러가 나오면 어떻게 해결하는지에 대해 여쭤보셨다. 나는 그것까지는 생각을 해본 적이 없어서 잘 모르겠다고 답 했었고?? 두고두고 맘에 남았다. 그래서 기존 프로젝트 axios 인터셉터 보고 “오 이렇게 만드는구나. 설계가 잘 되어있구나” 하고 그대로 갖다 썼던 마음이 큰 것 같다. 첫 삽질: 401 해결하려다 403 맞기 나는 빠르게 at 만료 감지를 만들고, refresh api도 붙였다. 그리고 좀 기다려서 만료되었을 때 나의 시나리오 오래된 at로 api 호출 서버가 401 던짐 인터셉터가 refresh 호출 새 토큰으로 요청 재시도 … 되어야 하는데 만료된 at로 api 호출 -> 401 err 자동적으로 refresh api 호출 -> 403 err 아니 왜 재발급 한번도 못했는데 왜 403 나옴? 이 악몽같은 현상으로 하루종일 삽질만 했다. 재발급 시마다 alert도 띄워보고, Authorization 헤더도 다시 붙여보고, 인터셉터 바깥에서 refresh 호출 성공하는것도 확인했는데,, 원인이 걍 퐝당했음. at와 rt의 유효기간이 같았던 것임!!! 아!뿔!싸! 기존 인터셉터도 이거 처리가 안되어있더라! 너무 모르겠어서 jwt.io에서 token 까보고 알았다. at가 만료되었을 때 rt도 만료가되어 refresh를 할 수 있는 시간이 없었던 것이다. accessToken 만료 → refresh 요청 시도 근데 refreshToken도 이미 만료 → 403 그래서 당연히 403이 나는 구조였다. 근데 백엔드를 바꿔달라고 할 수가 없는 상황 이걸 계기로 오랜만에 조금 머리를 굴려보았다. 자동 재발급? 그건 좀 아닌것같아요. 처음에는 이런 식의 자동 로직을 생각했다. 사용자가 뭘 하든 at 만료 5분전에 자동으로 refresh 하자 근데 이 생각을 말씀드렸더니 멘토님이 말씀하셨다. 사용자가 아무 행동도 안하는데 알아서 재발급 하는건 아닌 것 같아요! 맞말임. 아무래도 백오피스다보니까 보안적인 부분도 고려를 했어야했다. 그래서 방향을 바꿨다. 사용자가 실제 api 요청 시 만료 시간이 5분 이하라면 그때 refresh 하자 즉 활성 사용자만 재발급 → 비활성 사용자 세션은 종료 동시 요청 문제 → Pending Queue 도입 다음 문제는 이거였다. 이거는 내가 면접 때 질문을 받고 대답을 못했던 그 문제이기도 한데 A API 요청 시 → 토큰 만료 → refresh 시작 그 사이에 B API 요청 → 또 토큰 만료 → refresh 또 호출 이러면 refresh api가 동시에 여러번 호출되며 경합이 발생한다. 그래서 필수적으로 refresh 중엔 다른 요청을 멈춰서 줄세우는 로직이 필요하였다. 그것이 바로 pending queue ~~내가 자료구조 수업에서 듣고 코테 풀때만 쓰던 큐를 진짜 써보는 날이 오다니~~ 요약하자면 refresh 중이면 → 요청을 queue 에 쌓아둠 refresh 끝나면 → queue에 있던 요청들을 새 토큰으로 재요청 이렇게 하면 동시 재발급 요청 문제는 해결된다. 세션 만료 경고가 여러 번 뜨는 문제 아 근데 산넘어 산이라더니 에베레스트가 나옴 refresh 실패(401/403) → 로그아웃 처리할 때 다음과 같은 코드가 있었다. 근데 api 여러개가 동시에 터지면서 alert이 여러개가 떴던것임! alert 확인 버튼 연타함 그래서 로그아웃이 한 번만 실행되게 하기 위해서 zustand에 isLoggingOut state를 추가하여 해결하였다. 근데 왜 isLoggingOut 초기화가 안돼요? 문제 발생 두번째 세션 만료 로그아웃 때, 401 떴는데 로그아웃이 안되더라 그건 내가 isLoggingOut 상태값을 zustand persist 미들웨어에 넣어놨기 때문이었다. 그래서 persist partialize 설정해서 해결하였다. ㅎㅎ 바보 최종 Axios 인터셉터 코드 삽질 끝에 만들어진 인터셉터 구조는 다음과 같다. 토큰 만료 5분 이하 → refresh refresh 동안 다른 요청은 pending queue refresh 실패 → 로그아웃 alert 중복 방지 → isLoggingOut accessToken, refreshToken 상태는 zustand에서 관리 Authorization 헤더 자동 주입 정리하자면.. 이번에 인터셉터를 처음부터 설계하면서 느낀 점: 토큰 구조를 이해해야 한다 세션 만료 UX까지 고려해야 한다 동시 요청 문제까지 잡아야 한다 상태관리까지 연계해야 한다 인터셉터는 그냥 훅 두 개가 아니라 프로젝트의 전체 인증 흐름을 담당하는 중요한 부분임을 깨달았다. 그리고 무엇보다: 절대… 생각 안하고 코드 복붙부터 시작하지 말자.

2025년 11월 19일 15:33

프론트엔드

@tanstack/react-query Optimistic Updates

@tanstack/react-query Optimistic Updates Tanstack Query에서 Optimistic Updates는 서버 응답을 기다리기 전에 UI를 먼저 바꿔서 체감 속도를 올리는 패턴이다. 서버가 실패하면 되돌리고, 성공하면 실제 응답으로 확정한다. 사용하는 경우 버튼을 누르자마자 리스트/카운트/좋아요 상태가 바뀌어야 할 때 삭제/수정/좋아요/핀토글 처럼 결과가 예측 가능한 옵션 네트워크 지연이 UX를 해치는 구간 절차 onMutate: 서버 호출 직전, 관련 쿼리 refetch 취소 -> 현재 캐시 스냅샷 저장 -> 캐시를 낙관적으로 업데이트 onError: 실패 시 스냅샷으로 롤백 onSuccess: 서버 응답으로 정합성 확정(필요하면 캐시 merge) onSettled: 마지막에 관련 쿼리 invalidate/refetch ❗️ refetch를 취소하는 이유 게시글 목록을 보고 있음 -> useQuery(['posts'])가 캐시를 들고 있음 좋아요 버튼 클릭 -> useMutation() 실행됨 React Query는 이 와중에 자동으로 refetch 중일 수도 있음 (예: 창을 다시 클릭해서 포커스 됐을 때) refetch가 서버에서 예전 데이터를 받아오면, 당신이 방금 낙관적으로 바꿔둔 캐시(좋아요 눌림 상태)가 다시 덮어써짐 ❗️ refetch는 자동으로 취소되는가? ❌ refetch 취소는 자동으로 되지 않는다. 개발자가 onMutate 안에서 직접 cancelQueries()를 호출해야 한다. 예제: 좋아요 토글 사용

2025년 11월 04일 08:34

CS

[CS 스터디] 8주차 로드 밸런싱, 웹 서버 & WAS 차이

[8주차] 로드 밸런싱, 웹 서버 & WAS 차이 로드 밸런서란? + L4 vs L7 로드밸서 알고리즘 종류 헬스 체크 + 장애 조치 DNS로 하는 로드밸런싱 정적 vs 동적 페이지 차이 웹 서버와 WAS의 역할 비교 웹 서버 ↔ WAS 협업 구조 (리버스 프록시 포함) 웹/WAS를 왜 분리해서 쓰는가? 🔵 로드 밸런서란? 인터넷의 발달로 인해 트래픽이 증가하였다. 이에 기업들은 서버를 추가로 구비해 여러대의 서버에 동일한 데이터를 저장해 수많은 트래픽을 효과적으로 분산시킨다. 하지만 단순히 다수의 서버를 구축해 운영한다고 해서 모든 클라이언트의 요청을 일관성 있게 응답할 수 있는 것은 아니다. 쏟아지는 트래픽을 여러 대의 서버로 분산해 주는 기술이 없다면 한 곳의 서버에 모든 트래픽이 몰리는 상황이 발생할 것이다. 이때 필요한 기술이 바로 로드밸런싱이다. 로드밸런서는 서버에 가해지는 부하를 분산해주는 장치 또는 기술을 통칭한다. 클라이언트와 서버풀 사이에 위치하며, 한 대의 서버로 부하가 집중되지 않도록 트래픽을 관리해 각각의 서버가 최적의 퍼포먼스를 보일 수 있도록 한다. Scale-up Scale-up은 서버 자체의 성능을 확장하는 것을 의미한다. CPU가 i3인 컴퓨터를 i7로 업그레이드 하는 것과 같다. Scale-out Scale-out은 기존 서버와 동일하거나 낮은 성능의 서버를 두 대 이상 증설하여 운영하는 것을 의미한다. CPU가 i3인 컴퓨터를 여러 대 추가 구입해 운영하는 것에 비유할 수 있습니다. Scale-out의 방식으로 서버를 증설하였다면 여러 대의 서버로 트래픽을 균일하게 분산해주는 로드밸런싱이 반드시 필요하다. 🔵 L4 vs L7 로드밸런서 L4 로드밸런서 L4 로드밸런서는 전송 계층에서 작동하는 로드밸런서로, 주로 TCP 및 UDP 프로토콜을 기반으로 클라이언트와 서버 간의 트래픽을 분산시킨다. 클라이언트의 IP 주소와 포트, 서버의 IP 주소와 포트를 기반으로 로드밸런싱을 수행한다. L7 로드밸런서 L7 로드밸런서는 애플리케이션 계층에서 작동하는 로드밸런서로, 주로 HTTP, HTTPS 프로토콜을 기반으로 클라이언트와 서버 간의 트래픽을 분산시킨다. 요청 내용(URL, 헤더, 쿠키 등)을 기반으로 로드 밸런싱을 수행한다. L4, L7 로드밸런서 비교 | 항목 | L4 | L7 | | --------------- | ----------------- | ----------------------------- | | 작동 계층 | 전송 계층 | 애플리케이션 계층 | | 주요 프로토콜 | TCP, UDP | HTTP, HTTPS | | 로드밸런싱 기준 | IP 주소, 포트 | 요청 내용(URL, 헤더, 쿠키 등) | | 처리 속도 | 상대적으로 빠름 | 상대적으로 느림 | | 기능 및 유연성 | 상대적으로 제한적 | 다양한 기능 및 유연성 | L4 사용 사례 실시간 트래픽 처리가 중요한 서비스 온라인 게임, 스트리밍 서비스 등 실시간 트래픽 처리가 중요한 서비스에 적합하다. L7 사용 사례 애플리케이션 레벨의 로드밸런싱이 필요한 서비스 웹 서비스, API 게이트웨이, 콘텐츠 전송 네트워크 등 애플리케이션 레벨의 로드 밸런싱이 필요한 서비스에 적합하다. 🔵 로드밸런서 알고리즘 종류 라운드로빈 서버에 들어온 요청을 순서대로 돌아가며 배정하는 방식이다. 클라이언트의 요청을 순서대로 분배하기 때문에 여러 대의 서버가 동일한 스펙을 갖고 있고, 서버와의 연결이 오래 지속되지 않는 경우에 활용하기 적합하다. 가중 라운드로빈 각각의 서버마다 가중치를 매기고 가중치가 높은 서버에 클라이언트 요청을 우선적으로 배분한다. 주로 서버의 트래픽 처리 능력이 상이한 경우 사용되는 부하 분산 방식이다. 예를 들어 A라는 서버가 5라는 가중치를 갖고, B라는 서버가 2라는 가중치를 갖는다면 로드밸런서는 라운드로빈 방식으로 A서버에 5개 B서버에 2개의 요청을 전달한다. IP 해시 클라이언트의 IP 주소를 특정 서버로 매핑하여 요청을 처리하는 방식이다. 사용자의 IP를 해싱해 로드를 분배하기 때문에 사용자가 항상 동일한 서버로 연결되는 것을 보장한다. 최소 연결 요청이 들어온 시점에 가장 적은 연결상태를 보이는 서버에 우선적으로 트래픽을 배분한다. 자주 세션이 길어지거나 서버에 분배된 트래픽들이 일정하지 않은 경우에 적합한 방식이다. 최소 리스폰스 타임 서버의 현재 연결 상태와 응답시간을 모두 고려하여 트래픽을 배분한다. 가장 적은 연결 상태와 가장 짧은 응답시간을 보이는 서버에 우선적으로 로드를 배분한는 방식이다. 🔵 헬스 체크 로드밸런서는 부하분산을 하는 각 서버의 서비스를 주기적으로 헬스 체크 하여 정상적인 서비스 쪽으로만 부하를 분산하고 비정상적인 서비스는 서비스 그룹에서 제외해 트래픽을 보내지 않는다. 서비스 그룹에서 제외된 후에도 헬스 체크를 계속 수행해 다시 정상으로 확인되면 서비스 그룹에 해당 장비를 다시 넣어 트래픽이 해당 서버 쪽으로 보내지도록 한다. ICMP 방식: 서버에 ICMP 패킷(ping)을 보내 응답을 확인한다. 장점: 구현이 매우 간단하다. 단점: 네트워크 연결만 확인할 뿐, 애플리케이션 레벨의 상태는 확인 불가하다. 사용 여부: 실서비스 환경에서는 거의 사용하지 않는다. TCP 서비스 포트 방식: 서버의 특정 TCP 포트에 연결을 시도하여 열려있는지 확인한다. 장점: 서비스 포트가 열려 있는지 확인할 수 있다. 단점: 포트는 열려 있어도 애플리케이션이 정상 동작하는지는 보장하지 않는다. TCP 서비스 포트: Half Open 방식: TCP 3-way 핸드셰이크를 완료하지 않고, SYN → SYN-ACK까지만 보고 확인 후 종료하는 방식이다. 장점: 서버에 부담 없이 빠르게 상태 확인 가능하다. 용도: 빠르고 간단한 상태 체크에 적합하다. HTTP 상태 코드 방식: 정해진 경로(e.g. /health)에 HTTP 요청(GET)을 보내고 응답 상태 코드 (e.g. 200 OK)로 정상 여부 판단하는 방식이다. 장점: 웹 애플리케이션에서 가장 일반적이며, 서버가 정상적으로 HTTP 요청을 처리할 수 있는지 확인 가능하다. 단점: 상태 코드만으로는 세부적인 오류를 알기 어렵다. 콘텐츠 확인 방식: 특정 HTTP 요청의 응답 내용(body) 을 포함하여 비교한다. 예: /health 요청의 응답이 "OK"인지 확인. 장점: 애플리케이션이 정상적으로 작동하는지 더 정밀하게 판단 가능하다. 단점: 비교 연산이 추가되어 약간의 오버헤드가 발생한다. 🔵 장애 조치 Active: 현재 서비스를 제공하는 서버 Passive: 대기 중인 예비 서버 Active-Passive 장애 발생 시 Passive가 자동으로 Active 역할로 승격한다. 간단하고 안정적이지만 리소스 낭비가 있다. Active-Active 여러 서버가 동시에 서비스를 제공하며 로드밸런싱 된다. 하나의 서버가 장애가 나도 나머지에서 즉시 커리가 가능하다. 고가용성, 리소스가 효율적으로 사용되지만, 상태 동기화가 복잡하고 충돌 방지가 필요하다. N+1 구조 N개의 Active 서버에 대해 한개의 Passive 서버를 두는 방식이다. 하나가 장애가 나면 예비 서버가 대신한다. 자원 효율과 안정성 간 절충안이다. N+M 구조 N개의 Active 서버에 대해 M개의 Passive 서버를 두는 방식이다. 여러 서버에 동시에 장애가 나도 대응이 가능하다. 대규모 서비스에 적합한 방식이다. 🔵 DNS로 하는 로드밸런싱 DNS 서버가 하나의 도메인 이름(예: www.example.com)에 대해 여러 개의 A 레코드(IP 주소)를 등록해 두고, 클라이언트가 도메인 이름을 요청할 때마다 이들 중 하나 또는 여러 개를 반환함으로써 트래픽 분산을 유도하는 방식이다. 실시간 상태 반영이나 부하 기반 분산에는 한계가 있으므로, 일반적으로는 L7 로드밸서(ALB, Nginx 등) 와 함께 병행하거나, 클라우드 DNS 서비스의 고급 기능을 통해 보완한다. 작동 방식 www.example.com에 대해 다음과 같은 A레코드가 존재한다. A www.example.com → 192.168.0.1 A www.example.com → 192.168.0.2 A www.example.com → 192.168.0.3 DNS 질의가 오면 DNS 서버는 위 세 개 중 하나 또는 모두를 응답하고, 클라이언트는 해당 IP로 접속해 트래픽을 분산한다. 한계점 DNS 캐싱 클라이언트 또는 DNS 리졸버가 응답 IP를 캐싱해 오래 유지하면 분산 효과가 저하된다. 실시간 장애 감지 불가 일반 DNS는 헬스체크를 하지 않으므로 장애 서버에 응답이 갈 수 있다. 로드량 고려 불가 서버 부하 상태나 연결 수 등을 고려하지 못한다. 세션 유지 어려움 클라이언트가 매 요청마다 다른 서버에 연결될 수 있다. 🔵 정적 vs 동적 페이지 차이 인터넷을 이용하면서 접속하게 되는 웹페이지는 크게 두 가지로 나뉜다. 저장된 파일을 그대로 보는 정적 웹 페이지와 다른 변수들에 의해 변경되어 보이는 동적 웹 페이지이다. 정적 웹 페이지 웹서버에 이미 저장된 파일(HTML 파일, 이미지, JavaScript 파일 등)을 클라이언트에게 전송하는 웹 페이지이다. 사용자는 서버에 저장된 데이터가 변경되지 않는 한 고정된 웹 페이지를 계속 보게 된다. 따라서 모든 사용자는 같은 결과의 웹 페이지를 서버에 요청하고 응답 받게 된다. 동적 웹 페이지 서버에 저장된 HTML 파일이 그대로 브라우저에 나오는 것이 아닌 동적으로 만들어지는 웹 페이지이다. 요청에 관하여 사용자는 조건에 따라 다른 결과를 받게 된다. 사용자는 상황, 시간, 요청 등에 따라 달라지는 웹 페이지를 보게 된다. CSR (Client Side Rendering) CSR은 데이터가 없는 HTML 문서나 Static 파일만을 처음에 받아와 로드하고, 이후에 데이터를 요청하여 받아오는 방식이다. Javascript를 사용하여 브라우저에서 페이지를 직접 렌더링 진행한다. 모든 로직, 데이터 가져오기, 템플릿 및 라우팅 등은 서버가 아닌 클라이언트 측에서 진행한다. SSR (Server Side Rendering) CSR과 상반되게 서버에서 동적으로 데이터까지 전부 삽입하여 완성된 HTML을 넘겨준다. 서버 렌더링은 브라우저에서 응답을 받기 전에 처리되므로 클라이언트에서 데이터를 가져오거나 템플릿 작성에 대한 추가 왕복이 발생하지 않는다. MPA (Multi Page Application) 새로운 페이지를 요청할 때마다 정적 리소스가 다운로드 되고, 그에 맞춰 전체 페이지를 다시 렌더링 하는 방식이다. (즉, SSR 방식으로 렌더링된다.) 인터넷 주소창에 주소를 입력하거나 링크를 클릭하는 등의 사용자가 어떠한 요청을 하게 되면, 그에 맞는 완전한 페이지를 받아오고 다시 렌더링된다. SEO(검색 엔진 최적화) 관점에서는 유리하지만, 새로운 페이지를 이동할 때마다 완전히 새로 렌더링 되기 때문에 UI가 깜빡거리며 프론트엔드와 백엔드가 밀접하게 연결되어 개발이 복잡해질 수 있다. SPA (Single Page Application) 웹 어플리케이션에 필요한 모든 정적 리소스를 최초 한번만 다운로드한다. 그 이후 새로운 페이지에 대한 요청이 있을 떄마다 페이지 갱신에 필요한 데이터만 전달 받고 그 정보를 기준으로 페이지를 갱신한다. (즉, CSR 방식으로 렌더링한다.) SPA를 만드는데 사용되는 프레임워크로는 React, Vue, Angular 가 있다. 최초 접속 시 맨 첫 페이지 로딩 시간은 길어도 이후 페이지부터는 속도가 빠르다는 장점이 있다. 또한 로컬 데이터를 효과적으로 캐싱할 수 있다. 하지만 초기 구동 속도가 느리고 SEO에 불리하다는 단점이 있다. 🔵 웹 서버와 WAS의 역할 비교 웹 서버와 WAS(Seb Application Server) 서버는 웹 상에서 서비스를 제공하기 위해 사용되는 서버이다. 두 서버의 역할과 기능에는 차이가 있으며, 각각의 서버가 목적과 기능을 가지고 있다. | 항목 | 웹 서버 | WAS | | --------------- | ---------------------------------------------------- | ------------------------------------------------------------------------ | | 정의 | 정적인 콘텐츠(HTML, CSS, 이미지 등)를 제공하는 서버 | 동적인 콘텐츠(웹 애플리케이션)을 처리하고 제공하는 서버 | | 기능 | HTTP 프로토콜을 이용해 클라이언트에게 웹 페이지 제공 | 웹 애플리케이션 실행 및 데이터 처리, 웹 서버와 클라이언트 간의 중계 역할 | | 주요 소프트웨어 | Apache, Nginx | Tomcat, JBoss, WebLogic | 웹 서버의 역할과 예시 웹 서버는 클라이언트가 웹 브라우저를 통해 요청한 정적 콘텐츠를 제공하는 역할을 한다. 웹 서버는 주로 HTTP 프로토콜을 사용하여 작동하며, 클라이언트가 URL을 통해 요청한 웹 페이지를 찾아 전송해준다. 예시: 회사 홈페이지, 블로그, 뉴스 사이트 등 WAS 서버의 역할과 예시 WAS 서버는 웹 애플리케이션을 실행하여 동적 콘텐츠를 생성하고, 웹 서버와 클라이언트 간의 데이터 처리를 담당하는 역할을 한다. WAS 서버는 클라이언트의 요청에 따라 데이터베이스에서 정보를 가져오거나, 웹 애플리케이션을 실행하여 동적인 웹 페이지를 생성한 후 결과를 웹 서버에 전달한다. 웹 서버는 이를 받아 클라이언트에게 전달한다. 예시: 온라인 쇼핑몰, 은행 인터넷 뱅킹, SNS 등 🔵 웹 서버 ↔ WAS 협업 구조 (리버스 프록시 포함) 클라이언트가 HTTP 요청을 전송 사용자가 브라우저에서 URL을 입력하거나 링크를 클릭 예: GET /index.html, POST /login 웹 서버(Nginx, Apache 등)가 요청을 먼저 수신 정적 리소스(HTML, CSS, JS, 이미지 등) 요청이면 직접 응답 동적 요청이면 WAS로 전달 웹 서버가 리버스 프록시 역할 수행 WAS가 외부에 직접 노출되지 않고 웹 서버가 중계 역할 요청 URI나 패턴 기반으로 정적/동적 요청 분기 처리 WAS가 동적 요청 처리 Java, Spring, JSP, Servlet 등 동적 로직 처리 DB 조회, 로직 실행, 응답 데이터 생성 WAS → 웹 서버로 처리 결과 전달 WAS는 HTML, JSON, 텍스트 등 생성된 응답을 반환 웹 서버가 클라이언트에게 응답 전달 🔵 웹/WAS를 왜 분리해서 쓰는가? 정적 vs 동적 처리 분산 정적 리소스는 웹 서버가 빠르게 처리 WAS는 계산과 DB처리 등 로직 집중 트래픽 분산 및 성능 향상 리버스 프록시를 통한 부하 분산 가능 병목 구간 분리로 확장성 확보 보안 강화 외부 요청은 웹 서버까지만 접근 허용 내부 WAS는 외부 노출 차단 가능 운영 유연성 웹 서버와 WAS를 독립적으로 배포/스케일링 가능 설정 변경이나 유지보수가 용이

2025년 05월 22일 06:12

CS

[CS 스터디] 7주차 IP + HTTP & HTTPS + TLS/SSL + 쿠키 & 세션

[7주차] IP + HTTP & HTTPS + TLS/SSL + 쿠키 & 세션 IP HTTP & HTTPS HTTP 응답 코드 SSL과 TLS의 차이점 DNS에 대한 설명 쿠키 & 세션 www.github.com을 브라우저에 입력하고 엔터를 쳤을 때, 네트워크 상 어떤 일이 일어나는지 최대한 자세하게 설명해 주세요. 🔵 IP IP 주소의 개념과 기능 IP 주소는 인터넷에 연결된 각 기기를 구별하기 위해 사용되는 고유한 번호이다. IP는 프로토콜 그 자체이고 IP주소는 IP통신을 하기 위해 각 기기들을 구분하는 고유번호라고 이해하면 된다. IP 주소는 네트워크 내에서 특정 기기를 찾아 데이터를 전송할 수 있도록 도와주며, 기기들이 서로 통신할 때 필수적인 요소이다. IP 주소는 32비트 숫자로 구성되며, 보통 점 표기법으로 작성된다(예: 73.227.130.85). 점 사이의 숫자를 옥텟(8비트)이라고 한다. IP 주소 클래스 IP 주소를 과거에는 클래스 기반 방식으로 분류했으며, 현재는 CIDR 방식이 쓰인다. | 클래스 | 시작 주소 범위 | 네트워크/호스트 비트 | 개수 용도 | | ------ | --------------------------- | ------------------------------- | --------------- | | A | 0.0.0.0 ~ 127.255.255.255 | 8비트 네트워크 / 24비트 호스트 | 대규모 (기업용) | | B | 128.0.0.0 ~ 191.255.255.255 | 16비트 네트워크 / 16비트 호스트 | 중규모 | | C | 192.0.0.0 ~ 223.255.255.255 | 24비트 네트워크 / 8비트 호스트 | 소규모 | | D | 224.0.0.0 ~ 239.255.255.255 | 멀티캐스트용 | | | E | 240.0.0.0 ~ 255.255.255.255 | 실험용, 예약됨 | | CIDR 고정된 IP 클래스 대신, 가변 길이의 서브넷 마스크를 사용할 수 있게 만든 IP 주소 표기 방식이다. 과거 클래스 기반에서는 IP 자원의 비효율적 사용이 발생하였으며, CIDR 도입 이후에 필요에 따라 네트워크 크기를 세분화하여 할당 가능하게 되었다. 예) 192.168.10.0/24 192.168.10.0 -> 네트워크 주소 /24 -> 앞 24비트는 네트워크 식별, 나머지 8비트는 호스트 식별 IPv4과 IPv6의 차이점 IP 주소는 IPv4와 IPv6 두 가지 버전이 있다. IPv4: 32비트로 구성된 IP 주소로, 대략 43억 개의 고유한 주소를 생성할 수 있다. IPv4 주소는 4개의 0~255 사이의 숫자로 이루어져 있으며, 각 숫자는 점(.)으로 구분된다. 예) 192.168.0.1 IPv6: 128비트로 구성된 IP 주소로, 거의 무한한 수의 고유한 주소를 생성할 수 있다. IPv6 주소는 8개의 4자리 16진수로 이루어져 있으며, 각 16진수는 콜론(:)으로 구분된다. 예) 2001:0db8:85a3:0000:0000:8a2e:0370:7334 기본적으로 IP주소라고 하면 IPv4를 이야기하는데 자리 수의 한계로 인해 IPv4는 더이상 할당되지 않고 있다. IP 주소와 MAC 주소의 차이 | 항목 | MAC 주소 | IP 주소 | | ----------- | -------------------------------------------- | ---------------------------------------------------------------- | | 레이어 | OSI 2계층 (데이터 링크 계층) | OSI 3계층 (네트워크 계층) | | 식별 위치 | 동일 네트워크 내 장치 식별 | 인터넷 상의 장치를 전 세계적으로 식별 | | 주소 형식 | 12자리 16진수 (예: 00-14-22-01-23-45) | IPv4: 32비트 (예: 192.168.0.1), IPv6: 128비트 (예: 2001:0db8::1) | | 변경 가능성 | 변경할 수 없음 ( 제조시 장치에 하드코딩 됨 ) | 네트워크 설정을 통해 변경 가능 | | 주소 유형 | 물리적 주소 | 논리 주소 | | 할당 방식 | 제조시 장치에 하드코딩 됨 | 소프트웨어 구성을 통해 장치에 할당됨 | IP 주소 = 집 주소 인터넷상에서 어느 네트워크(집)에 위치했는지를 나타내는 주소이다. 예를 들어, 택배를 보낼 때 집 주소만 있으면 그 집까지는 도착할 수 있는 것처럼, IP 주소는 데이터가 목적지 네트워크까지 가는 데 사용된다. MAC 주소 = 집 안의 특정 사람(기기)을 가리키는 이름표 네트워크 안에서 특정 장치를 식별하는 고유한 주소이다. 집 안에 여러 사람이 있을 때, 택배 기사가 수신자 이름을 보고 그 사람에게 전달하듯, MAC 주소는 로컬 네트워크 내에서 누구한테 보낼지를 결정한다. TTL이란 TTL: Time To Live의 약자로 해당 패킷의 생존 시간을 의미한다. IP 패킷 내부에 있는 값으로서, 그 패킷이 네트워크에 너무 오래 있어서 버려져야 하는지의 여부를 라우터에게 알려주는 역할을 한다. 패킷들은 여러가지 이유로 적당한 시간 내에 지정한 장소에 배달되지 못할 수가 있다. 예를 들어 부정확한 라우팅 테이블의 결합은 패킷을 끝없이 순환하도록 만들 수 있다. 그래서 일정 시간이 지나면 그 패킷을 버릴건지 혹은 재전송할 것인지를 결정하도록 하기 위해서 TTL이 사용된다. 각 라우터는 TTL 패킷이 날라올 때 TTL Value를 1씩 감소시킨다. TTL 값이 0이 되었을 때 라우터는 그것을 감지하여 해당 패킷을 버리고 ICMP 메세지를 발신지 host에게 보내게 된다. IPv4에서 수행하는 Checksum과 TCP에서 수행하는 Checksum 차이점 | 항목 | IPv4 Checksum | TCP Checksum | | ------------ | ---------------------------------------- | ---------------------------------------------------------- | | 검사 범위 | IP 헤더만 검사 | TCP 헤더 + 데이터(페이로드) + 의사 헤더까지 검사 | | 목적 | IP 헤더의 무결성 확인 (라우팅 정보 보호) | 전체 TCP 세그먼트의 무결성 확인(데이터 손상 방지) | | 위치 | IPv4 헤더 내에 존재 | TCP 헤더 내에 존재 | | 손상 시 처리 | 패킷은 폐기됨, 상위 계층에 전달되지 않음 | 손상된 TCP 세그먼트는 수신 측에서 재전송 요청 등 처리 가능 | IP 체크섬은 패킷이 제대로 전달될 수 있게 IP 경로 자체를 보호 TCP 체크섬은 실제 데이터를 온전하게 받기 위해 데이터 자체를 보호 🔵 HTTP & HTTPS HTTP의 Stateless 특성 stateless 란 서버가 클라이언트의 이전 요청 상태를 저장하지 않는다는 특성을 의미합니다. 각 HTTP 요청은 독립적이며, 이전 요청의 정보를 기억하지 않는다. 예를 들어 로그인 후 다른 요청을 보내더라도, 서버는 사용자가 로그인했다는 상태를 기억하지 않는다. 그래서 세션, 쿠키, 토큰 등을 활용해 상태를 클라이언트 측에서 저장하고 요청마다 보내는 방식으로 상태를 유지한다. 장점: 서버가 상태를 저장할 필요가 없으므로 확장성과 단순성이 높아짐 단점: 매 요청마다 인증 정보 등을 반복적으로 포함해야 함 HTTPS에서 공개키와 대칭키의 차이 | 구분 | 공개키 암호화 방식 | 대칭키 암호화 방식 | | --------- | ---------------------------------- | ---------------------------------- | | 키 종류 | 공개키(암호화용), 개인키(복호화용) | 하나의 동일한 키를 암복호화에 사용 | | 속도 | 느림 | 빠름 | | 보안 방식 | 키쌍을 이용해 안전하게 키를 교환 | 미리 안전하게 키를 주고받아야 함 | | 사용 목적 | 주로 키 교환에 사용됨 | 실제 데이터 내용 암호화에 사용 | HTTPS Handshake 과정에서는 인증서를 사용하는 이유 신뢰할 수 있는 서버인지 확인하기 위해서 클라이언트는 서버가 제공한 인증서(Certificate) 를 통해 이 서버가 진짜 github.com인지 판단합니다. 인증서에 포함되는 정보 도메인 이름 서버의 공개키 인증 기관(CA)이 서명한 전자서명 클라이언트는 이 인증서가 신뢰할 수 있는 기관(CA) 에 의해 서명되었는지를 검증하고,서버의 공개키가 진짜임을 확인한다. 검증이 성공하면, 대칭키 교환에 사용할 암호키를 안전하게 서버로 전송할 수 있댜. 🔵 HTTP 응답 코드 GET과 POST의 차이점 | 항목 | GET | POST | | ----------- | ---------------------------------------- | ------------------------------------------ | | 목적 | 데이터 조회 | 데이터 생성/전송 | | 요청 데이터 | URL의 쿼리 스트링에 포함 | HTTP Body에 포함 | | 길이 제한 | 있음 (URL 길이 제한 존재) | 없음 | | 캐싱 | 가능 (브라우저/프록시 등 캐싱 활용 가능) | 일반적으로 캐싱하지 않음 | | 멱등성 | O (여러 번 요청해도 결과 동일) | X (여러 번 요청하면 데이터 중복 생성 가능) | | 보안 | 낮음 (URL에 민감 정보 노출 우려) | 상대적으로 높음 (Body에 숨겨짐) | POST와 PUT, PATCH의 차이점 | 항목 | POST | PUT | PATCH | | ----------- | ---------------------------------- | ------------------------------ | --------------------------- | | 목적 | 리소스 생성 | 리소스 전체 수정 or 생성 | 리소스 일부 수정 | | 멱등성 | X (여러 번 호출 시 중복 생성 가능) | O (여러 번 호출해도 동일 결과) | 일반적으로 멱등성 보장 안됨 | | 사용 예시 | 새로운 게시글 작성 | 게시글 전체 내용 수정 | 게시글의 일부 내용만 수정 | | 요청 데이터 | 필드 전체 포함 필요 없음 | 전체 필드 필요 | 수정할 필드만 포함 | 🔵 SSL과 TLS의 차이점 | 항목 | SSL (Secure Sockets Layer) | TLS (Transport Layer Security) | | --------- | ------------------------------- | -------------------------------------------- | | 개발 시기 | 1990년대 중반 개발 | SSL의 후속 프로토콜, 1999년부터 등장 | | 최신 버전 | SSL 3.0 (더 이상 사용하지 않음) | TLS 1.3 (2020년 기준 최신) | | 보안성 | 여러 보안 취약점 존재 | 보안 강화 (키 교환, 암호화 알고리즘 등 개선) | | 호환성 | 구형 시스템에 사용 | 최신 웹 브라우저와 시스템에서 표준 사용 | | 사용 여부 | 비권장 (Deprecated) | 표준 보안 프로토콜로 사용 중 | 현재는 "TLS"가 올바른 명칭이며, 관행적으로 SSL이라고 부르기도 하지만 실질적으로는 TLS 사용 중이다. 🔵 DNS에 대한 설명 DNS란? Domain Name System의 약자 사용자가 도메인 주소 (예: www.github.com)를 입력하면 해당 도메인에 매핑된 IP 주소를 찾아주는 주소 해석 시스템 계층 및 프로토콜 | 항목 | 설명 | | -------- | -------------------------------------------- | | 계층 | 애플리케이션 계층 (OSI 7계층 기준) | | 프로토콜 | 주로 UDP 53번 포트 사용 (빠른 응답) | | 예외 | 데이터 길이가 길거나 보안 DNS는 TCP 사용 | 🔵 쿠키 & 세션 쿠키와 세션의 차이점 | 항목 | 쿠키 | 세션 | | --------- | --------------------------------------- | ------------------------------------- | | 저장 위치 | 클라이언트(브라우저) | 서버 | | 보안성 | 상대적으로 낮음 (조작 가능) | 상대적으로 높음 (서버에서 관리) | | 만료 설정 | 클라이언트가 직접 만료 시간 설정 가능 | 서버 설정에 따라 결정 | | 용량 제한 | 약 4KB | 제한 없음 (서버 메모리에 의존) | | 식별 방식 | 클라이언트가 요청 시 자동으로 쿠키 전송 | 세션 ID를 쿠키로 전달하여 서버가 식별 | 세션 기반 로그인 과정 클라이언트가 로그인 요청 서버가 로그인 정보 확인 후 세션 생성 세션 ID를 쿠키에 담아 클라이언트에 전달 이후 요청마다 클라이언트는 세션 ID를 전송 서버는 해당 세션 ID로 로그인 사용자를 식별 서버가 여러 대일 때 세션 관리 방법 세션 클러스터링: 서버 간 세션 정보를 동기화 세션 스토리지 사용: Redis, Memcached 등의 인메모리 DB 활용 JWT 사용: 세션 없이 토큰 기반 인증 (Stateless 방식) Stateless vs Connectionless | 항목 | Stateless | Connectionless | | ---- | ------------------------------------ | ------------------------ | | 정의 | 이전 상태를 서버가 저장하지 않음 | 연결 없이 개별 패킷 전송 | | 예시 | HTTP | UDP | | 특징 | 요청마다 독립적, 서버 확장성 용이 | 빠르지만 신뢰성 낮음 | HTTP가 Stateless 구조인 이유 확장성과 단순성 확보 서버는 클라이언트의 상태를 기억하지 않기 때문에 요청 처리 시 독립성 보장 캐싱, 로드 밸런싱, 서버 분산 처리에 유리 🔵 www.github.com을 브라우저에 입력하고 엔터를 쳤을 때, 네트워크 상 어떤 일이 일어나는지 최대한 자세하게 설명해 주세요 브라우저 캐시 확인 - 먼저 이전에 저장된 캐시 기록이 있는지 확인한다. DNS 조회 - github.com 도메인에 해당하는 IP 주소를 찾기 위해 DNS 질의를 수행한다. - 브라우저 → OS → DNS Resolver → Root → TLD → Authoritative → IP 응답 TCP 연결 (3-way Handshake) - 클라이언트는 서버와의 연결을 위해 TCP 3-way handshake 수행한다. - SYN → SYN-ACK → ACK TLS Handshake (HTTPS의 경우) - 서버 인증서를 전달하고 공개키를 교환한다. - 세션키 생성 후 대칭키 방식으로 통신을 시작한다. HTTP 요청 전송 - 브라우저는 GET 방식으로 / 요청을 보낸다. - ex) GET / HTTP/1.1 서버 응답 - 서버는 HTML, CSS, JS 등의 데이터를 응답한다. - HTTP 응답 코드와 함께 콘텐츠를 전송한다. 브라우저 렌더링 - HTML 파싱 → DOM 트리 구성 - CSSOM, JS 파싱 → 렌더링 트리 완성 → 페이지 렌더링 추가 리소스 요청 - 이미지, JS, CSS 등 외부 리소스 추가 요청 발생 (병렬 처리)

2025년 05월 13일 12:25

CS

[CS 스터디] 6주차 TCP, UDP, 흐름 제어 / 혼잡 제어

[6주차] TCP, UDP, 흐름 제어 / 혼잡 제어 Transport Layer TCP, UDP 특징 TCP의 신뢰성 보장 메커니즘 TCP의 흐름 제어 (Flow Control) TCP의 혼잡 제어 (Congestion Control) TCP 연결 과정: 3-Way Handshake와 관련 이슈 흐름 제어와 혼잡 제어의 차이 UDP가 흐름/혼잡 제어를 하지 않는 이유 DHCP 멀티플렉싱과 디멀티플렉싱(포트 번호와 TCP/UDP 연결) 🔵 Transport Layer 다른 호스트에서 실행되는 application process 사이에 논리적인 통신을 제공한다. Application 관점에서는 서로 다른 호스트의 프로세스들이 직접 연결된 것처럼 동작한다. 데이터 흐름 sender (송신 측): 어플리케이션 메세지를 세그먼트 단위로 쪼개어 Network Layer로 전달한다. receiver (수신 측): 수신한 세그먼트들을 조립하여 Application Layer로 전송한다. network vs transport Network Layer: host 사이의 논리적 통신 Transport Layer: process 사이의 논리적 통신 주요 Transport Layer 프로토콜 TCP (Transmission Control Protocol) UDP (User Datagram Protocol) 🔵 TCP, UDP 특징 | 항목 | TCP | UDP | | ----------- | --------------------- | ------------------- | | 신뢰성 | O (재전송, 확인 응답) | X (손실되어도 무시) | | 순서 보장 | O | X | | 연결 설정 | O (3-way handshake) | X (연결 없이 전송) | | 혼잡 제어 | O | X | | 지연 보장 | X | X | | 대역폭 보장 | X | X | 항목 별 용어 설명 신뢰성 (Reliability) 데이터가 전송 중 손실되거나 손상되더라도, 송신자가 재전송하거나 수신자가 확인 응답(ACK) 을 보내어 정확히 데이터를 수신하는 것을 보장하는 것 TCP는 신뢰성을 제공한다. (손실되면 재전송) UDP는 신뢰성을 제공하지 않는다. (손실돼도 무시) 순서 보장 (In-order Delivery) 여러 개의 데이터 조각이 전송될 때, 수신자가 원래 송신자가 보낸 순서대로 정확하게 데이터를 재조립하여 전달받는 것 TCP는 순서를 보장한다. (순서 엇갈려도 정렬) UDP는 순서를 보장하지 않는다. (순서 무시) 연결 설정 (Connection Setup) 데이터를 보내기 전에 송신자와 수신자가 서로 연결을 확립하는 과정 TCP는 3-way handshake 과정을 통해 연결을 설정한다. UDP는 연결 없이 바로 데이터 전송을 시작한다. 혼잡 제어 (Congestion Control) 네트워크가 혼잡할 때, 송신자가 전송 속도를 조절하여 네트워크 부하를 줄이는 메커니즘 TCP는 혼잡을 감지하고 전송 속도를 줄인다. UDP는 혼잡 상황을 고려하지 않고 계속 전송한다. 지연 보장 (Delay Guarantee) 데이터가 얼마나 빨리 도착하는지를 보장해주는 기능 TCP와 UDP 모두 지연 시간을 보장하지 않는다. 네트워크 상황에 따라 도착 시간이 변동될 수 있다. 대역폭 보장 (Bandwidth Guarantee) 일정한 전송 속도를 지속적으로 확보해주는 기능 TCP와 UDP 모두 특정 대역폭을 보장하지 않는다. 트래픽 상황에 따라 대역폭이 달라질 수 있다. 🔵 TCP의 신뢰성 보장 메커니즘 TCP는 데이터 전송 중 발생할 수 있는 오류, 손실, 중복, 순서 어긋남 문제를 해결하기 위해 다양한 신뢰성 보장 매커니즘을 사용한다. 이 매커니즘들은 rdt (reliable data transfer) 프로토콜 발전 과정을 통해 이해할 수 있다. TCP가 적용한 신뢰성 매커니즘은 다음과 같은 흐름으로 발전해 왔다. [rdt 1.0] 완벽한 채널 가정 처음에는 채널이 완벽하다고 가정하여, 데이터가 손상되거나 손실되지 않는다고 생각했다. 이 경우 송신자는 데이터를 전송하기만 하면 되었고, 별다른 추가 제어가 필요 없었다. [rdt 2.0] 비트 오류 복구 (ACK/NAK) 현실에서는 채널에서 비트 오류가 발생할 수 있으므로, 수신자는 데이터에 오류가 있는 경우 NAK를 보내어 송신자가 재전송하도록 하고, 데이터가 정상적이면 ACK를 보내 확인하는 메커니즘이 도입되었다. [rdt 2.1] ACK/NAK 깨짐 대비 (Sequence Number 추가) ACK/NAK 신호 자체가 깨질 수 있는 문제를 대비해, 시퀀스 번호(Sequence Number) 를 도입했다. 이를 통해 송신자와 수신자는 어떤 데이터가 정상적으로 전송/수신되었는지를 번호를 통해 명확히 확인할 수 있게 되었다. [rdt 2.2] NAK 없이 ACK만 사용 (TCP 스타일) 추가적인 최적화를 위해, NAK 없이 ACK만 사용하는 방식이 제안되었다. 수신자가 정상적으로 수신한 마지막 데이터에 대해 ACK를 보내고, 송신자는 중복된 ACK을 통해 문제를 감지하고 필요 시 재전송한다. TCP는 이 방식(rdt 2.2) 을 기본으로 사용한다. [rdt 3.0] 패킷/ACK 유실까지 대비 (Timeout 추가) 이후, 네트워크에서는 데이터 패킷이나 ACK 자체가 유실(loss) 되는 상황도 고려해야 했다. 이를 해결하기 위해 송신자는 타이머(timeout) 를 설정하여 일정 시간 동안 ACK이 도착하지 않으면 해당 패킷을 재전송하는 방식으로 대응한다. 이로써 유실된 데이터도 복구할 수 있다. [GBN/SR] Stop-and-Wait 한계 극복 (Window 기반) Stop-and-Wait 방식은 한 번에 하나씩만 전송하고 기다리는 방식이기 때문에 전송 효율이 매우 낮았다. 이를 해결하기 위해 Go-Back-N(GBN) 과 Selective Repeat(SR) 같은 윈도우 기반 프로토콜이 도입되었다. TCP도 이와 유사하게 여러 개의 패킷을 동시에 보내고, ACK을 받아가며 윈도우를 조정하는 방식을 사용한다. 항목 별 용어 설명 Sequence Number (시퀀스 넘버) 패킷의 고유 번호로, 데이터의 순서 보장과 중복 감지를 위해 사용 송신자가 전송하는 각 패킷에 고유 번호를 붙인다. 수신자는 시퀀스 번호를 기준으로 정확한 순서로 재조립하거나 중복 패킷을 구별할 수 있다. 번호를 통해 이건 이미 받은 데이터인지 확인할 수 있다. ACK (Acknowledgement, 확인 응답) 데이터가 정상적으로 도착했음을 알리는 신호 수신자가 데이터(패킷)를 정상적으로 받았을 때 송신자에게 보낸다 송신자는 ACK를 받으면 다음 데이터를 전송한다. TCP에서는 일반적으로 “어떤 시퀀스 번호까지 받았는지“를 함께 보낸다 (누적 ACK) NAK (Negative Acknowledgement, 부정 응답) 데이터에 오류가 발생했음을 알리는 신호 수신자가 패킷을 제대로 받지 못했거나 오류가 있으면 송신자에게 보낸다 송신자는 NAK를 받으면 해당 데이터를 즉시 재전송 TCP는 NAK를 명시적으로 사용하지 않고, 중복 ACK로 오류를 감지하고 처리한다 Retransmission (재전송) 데이터가 손실되었거나 손상되었을 때, 송신자가 같은 데이터를 다시 보내는 것 NAK를 받거나 일정 시간 안에 ACK를 받지 못하거나 (timeout) 중복된 ACK를 여러 번 받으면 송신자는 해당 패킷을 다시 전송한다 Timeout (타이머) 송신자가 ACK를 기다리는 최대 시간 데이터 전송 후, 타이머를 시작한다 타이머가 만료되었는데 ACK가 도착하지 않으면 해당 데이터를 재전송한다 타이머의 시간 길이(Timeout Interval)는 네트워크 상황에 따라 동적으로 조정될 수 있다 (ex: RTT 기반) TCP는 패킷마다 번호(Sequence Number)를 붙이고, 도착 확인(ACK)을 받고, 오류나 손실이 발생하면 재전송(Retransmission)하며, 일정 시간(Timeout) 내에 확인이 안 되면 다시 보내는 구조 🔵 TCP의 흐름 제어 (Flow Control) TCP 흐름 제어는 송신자가 수신자의 처리 능력을 초과하지 않도록 데이터 전송 속도를 조절하는 메커니즘이다. Sliding Window란? 송신자가 수신자로부터 받은 수신 윈도우 크기(rwnd)만큼 데이터를 한 번에 전송할 수 있다. 수신자는 매번 ACK를 보낼 때 자신이 추가로 받을 수 있는 버퍼 크기를 알려준다. 송신자는 이 rwnd를 보고 자신의 송신 윈도우 크기를 조절한다. 주요 특징 수신자의 버퍼 오버플로우 방지 연속적인 데이터 전송 가능 (ACK 기다리지 않고 윈도우 내에서 계속 전송) ACK을 받으면 윈도우가 슬라이딩(slide) 되어 다음 전송 준비 흐름 수신자는 현재 가능한 버퍼 크기(rwnd)를 송신자에게 통보 송신자는 rwnd를 초과하지 않도록 데이터 전송 수신자가 버퍼를 비우면 ACK + 새로운 rwnd를 송신자에게 전달 송신자는 윈도우를 슬라이딩하여 전송 지속 🔵 TCP의 혼잡 제어 (Congestion Control) TCP 혼잡 제어는 네트워크 자체가 과부하되지 않도록 송신자가 전송 속도를 동적으로 조절하는 메커니즘이다. Slow Start (느린 시작) 처음 연결이 열리면, TCP는 작은 전송 속도(cwnd = 1 MSS)부터 시작한다. 매 ACK마다 전송 윈도우(cwnd)를 2배씩 지수적으로 증가시킨다. 네트워크 상태를 빠르게 파악하면서 적응해간다. AIMD (Additive Increase Multiplicative Decrease) 혼잡이 감지되기 전까지는 1 RTT마다 cwnd를 선형(+)으로 증가시킨다 (Additive Increase) 혼잡(패킷 손실)이 발생하면 cwnd를 절반(×0.5)로 감소시킨다 (Multiplicative Decrease) 🔵 TCP 연결 과정: 3-Way Handshake와 관련 이슈 3-Way Handshake란? TCP는 연결형 프로토콜로, 통신을 시작하기 전에 반드시 연결 설정 과정을 거친다. 이 연결 설정은 3-Way Handshake라는 절차를 통해 이루어진다. 3-Way Handshake는 TCP 통신을 시작할 때 송신자와 수신자가 양방향 연결을 확립하는 과정이다. [step 1] 클라이언트가 서버에 접속을 요청하는 SYN 패킷을 보낸다. 클라이언트는 SYN을 보내고 SYN/ACK 응답을 기다리는 SYNSENT 상태, 서버는 LISTEN 상태다. [step 2] 서버는 SYN 요청을 받고 클라이언트에게 요청을 수락한다는 ACK와 SYN 패킷을 보낸다. 서버는 ACK을 기다리고 SYN RCVD 상태가 된다. [step 3] 클라이언트는 ACK과 SYN 패킷을 받고 연결이 ESTAB 된다. 클라이언트는 SYN/ACK을 잘 받았으므로 ACK을 보낸다. 서버는 ACK을 받고 연결을 ESTAB 한다. ACK, SYN 정보 전달 방식 TCP 패킷의 헤더에 SYN, ACK, FIN 등의 플래그(flag) 비트가 존재한다. 이 플래그 비트를 설정하여 SYN 요청, ACK 응답, 연결 종료(FIN) 같은 상태 정보를 전달한다. 즉, SYN/ACK은 TCP 헤더 플래그를 통해 표시된다. 3-Way Handshake 시 첫 번째 패킷: SYN 플래그만 켜짐 (S 비트 = 1) 두 번째 패킷: SYN + ACK 플래그 켜짐 (S 비트, A 비트 = 1) 세 번째 패킷: ACK 플래그만 켜짐 (A 비트 = 1) | 비트 | 의미 | 역할 | | ------- | ------------------------- | -------------------------------- | | C (CWR) | Congestion Window Reduced | 혼잡 윈도우 감소 통지 | | E (ECE) | ECN-Echo | 혼잡 경험 알림 | | U (URG) | Urgent | 긴급 데이터 표시 | | A (ACK) | Acknowledgment | 확인 응답 존재 여부 표시 | | P (PSH) | Push | 수신자가 즉시 데이터 처리 요청 | | R (RST) | Reset | 연결 강제 종료 요청 | | S (SYN) | Synchronize | 연결 설정 요청 (초기 SYN 보내기) | | F (FIN) | Finish | 연결 종료 요청 | 2-Way Handshaking을 쓰지 않는 이유 만약 2번만 통신한다면, 서버는 클라이언트의 응답 없이도 연결이 성립됐다고 착각할 수 있다. 중간에 패킷이 유실될 경우 또는 클라이언트가 응답을 못하는 경우 서버는 유령 연결(half-open connection) 을 유지하게 된다. 3-Way Handshake는 송신자와 수신자 모두가 연결 의사를 명확히 확인하게 하여, 연결이 진짜 준비 완료됐는지 검증하는 역할을 한다. 두 호스트가 동시에 연결 시 연결 방법 동시 오픈(Simultaneous Open) 클라이언트와 서버가 동시에 SYN 을 보내고, 서로의 SYN에 대해 ACK를 보내면서 연결이 성립된다. 즉, 양방향으로 SYN, ACK가 교환되면서 정상적으로 3-Way Handshake가 완료된다. SYN Flooding 공격 SYN Flooding은 TCP 3-Way Handshake 과정을 악용한 DoS(Denial of Service) 공격이다. 공격자가 수많은 SYN 패킷을 보내고 서버는 SYN-ACK을 응답했지만 공격자는 최종 ACK를 보내지 않는다 이로 인해 서버는 대량의 미완료 연결(Half-open Connection) 을 계속 유지하게 되고, 결국 서버 자원이 고갈되어 정상 사용자 요청을 처리할 수 없게 된다. 0-RTT 기법 0-RTT(Zero Round Trip Time) 기법은 3-Way Handshake 없이 빠르게 데이터를 전송하려는 최적화 기술이다. 이전에 통신한 적이 있는 서버라면, 과거 세션 정보를 저장해두고, SYN 보내자마자 바로 데이터도 함께 전송한다. 즉, 연결이 완전히 성립되기 전에 미리 데이터를 보내서 시간을 절약하는 방식이다. 4-Way Handshake 🔵 흐름 제어와 혼잡 제어의 차이 | 항목 | 흐름 제어 (Flow Control) | 혼잡 제어 (Congestion Control) | | ---- | ------------------------ | ------------------------------ | | 대상 | 송신자 -> 수신자 간 | 송신자 -> 네트워크 간 | | 목적 | 수신자 과부하 방지 | 네트워크 혼잡 방지 | | 방법 | 수신자가 rwnd로 통제 | 송신자가 cwnd로 조절 | TCP 흐름 제어: 수신자의 버퍼 상황에 맞춰 보내는 양 조절 (Sliding Window, rwnd) TCP 혼잡 제어: 네트워크 상태에 따라 보내는 속도 조절 (Slow Start, AIMD, cwnd) 🔵 UDP가 흐름/혼잡 제어를 하지 않는 이유 UDP(User Datagram Protocol)는 빠른 전송 을 목적으로 설계된 프로토콜이다. 따라서 흐름 제어(Flow Control) 와 혼잡 제어(Congestion Control) 를 일부러 적용하지 않는다. UDP는 비연결형 프로토콜이다. (연결 설정 없이 바로 데이터 전송) 빠른 전송이 목표이기 때문에, 수신자 상태나 네트워크 상황을 고려하지 않는다. 흐름 제어, 혼잡 제어를 하게 되면 오버헤드가 생겨 전송 속도가 느려질 수 있다. 예를 들어, DNS, VoIP(인터넷 전화), 스트리밍 같은 서비스는 약간의 데이터 손실보다 속도가 훨씬 더 중요하다. 즉, UDP는 빠른 전송을 위해 수신자 버퍼 초과, 네트워크 혼잡 여부를 신경 쓰지 않는다. 데이터가 손실되면 상위 Application Layer가 별도로 복구할 수 있도록 한다. 🔵 DHCP DHCP는 IP 주소를 자동으로 할당해주는 프로토콜이다. 클라이언트가 네트워크에 접속할 때, 수동 설정 없이도 자동으로 IP 주소, 서브넷 마스크, 게이트웨이, DNS 등을 할당받을 수 있게 해준다. DHCP 작동 방식: DORA 과정 Discover: 클라이언트가 네트워크에 접속하면, 브로드캐스트로 DHCP 서버를 찾는다. Offer: DHCP 서버가 IP 주소 제안과 함께 설정 정보를 보낸다. Request: 클라이언트가 하나의 Offer를 선택하고 요청을 보낸다. Acknowledge: 서버가 해당 요청을 승인하고, 설정 정보를 최종 전송한다. DHCP의 장점 수동 설정 없이 자동 IP 할당 가능 IP 주소 관리 효율화 (중복 방지, 갱신 가능) 모바일/유동 IP 환경에 적합 🔵 멀티플렉싱과 디멀티플렉싱(포트 번호와 TCP/UDP 연결) 멀티플렉싱과 디멀티플렉싱은 Transport Layer의 핵심 역할 중 하나로, 하나의 호스트에서 여러 애플리케이션 간의 데이터를 구분하고 전달하는 기능을 한다. 멀티플렉싱 (Multiplexing) 송신 측에서 수행 여러 애플리케이션의 데이터(예: HTTP, FTP 등)를 하나의 전송 통로(IP 주소) 로 묶어서 전송 Transport Layer는 각각의 애플리케이션 데이터를 포트 번호로 구분하여 전송 디멀티플렉싱 (Demultiplexing) 수신 측에서 수행 도착한 세그먼트를 포트 번호를 기반으로 해당 애플리케이션에 정확히 전달 포트 번호의 역할 IP 주소는 호스트를 식별 포트 번호는 호스트 내 애플리케이션 프로세스를 식별 TCP, UDP 모두 포트 번호를 통해 각 데이터를 구분

2025년 05월 06일 04:41