본문으로 건너뛰기

안동민 개발노트

본문 시작

서버와 클라이언트 관계 이해

브라우저 클라이언트와 백엔드 서버의 책임을 구분하고 HTTP 요청·처리·응답이 오가는 전체 흐름을 이해합니다.

우리는 지금까지 사용자 화면을 직접 다루는 프론트엔드(Frontend) 개발에 집중해 왔습니다.

HTML, CSS, JavaScript, 그리고 프레임워크를 사용해 복잡한 UI를 구성하는 방법도 익혔습니다.

하지만 실제 서비스는 브라우저 안에서만 완성되지 않습니다.

계정, 데이터 저장/조회, 권한, 보안, 외부 연동처럼 핵심 기능은 대부분 백엔드(Backend)에서 수행됩니다.

즉, 프론트엔드는 사용자와 맞닿은 화면이라면, 백엔드는 그 화면이 제대로 동작하게 만드는 시스템의 중심입니다.

12장 백엔드 기초와 API에서는 프론트엔드와 백엔드가 어떤 방식으로 협력하는지, 그리고 API(Application Programming Interface)가 왜 중요한지 다룹니다.

첫 시작은 가장 기본인 클라이언트-서버 관계를 명확히 이해하는 것입니다.

웹은 기본적으로 클라이언트-서버 모델(Client-Server Model)에 기반하여 작동합니다.

이 모델은 정보를 요청하는 주체(클라이언트)와 정보를 제공하는 주체(서버)로 나뉘어 서로 통신하는 방식입니다.

HTTP 클라이언트·서버 책임 경계

DATA-FLOW · B99 WEB FUNDAMENTALS

HTTP 클라이언트·서버 책임 경계

요청은 method·URL·headers·body를 담고 서버는 routing·validation·authentication·authorization·business logic·data access를 거쳐 응답한다. 클라이언트는 loading·success·error 상태를 렌더링하지만 권한과 데이터 무결성은 서버가 강제한다.

HTTP 클라이언트·서버 책임 경계 브라우저가 method URL headers body를 담은 요청을 보내면 서버가 route, 입력과 권한, domain rule, database를 처리하고 status headers body 응답을 돌려주는 경계 흐름 CLIENTSERVER 브라우저 상태URL · cookie · cache HTTP 요청method · URLheaders · body route 선택method + path 입력·권한 검사400 · 401 · 403실패면 즉시 응답 domain rule업무 불변식 database조회 · 원자적 변경 HTTP 응답status · headers · body 브라우저 해석cache · redirect · parse오류 상태 분기 UI 커밋화면 · URL · focus
  1. 클라이언트 요청

    브라우저가 method·URL·headers·body와 cookie/cache 맥락을 전송한다.

  2. 서버 경계

    route를 고른 뒤 입력과 인증·권한을 검사한다. 실패는 400·401·403 응답으로 끝난다.

  3. 업무와 저장

    통과한 요청만 domain rule과 데이터베이스 조회·변경을 수행한다.

  4. HTTP 응답

    서버가 status·headers·body를 계약으로 반환한다.

  5. 클라이언트 커밋

    브라우저가 cache·redirect·parse 규칙을 적용하고 화면·URL·focus를 갱신한다.

네트워크는 호출 상자가 아니라 책임 경계다. 요청과 응답의 메타데이터가 양쪽 실패 처리까지 연결한다.


클라이언트 (Client)란?

클라이언트는 서비스를 요청하는 쪽입니다.

웹 환경에서 클라이언트는 주로 사용자가 웹 애플리케이션에 접근하기 위해 사용하는 소프트웨어를 의미합니다.

  • 웹 브라우저: Chrome, Firefox, Safari, Edge 등 우리가 인터넷에 접속할 때 사용하는 웹 브라우저가 가장 대표적인 웹 클라이언트입니다. HTML, CSS, JavaScript를 해석하여 웹 페이지를 화면에 렌더링하고, 사용자의 입력(클릭, 타이핑 등)을 받아 서버에 요청을 보냅니다.
  • 모바일 앱: 스마트폰이나 태블릿에 설치된 네이티브 앱(iOS 앱, Android 앱)도 특정 서버에 데이터를 요청하고 응답을 받는 클라이언트가 될 수 있습니다.
  • 데스크톱 애플리케이션: PC에 설치된 프로그램도 특정 서비스를 이용하기 위해 서버에 요청을 보낼 수 있습니다.
  • API 클라이언트: Postman, Insomnia와 같은 도구는 개발자가 직접 HTTP 요청을 만들어서 서버 API를 테스트할 때 사용하는 클라이언트입니다.

클라이언트의 주된 역할은 사용자의 요청을 서버에 전달하고, 서버로부터 받은 응답(데이터, HTML 등)을 사용자에게 적절한 형태로 보여주는 것입니다.


서버 (Server)란?

서버는 클라이언트의 요청을 받아 처리하고, 그에 대한 응답을 다시 클라이언트에게 보내주는 컴퓨터 프로그램 또는 하드웨어를 의미합니다.

서버는 "서비스를 제공하는 자"라는 의미를 가집니다.

  • 웹 서버: 웹 페이지 파일(HTML, CSS, JS, 이미지 등)을 저장하고 있다가 클라이언트(브라우저)의 요청이 오면 해당 파일을 전송합니다. Apache, Nginx 등이 대표적입니다.
  • 애플리케이션 서버 (WAS: Web Application Server): 클라이언트의 요청을 받아 복잡한 비즈니스 로직을 수행하고, 데이터베이스와 연동하여 데이터를 처리하는 역할을 합니다. Java의 Tomcat, Node.js의 Express, Python의 Django/Flask 등이 여기에 해당합니다.
  • 데이터베이스 서버: 대량의 데이터를 체계적으로 저장하고 관리하며, 애플리케이션 서버의 요청에 따라 데이터를 조회하거나 저장합니다. MySQL, PostgreSQL, MongoDB 등이 있습니다.

서버의 주된 역할은 클라이언트의 요청을 기다리고, 요청이 오면 이를 해석하여 적절한 처리(데이터 조회, 저장, 연산 등)를 수행한 후, 결과를 다시 클라이언트에게 응답하는 것입니다.


클라이언트-서버 통신 과정 (HTTP 프로토콜)

웹에서 클라이언트와 서버는 주로 HTTP(Hypertext Transfer Protocol)라는 통신 규약을 사용하여 데이터를 주고받습니다.

이 과정은 다음과 같습니다.

요청 (Request)
  • 사용자가 브라우저에서 웹 주소(URL)를 입력하거나, 링크를 클릭하거나, 버튼을 누르는 등의 행위를 합니다.
  • 클라이언트(브라우저)는 이 행위를 HTTP 요청 메시지로 변환하여 서버로 전송합니다.
  • 요청 메시지에는 URL (어떤 자원을 원하는지), HTTP 메서드 (어떤 동작을 원하는지 - GET, POST, PUT, DELETE 등), 헤더 (부가 정보), 바디 (데이터) 등이 포함될 수 있습니다.
처리 (Process)
  • 서버는 클라이언트로부터 HTTP 요청을 받습니다.
  • 서버는 요청 메시지를 분석하여 클라이언트가 원하는 것이 무엇인지 파악합니다.
  • 필요에 따라 데이터베이스에 접근하여 데이터를 조회하거나 저장하고, 복잡한 비즈니스 로직을 수행합니다.
응답 (Response)
  • 서버는 요청 처리 결과를 HTTP 응답 메시지로 구성하여 클라이언트에게 전송합니다.
  • 응답 메시지에는 상태 코드 (요청 처리 결과 - 200 OK, 404 Not Found, 500 Internal Server Error 등), 헤더 (부가 정보), 바디 (클라이언트에게 전달할 데이터 - HTML, JSON, 이미지 등) 등이 포함될 수 있습니다.
렌더링 (Render)
  • 클라이언트(브라우저)는 서버로부터 받은 HTTP 응답 메시지를 받습니다.
  • 응답 바디에 HTML, CSS, JavaScript 파일이 포함되어 있다면 이를 파싱하여 웹 페이지를 화면에 렌더링합니다.
  • JSON 데이터와 같은 경우, JavaScript 코드를 통해 이 데이터를 가공하여 UI를 동적으로 업데이트합니다.

이러한 요청-응답 과정은 우리가 웹 서핑을 할 때마다 수없이 반복되며, 웹의 기본 작동 원리를 이룹니다.


역할 분리와 협업

클라이언트와 서버의 역할이 명확히 분리되면서, 현대 웹 개발에서는 프론트엔드 개발자와 백엔드 개발자가 각자의 전문 분야에 집중하여 협업하는 것이 일반적입니다.

  • 프론트엔드 개발자: 주로 사용자 인터페이스(UI)와 사용자 경험(UX)을 담당합니다. 서버로부터 데이터를 받아와 화면에 표시하고, 사용자의 상호작용을 처리하여 서버에 요청을 보냅니다. (우리가 앞서 배운 내용들)
  • 백엔드 개발자: 주로 서버, 데이터베이스, 비즈니스 로직, 보안, 인증 등을 담당합니다. 프론트엔드(클라이언트)가 필요로 하는 데이터를 효율적으로 제공하고, 서비스의 핵심 기능을 구현합니다. (이제부터 배울 내용들)

프론트엔드와 백엔드는 서로 다른 언어(JavaScript, Python, Java, PHP 등)와 프레임워크를 사용할 수 있지만, HTTP라는 공통된 통신 규약을 통해 데이터를 주고받으며 하나의 웹 애플리케이션을 완성합니다.

문제가 생겼을 때도 같은 기준을 사용하면 원인을 빠르게 좁힐 수 있습니다.

요청이 올바르게 만들어졌는지, 서버에 도착했는지, 응답이 의도대로 돌아왔는지를 차례로 확인합니다.

클라이언트·서버 실패 상태 분기

FLOWCHART

클라이언트·서버 실패 상태 분기

실패를 요청 발생, 연결, HTTP 상태, 응답 계약, UI 반영 경계로 좁히고 각 경계의 증거를 확인한 뒤 같은 요청으로 재검증한다.

클라이언트·서버 실패 상태 분기 요청 발생 여부에서 시작해 네트워크 응답, 2xx 상태, body와 schema, UI 반영 여부를 순서대로 분기하며 각 실패를 Console, Network, 서버 로그, parser와 렌더 상태 증거로 연결한다. NO YES NO YES NO YES NO YES NO YES 요청이 실제 발생? UI event → fetch 연결·응답 도착? DNS · TLS · CORS status가 2xx? HTTP 경계 body·schema 유효? Content-Type · JSON UI 상태 반영? render · state 클라이언트 wiring Console · event handler · request state 네트워크 경계 Network · DNS/TLS · CORS · timeout HTTP·서버 경계 401/403 auth · 400 validation · 409/5xx log 응답 계약 경계 header · parser · schema error 렌더링 경계 Console · component state · error UI 같은 요청으로 재검증 경계 하나 수정 · 증거 비교

요청 미발생

구분 신호 Network에 항목 없음

확인 증거 event handler·Console·loading state

연결 실패

구분 신호 reject·timeout·CORS

확인 증거 Network, DNS/TLS, abort reason

HTTP 오류

구분 신호 401/403·400·409·5xx

확인 증거 status/body와 서버 로그·request ID

응답 계약 오류

구분 신호 Content-Type·JSON·schema 불일치

확인 증거 raw body와 parser/schema error

UI 반영 오류

구분 신호 응답은 정상이나 화면 상태 실패

확인 증거 component state·render exception

  • 조건을 통과한 정상 경로
  • 경계별 실패 증거
  • 동일 요청 재검증

HTTP 응답이 왔다는 사실과 성공 상태는 다르며, 2xx 이후에도 파싱·schema·UI 반영 경계가 남는다.

클라이언트와 서버의 책임을 분리해서 보면 화면 문제인지, 요청 문제인지, 서버 처리 문제인지 빠르게 좁힐 수 있습니다.

마지막으로 전체 흐름을 점검할 때는 책임 구간별 질문으로 원인을 좁힙니다.


서버-클라이언트 구조 정리

정리 단계에서는 요청과 응답의 책임 경계를 분리해 문제 원인을 빠르게 찾는 관점을 강조합니다.

이번 장에서는 웹 애플리케이션의 가장 근본적인 작동 원리인 서버와 클라이언트의 관계를 명확히 이해했습니다.

이번 절에서는 클라이언트가 정보를 요청하고 서버가 응답하는 구조를 정리했습니다.

HTTP 요청과 응답 흐름을 기준으로 웹 브라우저, 애플리케이션 서버, 데이터베이스 서버의 역할을 구분합니다.

이러한 클라이언트-서버 모델에 대한 이해는 우리가 앞으로 배우게 될 백엔드 개발과 API 설계의 기초가 됩니다.

프론트엔드가 어떤 데이터를 어떻게 요청해야 하는가를 고민한다면, 백엔드는 어떤 데이터를 어떻게 제공하고 처리해야 하는가를 고민하게 될 것입니다.