프록시 서버 구현

2025. 5. 14. 11:31개발

프록시 서버 구현 - 캐시와 병렬 처리로 효율 UP!

이번 글에서는 C언어로 구현한 프록시 서버(proxy server)에 대해 정리해볼게요. 특히 캐시를 어떻게 저장하는지동시 접속 요청을 어떻게 처리하는지를 중심으로 볼 거예요.


 1. 구조 개요

  • 클라이언트로부터 HTTP 요청을 받아 서버에 전달하고 응답을 다시 클라이언트에 전달하는 중계 역할을 해요.
  • 자주 오는 요청은 캐시에 저장해서 더 빠르게 응답할 수 있어요.
  • 여러 클라이언트가 동시에 요청해도 각 요청을 스레드로 처리해서 병렬로 응답할 수 있어요.

2. 캐시 구조: 연결리스트 기반의 LRU 정책

캐시는 웹 객체(web_object_t)를 저장하는 이중 연결리스트(doubly linked list) 형태로 구현되어 있어요.


typedef struct web_object_t {
  char path[MAXLINE];          // 요청 경로 (URI)
  int content_length;          // 컨텐츠 길이
  char *response_ptr;          // 실제 응답 데이터
  struct web_object_t *prev, *next; // 이전, 다음 노드
} web_object_t;

LRU(Least Recently Used) 방식으로 작동해요:

  1. 새로운 객체는 항상 맨 앞(root)에 삽입
  2. 사용된 캐시는 다시 맨 앞으로 이동 (read_cache)
  3. 전체 캐시 크기를 초과하면 맨 끝(lastp)부터 제거

관련 주요 함수들:

  • find_cache(path) – 요청한 path가 있는 캐시 객체를 찾아 반환
  • send_cache(obj, fd) – 캐시된 응답을 클라이언트로 전송
  • read_cache(obj) – 사용된 캐시를 리스트 맨 앞으로 이동
  • write_cache(obj) – 새로운 응답을 캐시에 저장 (용량 초과 시 제거)

 3. 요청 동시 처리: 스레드 기반 병렬 구조

이 서버는 클라이언트 요청을 하나씩 순차적으로 처리하지 않고, 요청마다 새로운 스레드를 생성해서 동시에 병렬로 처리해요.


while (1) {
  connfdp = Malloc(sizeof(int));
  *connfdp = Accept(...);
  Pthread_create(&tid, NULL, thread, connfdp);
}

thread 함수는 각 요청을 처리하고, 끝나면 자동으로 리소스를 정리해줘요:

  • Pthread_detach() – 스레드 종료 시 자동으로 자원 반환
  • handle_client(connfd) – 요청 처리 함수 (GET/HEAD)

요즘 웹 환경처럼 수많은 요청이 동시에 들어오는 상황에서 매우 효율적인 구조죠!


4. 마무리 요약

  • 캐시는 메모리 절약과 빠른 응답을 위해 필수!
  • LRU 정책으로 오래된 응답부터 삭제
  • 스레드로 동시 요청 처리 → 고성능 서버 구현 가능

 

웹 프록시 서버 git 주소 : https://github.com/applepc24/tiny_web-proxy/blob/main/proxy.c