Back-end

[Back-end] 서버와 클라이언트

창모의 개발사전 2025. 9. 11. 08:26

 

서버와 클라이언트란?

 

서버와 클라이언트의 관계

[Server]

서버란 클라이언트로부터의 요청을 무한정 대기하며 요청이 들어오면 요청에 해당하는 데이터 및 로직을 거쳐 클라이언트에 원하는 결괏값을 제공하는 역할을 하는 것.

[Client]

정적/동적 스크립트에 바인딩할 데이터들을 어떤 정해진 역할을 수행하는 서버에 요청하여 원하는 결괏값을 요청하는 형태의 프로그램.

 

서버는 클라이언트에게 서비스를 제공하는 자

클라이언트는 서버에게 서비스를 요청하는 자

 


서버는 왜 존재하고 왜 실행해야만 할까?

우리가 기본적으로 개인 환경에서 코드를 작성한다면

print("hello, world!")

 

위와 같은 일회성으로 실행이 된다.

이런 스크립트들은 우리가 컴파일한 순간 코드의 처음부터 끝까지 딱 한 번만 실행이 된다.

 

 

예를 들어 우리가 두 수를 입력 받아 두 수의 더한 값을 출력하는 코드를 작성했다고 하자.

num1, num2 = map(int, input().split())

def plus_num(num1, num2):
		return num1 + num2
		
print("함수 호출 결과 : ", plus_num(num1, num2))

 

그럼 위와 같은 결과가 출력된 후 프로그램은 종료된다.

 

만약 우리가 계산기 프로그램을 사용할 때 위와 같이 한 번만 실행이 되고 종료가 되면 어떻게 될까?

우리는 더하기를 할 때 매번 프로그램을 실행시키고 해야할 것이다.

 

그렇다면 이런 코드는 어떨까?

def plus_num(num1, num2):
		return num1 + num2

while(True):
	num1, num2 = map(int, input().split())
	
	if num1 > 1000 or num2 > 1000:
		break
		
	print("함수 호출 결과 : ", plus_num(num1, num2))

 

이렇게 작성을 하면 입력 수가 1000보다 작다면 우리가 종료하기 전까지 계속해서 실행될 것이다.

→ 즉, 내가 원하는 작업(더하기)을 수행할 수 있게 계속 대기를 하는 것이다. 지금은 단순한 더하기를 수행하는 역할을 하지만 저 루프 안에 추가적으로 다른 작업을 수행하는 로직을 구현한다면 내가 원하는 요청에 맞게 처리하도록 설계할 수 있을 것이다.

 

서버는 이런 개념과도 비슷하다.

프로그램을 실행하고 사용자(클라이언트)의 입력을 대기하고 입력(요청)이 들어오면 해당하는 결괏값을 반환해준다.

 

즉, 서버는 클라이언트의 요청을 처리해서 결괏값을 제공해주기 위해 무한정으로 클라이언트의 요청을 대기하는 프로그램이다.

나아가 프로그램을 개발하게 된다면 여러 사용자들이 존재하게 될 것이다. 개발자는 사용자에게 안정적이고 지속적으로 서비스를 제공해야만 한다.

사용자에게 지속적으로 서비스를 제공하기 위해서는 우리가 작성한 스크립트에 역할을 부여해야 한다.

사용자의 요청을 무한정 대기하며 처리하라는 역할을 부여하고 → 이것이 바로 우리가 사용하는 ‘서버’가 된다.


웹 서버

이제 우리는 개발한 두 수 더하기 프로그램을 잘 사용하고 있다.

그런데 여기서 문제가 발생한다. 우리가 개발한 프로그램은 해당 컴퓨터를 사용하는 사람. 즉 한 사람만 사용할 수 있다는 것이다. → 프로그램을 사용하려는 사람이 5명일 때, 프로그램은 단 한 사람만이 사용할 수 있고 동시에 한 컴퓨터를 사용하지 못하기

때문에 나머지 4명은 앞 사람이 끝날 때까지 대기해야 한다. 여기서 병목이 발생하게 된다.

사용자들은 기다리다 지쳐 프로그램을 사용하지 않게 될 것이고 사용자의 만족도가 아주 떨어질 것이다.

 

그래서 우리는 여러 명이 동시에 사용할 수 있는 계산기 프로그램을 개발하려고 한다.

그럼 어떻게 해야할까? 컴퓨터를 사용자의 수만큼 늘려서 준비한다? 아마 이렇게 되면 사용자가 100명 , 10000명이 될수록 비용은 어마무시하게 늘어날 것이다.

 

이 문제를 해결하기 위해 웹 서버가 등장한다.

우리는 무언가 검색하거나, 대화를 하거나, SNS를 하는 등 웹 페이지를 통해서 많은 기능들을 요청하고 처리한다.

그렇게 우리는 계산기를 사지 않고도 웹 페이지에서 계산기 기능을 사용할 수 있고, 날씨 정보를 제공받을 수 있고,

시간을 확인할 수 있다.

 

그럼 웹 서버란? 이름으로 알 수 있듯이 웹에서 처리되는 모든 기능과 요청을 받아 처리하는 역할을 하는 서버이다.

웹에서 처리하는 프로그램을 개발하여 사용자의 요청을 무한정 대기하여 처리하는 역할을 부여받은 서버라고 볼 수 있다.

 

 

자 여기서 여러 사용자가 요청을 보낼 때, 요청하는 방식이 다 다르다면?

예를 들어 한국인과 일본인이 각자 자신의 언어로 한 미국 식당에 가서 주문을 요청하면 그 누구도 제대로 알아듣고 원하는 결과를 제공하지 못할 것이다.

 

그래서 이러한 웹 서버에 대한 클라이언트들의 약속된 언어를 정해놓고 대화를 하는데 이 규칙이 바로 ‘HTTP’이다.

 

물론 사용자가 직접 이 규칙을 지켜서 요청을 해야하는 건 아니다. 프로그램 개발자는 이 규칙을 통해 사용자의 요청을

이 규칙에 맞게 번역을 하고 서버에 전달을 하게 설계를 진행한다.

 

웹 서버는 html, css, javascript같은 정적 컨텐츠 형태의 데이터를 처리하고 제공한다.

즉, 사용자가 서버에 웹에 대한 정보를 얻기 위해서 요청을 하면 웹 서버는 사용자에게 이미지, 회사 소개서와 같은

고정적인 내용이 담긴 정적 컨텐츠를 제공한다.

정적 컨텐츠에 대해 추가적으로 설명을 더하자면 로그인이나 수정하는 등 기능없이 그냥 사전같이 읽기 용도로만 되어있는

컨텐츠라고 생각하면 쉽다.

그래서 우리는 웹 서버에 컨텐츠를 요청하면 서버에서는 미리 다운 받아 놓았던 html, css 파일 등을 사용자에게 제공을 해주는

역할만 한다.


WAS (Web Application Server)

WAS란?

보통 우리가 로그인을 하거나 구매를 하는 등 행위를 할 때, 개인의 정보가 담긴 데이터를 기반으로 결과를 반환하는 흐름이다.

→ 사용자의 요청에 따라 로직을 수행하는 코드를 실행하거나 DB를 조회해 요청에 맞는 결괏값을 반환해주는 서버 역할이다.

 

그렇다면 이 WAS는 웹 서버와 어떤 관계이며 어떻게 연계되는걸까?

WAS와 웹 서버는 철저히 역할이 분리되어 있다. 웹 서버는 만들어진 html파일을 사용자에게 전달하는 역할.

그리고 WAS는 요청에 맞게 데이터를 바인딩하는 역할.

그래서 웹 서버는 사용자의 요청을 받아서 그 요청을 다시 WAS에게 전달한다.

WAS는 전달받은 요청에 따라 데이터를 바인딩하고 다시 웹 서버에 전달하고

최종적으로 생성된 결괏값을 웹 서버가 사용자에게 전달하는 흐름이다.

 

위 그림과 같은 형태로 연계된다.

 

이러한 형태의 장점은 뭘까?

  1. 완벽한 역할 분리 : 웹 서버와 WAS의 역할이 명확히 분리되어서 온전히 자신의 업무에 집중할 수 있어 효율이 높아진다. (처리 속도 등)
  2. 보안 강화 : 핵심 로직과 데이터를 다루는 WAS는 외부 사용자에게 직접 노출되지 않기 때문에 해킹이나 공격들로부터 보호할 수 있다.
  3. 확장 : 사용자가 많아질수록 하나의 서버로 모든 데이터를 처리하는 데에는 자원과 시간적 한계가 존재한다. 그래서 WAS를 여러 대 구축해 안정적으로 요청을 처리할 수 있다.

이제 이 흐름을 따라 우리가 앞에서 말한 통신 규칙인 ‘HTTP’에 맞게 사용자의 요청을 처리한다.

이 역할을 담당하는 게 웹 서버의 역할이기도 하다.

 

 

 

흔히 웹에서 요청하는 행위는 크게 Create, Read, Update, Delete 네 가지로 나눌 수 있고, 이걸 줄여서 CRUD라고도 부른다.

사용자는 생성하고, 조회하고, 수정하고, 삭제하는 크게 네 가지의 처리를 요청한다고 생각을 한다는 것이다. 이걸 HTTP 메서드로 매핑을 하게되면

Create - Post, Read - Get, Update - Put, Delete - Delete 가 된다.

 

웹 서버는 이렇게 구분된 요청에 따라 WAS에 데이터 처리를 요청하게 되고 결과를 받아 다시 사용자에게 제공한다.

여기서 요청을 Get, Put, Post 등으로 역할에 따라 구분하지 않고 단일 메서드로만 처리를 하게 된다면 어떻게 될까?

다시 그 요청이 어떤 행위를 요청하는지 분류하고 그에 따라 처리를 요청하는 식으로 비효율적으로 흘러갈 것이다.

→ 마치 우체국에서 대출, 소포, 우편 등 업무를 하나의 창구에서 모두 처리하는 것과 비슷하다.

업무 분리가 되지 않아 효율적으로 운영하지 못한다.

 

그래서 우리는 GET, PUT, POST, DELETE와 같은 역할을 명확히 분리하여 처리를 한다.

물론 사용자의 입장에서는 신경쓸 필요 없고 개발자가 설계를 하는 것이다.

 

이런 규칙을 우리는 ‘REST API’라고 부른다.


REST API가 뭐지?

REST는 Representational State Transfer의 약자로 자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것을 의미한다.

즉 위의 문제를 효율적으로 해결하기 위해서 나온 규칙이 REST API인 것이다.

이렇게 역할 별로 구분을 해서 명시한다. 같은 item이지만 메서드 별로 역할이 달라 어떤 요청을 처리하는지 명확해진다.

기능 REST API REST가 아닌 방식
생성 POST /item POST /insert_item
조회 GET /item/{id} POST /get_item
수정 PUT /item/{id} POST /update_item
삭제 DELETE /item/{id} POST /delete_item