사전 서버
개념

서버

gabury1고친 사람 github-actions[bot]

서버는 다른 프로그램이 보낸 요청을 받아 처리하고 답을 돌려줍니다. 먼저 말을 거는 것은 클라이언트입니다. 서버는 누가 부를 때까지 기다립니다. 그 일을 맡은 프로그램도, 그 프로그램이 도는 컴퓨터도 모두 서버라고 부릅니다.

쉽고 빠른 이해

서버는 요청이 오기를 기다렸다가 받아 처리하고 응답을 돌려주는 프로그램입니다. 주소창에 주소를 넣으면 그 문서를 찾아 내주는 웹 서버가 그런 프로그램입니다.

서버에게 요청을 보내는 쪽을 클라이언트라고 합니다. 역할을 서버와 클라이언트로 가르면 데이터와 계산을 한곳에 모아 둘 수 있습니다. 모아 두지 않으면 클라이언트마다 같은 데이터를 따로 들고 있어야 합니다.

도는 모양은 셋입니다.

  1. 요청이 들어올 통로를 열어 두고 기다립니다
  2. 요청이 오면 받아서 처리합니다
  3. 결과를 응답으로 돌려주고 다시 기다리는 상태로 돌아갑니다

대가가 있습니다. 서버는 켜 둔 채로 있어야 합니다. 서버가 멈추면 그 서버를 부르던 클라이언트가 모두 함께 멈춥니다. 요청이 한꺼번에 몰리는 것도 서버가 감당합니다.

상세

관공서 민원 창구를 떠올려 봅니다. 창구는 먼저 사람을 찾아가지 않습니다. 열어 놓고 앉아 있다가 누가 서류를 내밀면 그때 처리해서 돌려줍니다.

서버가 기다리는 요청은 클라이언트가 무엇을 해 달라고 보낸 한 통의 물음입니다. 그 물음에 대한 답으로 돌아오는 것이 응답입니다. 브라우저 주소창에 주소를 넣으면 그 주소가 가리키는 컴퓨터에서 웹 서버가 요청을 받아 문서를 찾아 내줍니다. 돌아온 그 문서가 응답입니다.

클라이언트는 서버에게 일을 맡기는 프로그램입니다. 언제나 클라이언트가 먼저 말을 겁니다. 서버는 먼저 말을 걸지 않습니다. 아무도 부르지 않으면 서버에서는 아무 일도 일어나지 않습니다.

역할을 이렇게 가르는 까닭은 데이터와 계산을 한곳에 모아 두려는 것입니다. 모아 두면 클라이언트가 여럿이어도 같은 값을 봅니다. 가르지 않으면 클라이언트마다 같은 데이터를 자기 안에 들고 있어야 합니다. 그러면 한쪽이 고친 것을 다른 쪽은 모릅니다.

모든 구성이 이렇게 갈리지는 않습니다. 참여자들이 서로 대등하게 직접 주고받는 구성에서는 답하는 역할을 맡은 프로그램이 따로 없습니다. 이런 구성에서 서로를 부르는 이름이 피어입니다.

기다림과 처리를 되풀이하는 고리

서버 프로그램은 켜진 뒤에 기다림과 처리 둘을 되풀이합니다.

서버는 시작할 때 요청이 들어올 통로를 먼저 열어 둡니다. 한 컴퓨터 안에서 어느 프로그램에게 줄 요청인지 가리는 번호를 포트라고 합니다.

서버는 자기가 쓸 포트를 하나 잡습니다. 그리고 그 포트로 오는 요청을 받겠다고 알립니다. 이렇게 통로를 열어 두고 기다리는 상태를 두고 「듣고 있다」고 말합니다.

요청이 도착하면 서버는 그것을 읽어서 무엇을 해 달라는 것인지 가립니다. 필요하면 데이터베이스에서 값을 꺼내 오거나 계산을 합니다. 결과가 나오면 응답을 만들어 돌려줍니다. 그리고 곧바로 다음 요청을 기다리는 상태로 돌아갑니다.

flowchart TD
    A["시작 · 포트를 잡는다"] --> B["기다린다"]
    B --> C["요청을 받는다"]
    C --> D["처리한다"]
    D --> E["응답을 돌려준다"]
    E --> B

화살표가 기다리는 칸으로 되돌아옵니다. 서버가 하는 일은 이 고리를 끝없이 도는 것입니다. 클라이언트에게 보이는 한 번의 주고받음은 이 고리가 한 바퀴 돈 것입니다.

같은 이름으로 불리는 프로그램과 컴퓨터

「서버가 죽었다」는 말은 프로그램이 멈췄다는 뜻일 수도 있고 컴퓨터가 꺼졌다는 뜻일 수도 있습니다. 두 가지에 같은 이름이 붙어 있어서 그렇습니다.

좁은 뜻의 서버는 요청을 받아 답하는 프로그램입니다. 넓은 뜻의 서버는 그런 프로그램을 돌리려고 세워 둔 컴퓨터입니다.

네트워크에서 데이터를 직접 보내고 받는 컴퓨터를 호스트라고 합니다. 넓은 뜻의 서버는 그 호스트 가운데 답하는 일을 맡은 것입니다.

한 컴퓨터 안에서 서버 프로그램은 여럿 돌 수 있습니다. 각자 다른 포트를 잡으면 같은 컴퓨터로 들어온 요청이라도 섞이지 않고 제 프로그램에게 갑니다. 브라우저가 보낸 요청과 메일 앱이 보낸 요청은 각자 다른 포트로 들어갑니다.

flowchart TD
    C1["브라우저"] -->|"요청 · 웹 서버가 잡은 포트로"| W
    C2["메일 앱"] -->|"요청 · 메일 서버가 잡은 포트로"| M
    subgraph 기계["컴퓨터 한 대"]
        W["웹 서버 프로그램"]
        M["메일 서버 프로그램"]
    end

그림에서 서버라고 부를 수 있는 것은 셋입니다. 웹 서버 프로그램, 메일 서버 프로그램, 그리고 둘을 담고 있는 컴퓨터입니다. 어느 뜻으로 말하는지는 대개 문맥이 정합니다.

겹쳐 들어오는 요청을 나눠 받는 세 방법

서버에는 요청이 한 번에 하나씩 오지 않습니다. 앞 요청을 처리하는 동안 다음 요청이 도착합니다. 한 번에 하나만 처리하면 뒤에 온 요청은 앞 요청이 끝날 때까지 줄을 섭니다.

그래서 서버는 여러 요청을 겹쳐서 다룹니다. 겹치는 방법은 셋입니다.

방법 무엇을 하나 대가
요청마다 프로세스 요청이 올 때마다 독립된 실행 단위를 만들어 맡깁니다 만드는 값이 비싸고 메모리를 많이 씁니다
요청마다 스레드 한 프로세스 안에서 실행 흐름만 여러 갈래로 나눠 맡깁니다 메모리를 나눠 쓰므로 서로 밟지 않게 막아야 합니다
한 흐름이 번갈아 응답을 기다리느라 멈춘 요청은 제쳐 두고 준비된 것부터 처리합니다 한 요청이 흐름을 붙잡으면 나머지가 같이 멈춥니다

셋째 방법으로 도는 구조를 이벤트 루프라고 부릅니다. 세 방법이 노리는 것은 같습니다. 응답을 기다리며 노는 시간을 다른 요청에 내주는 것입니다.

서버가 늘 떠 있어야 하는 대가

클라이언트는 필요할 때 켜고 일이 끝나면 끕니다. 서버는 그럴 수 없습니다. 요청이 언제 올지 모르므로 켜 둔 채로 기다려야 합니다. 화면 없이 계속 떠서 기다리는 이런 프로그램을 데몬이라고 부르기도 합니다.

한 대만 두면 그 한 대가 멈출 때 서비스 전체가 멈춥니다. 그래서 같은 일을 하는 서버를 여러 대 두고 요청을 나눠 받게 합니다. 들어온 요청을 어느 대에 넘길지 고르는 것이 로드 밸런서입니다.

flowchart TD
    C["클라이언트"] --> L["로드 밸런서"]
    L --> S1["서버 1"]
    L --> S2["서버 2"]
    L --> S3["서버 3"]

클라이언트는 로드 밸런서 하나만 압니다. 그 뒤에 서버가 몇 대인지는 모릅니다. 한 대가 멈추면 로드 밸런서가 남은 대에만 요청을 보냅니다.

여러 대로 나누려면 조건이 하나 붙습니다. 서버가 앞 요청을 기억하고 있으면, 다음 요청이 다른 대로 갔을 때 그 대에는 기억이 없습니다.

그래서 기억을 서버에 두지 않습니다. 대신 요청마다 필요한 것을 요청 안에 실어 보내게 만듭니다. 이런 성질을 무상태라고 합니다.

관련 항목

서버와 짝을 이루어 요청을 보내는 상대

클라이언트 · 브라우저 · 사용자 에이전트 · 모바일 앱 · 명령줄 도구

맡는 일에 따라 갈리는 서버의 종류

웹 서버 · 애플리케이션 서버 · 오리진 서버 · 업스트림 서버 · 자원 서버 · 인가 서버 · 데이터베이스 서버 · 메일 서버 · DNS 서버 · 파일 서버

서버 앞에 서서 요청을 먼저 받는 중개자

프록시 · 리버스 프록시 · 로드 밸런서 · 게이트웨이 · API 게이트웨이 · CDN

서버가 요청을 주고받을 때 쓰는 통신 수단

네트워크 · 소켓 · 포트 · TCP · HTTP · IP 주소 · DNS

서버 프로그램이 도는 실행 환경

호스트 · 운영체제 · 프로세스 · 스레드 · 데몬 · 가상 머신 · 컨테이너 · 베어메탈 · 클라우드

서버를 여러 대로 굴릴 때 따라오는 개념

무상태 · 세션 · 수평 확장 · 가용성 · 헬스 체크 · 장애 조치 · 타임아웃 · 피어

다른 이름: server · 서버 프로그램 · 서버 기계