Web에 대하여

안준성·2024년 10월 11일

Web

목록 보기
6/7
post-thumbnail

웹이란 무엇일까
굉장히 자주 듣고 자주 쓰지만, 정작 웹이 무엇이냐 했을 때 깔끔하게 설명하기가 쉽지 않았다.
웹, 인터넷, 인터넷 브라우저, WAS 등 자주 등장하는 용어들에 대해 정리해본다.

웹과 인터넷

먼저 인터넷부터 보자.
인터넷은 pc, 휴대폰 같은 호스트들을 유선/무선으로 서로 연결하여 통신할 수 있게 한 네트워크 인프라 + 통신 방식(IP)을 포괄한 것이다.

이 네트워크 상에서 각 호스트는 IP(이름부터 인터넷 프로토콜) 주소를 부여받아, 라우팅을 통해 네트워크 상의 어떤 호스트와도 통신할 수 있게 된다.

이 때, 이 인터넷 인프라를 통해 텍스트, 이미지 같은 하이퍼텍스트 콘텐츠를 주고 받기 위해 고안된 기술이 바로 Web이다.

Web은 HTTP/HTTPS를 기반으로 동작하며(이름부터 하이퍼텍스트 전송 프로토콜), HTML, CSS, Javascript와 같은 기술로 구성된 기술 스택이다.

계층적 관점에서 보자면, 인터넷은 물리계층부터 전송계층까지 포괄하는 통신 인프라이고,
웹은 그 위 애플리케이션 계층에서 동작하는 기술이다.


웹 개발의 역사

1. CGI

초기 웹 개발에선 웹 페이지에 동적인 데이터를 포함하기 위해 CGI(웹서브에서 했던 그녀석) 기술을 사용했다.
CGI는 클라이언트로부터 요청이 들어오면, 웹 서버가 서버 컴퓨터에 위치한 외부 프로그램(그냥 컴퓨터에 있는 다른 프로그램)을 별도의 프로세스로 생성 및 실행하여, 그 표준 출력을 HTTP 응답 본문에 그대로 실어 보내는 방식이다.

이렇듯 CGI는 매 요청마다 프로세스를 새로 생성하기 때문에, 서버 리소스 소모가 컸다.
이에 자바 진영에서는 이를 대체하기 위해 Servlet API 컴포넌트를 만들었다.

2. Servlet

Servlet은 웹 서버 위에서 실행되는 프로그램(자바 객체)으로,
웹 서버로부터 HTTP 요청을 받아 동적인 데이터를 처리하고, 그 결과를 HTML 문자열로 구성하여 응답을 생성한다.

참고로 이렇게 서블릿을 이용해 요청을 처리하는 웹 서버를 서블릿 컨테이너라고 부르고,
대표적인 서블릿 컨테이너로는 Tomcat이 있다.

3. Spring Framework

하지만 서블릿도 매번 HttpServlet을 상속받아 doGet(), doPost() 같은 메서드들을 직접 구현하고, 응답을 HTML 문자열로 일일이 구성해 PrintWriter로 찍어야 했다.

이러한 복잡함을 줄이기 위해 서블릿을 한번 감싸서 추상화한 것이 바로 스프링 프레임워크다.
스프링은 서블릿 수준의 저수준 코드를 직접 작성하지 않고도, MVC 구조나 DI, 트랜잭션, 보안 등 다양한 기능을 제공할 수 있게 지원한다.

스프링도 내부적으로 서블릿을 기반으로 동작하기 때문에,
요청이 들어오면 DispatcherServlet이라는 중앙 서블릿이 요청을 받고,
이 서블릿이 요청에 매핑(@GetMapping("/user"))되어 있는 Controller로 매핑해준다.

이렇게 요청을 받은 컨트롤러가 반환한 내용은 HttpServletResponse에 기록되어, 톰캣이 이 응답을 클라이언트에게 전송한다.

즉, 추상화되어 개발자가 서블릿을 직접 작성하지 않는다 뿐이지, 내부적으로는 기존 서블릿과 동일하게 처리되는 것이다.

이 후 Spring Boot에서는 Tomcat과 같은 서블릿 컨테이너를 내장하고,
실행에 필요한 의존성 라이브러리들을 함께 하나의 JAR 파일로 패키징하여,
실행환경에서 WAS 설치 없이 java -jar 명령만으로 실행할 수 있도록 지원한다.

또한 컴포넌트 스캔을 통해,
필요한 Bean을 자동으로 구성해주는 Auto-Configuration 기능을 제공하여,
복잡한 설정 없이도 실행 가능한 기본 설정을 지원한다.

즉, Spring Boot는 전통 Spring 환경에
'자동 설정 + 내장 서버 + 스타터 의존성'을 도입하여,
기존에 Tomcat을 따로 설치하고 WAR 파일을 배포하는 등의 귀찮은 과정 없이도
Spring 웹 애플리케이션을 개발할 수 있게 도와준 도구이다.


웹 서버와 웹 애플리케이션 서버

웹 서버는 기본적으로 HTML, CSS, JS와 같은 정적 리소스에 대한 HTTP 요청을 받아 응답을 반환해주는 서버이다.

대표적인 웹 서버로는 Nginx가 있는데,
Nginx는 C로 작성된 이벤트 기반 웹 서버로,
가볍고 성능이 뛰어나 리버스 프록시나 로드밸런서, 정적파일 처리, HTTPS 종료 등 다양한 목적으로 많이 활용된다.

반면 Tomcat은 Java로 작성된 WAS(웹 애플리케이션 서버)로,
자바 웹 애플리케이션 실행에 특화된 서블릿 컨테이너이다.
물론 Tomcat도 ~/static/에 정적 파일을 두면 DefaultServlet을 통해 서빙이 가능하지만,
Nginx 같은 전문 웹 서버에 비해 성능이 떨어져 주로 동적 요청 처리 전용으로 많이 쓰인다.

따라서 개발할 때는 Tomcat만 써서 개발하다가,
실제 운영 환경에서는 Nginx와 같은 웹서버를 앞단에 배치하여,
정적 파일은 바로 처리하고, 동적 요청만 톰캣으로 전달(리버스 프록시)한다던가,
HTTPS를 종료시켜 Nginx 뒷단부터는 HTTP 평문으로 통신한다던가,
로드 밸런싱을 통해 여러 Tomcat 인스턴스로 요청을 분산시키는 등
웹서버와 WAS의 역할을 분리하여,
성능, 보안, 확장성 측면에서 더 나은 아키텍처를 구성할 수 있다.


웹 애플리케이션과 WAS

웹 애플리케이션은 흔히 웹 개발에서 백엔드를 개발 한다고 했을 때
개발하는 것이 웹 애플리케이션이다.

즉, 클라이언트의 요청을 받아 처리하고,
필요 시 데이터베이스와 통신하여 응답을 생성하는 서버 측 애플리케이션을 뜻한다.

웹 애플리케이션 서버는 이러한 웹 애플리케이션을 실행하는 서버로,
동적 리소스를 요청하는 HTTP 요청을 받아,
웹 애플리케이션을 실행하고, 그 결과를 HTTP 응답으로 만들어 전송하는 서버 측 런타임 환경이다.

Spring Boot를 이용해 개발한다고 하면 이미 Tomcat 같은 WAS가 내장되어있어,
WAS에 대해 따로 신경쓰지 않고도 웹 애플리케이션 로직 개발에만 집중할 수 있게 도와준다.


프론트엔드와 백엔드

앞서 말했듯이 백엔드 개발은 WAS에서 돌아가는 서버 측 웹 애플리케이션을 개발하는 것이다.
그렇다면 프론트엔드 개발은 무엇을 개발하는 것일까?

프론트는 사용자의 브라우저에서 실행되는 클라이언트 측 애플리케이션을 개발한다.
HTML/CSS/Javascript 또는 React, Vue와 같은 도구를 통해 UI를 구성하고,
사용자의 입력을 받아 상호작용하며,
필요 시 백엔드 API를 호출하여 동적인 데이터를 받아 화면에 업데이트하는
Javascript 프로그램을 만드는 것이다.

여기서 브라우저는 HTML, CSS, JS 파일을 해석하고 실행하는 런타임 환경이며,
프론트엔드 개발의 결과물인 HTML/CSS/JS는 정적 파일이지만,
브라우저가 이를 실행하면서 동적인 동작을 수행하기 때문에
클라이언트 애플리케이션이라고 부른다.
(정적인 jar 파일을 JVM이 실행하여 로직이 작동하는 것과 유사한 개념이다)

그렇다면 이 정적 파일들을 서빙해줄 웹 서버가 필요할 것이다.
일반적으로 Nginx와 같은 정적 파일 전용 웹 서버가 사용되지만,
별도의 웹 서버 없이 하나의 WAS(Tomcat, Node.js + Express 등)에서
정적파일 서빙까지 하는 경우도 많다(고 한다).

따라서 사용자는 url을 통해 웹 서버(혹은 WAS)에 접속하여
리소스(HTML/CSS/JS)를 요청하고,
응답 받은 파일들을 브라우저가 실행 및 렌더링하여
최종적으로 화면 상에서 볼 수 있는 것이다.


프론트/백엔드 구조에서의 요청 처리 흐름

1. 클라이언트 초기 접속 및 정적 리소스 처리

  1. 사용자가 브라우저를 통해 웹사이트 접속 (URL 입력)
  2. 브라우저가 웹 서버(Nginx 또는 WAS)에 HTML, CSS, JS 등의 정적 리소스를 요청
  3. 웹 서버(또는 WAS)가 정적 파일들을 응답
  4. 브라우저가 HTML, JS, CSS 파일을 해석하고 실행하여 화면에 렌더링
  5. 사용자는 화면을 보고 상호작용 (클릭, 입력 등)

2. 클라이언트 이벤트 및 백엔드 연동

  1. 프론트엔드 애플리케이션(JS)이 사용자 입력을 감지하고, 필요 시 백엔드 API를 호출 (예: fetch/axios로 POST /api/login 등)
  2. 백엔드 서버(WAS)의 Tomcat이 해당 HTTP 요청을 수신

3. 백엔드 요청 처리 및 응답 생성

  1. Tomcat이 DispatcherServlet을 실행하여 요청을 전달
  2. Spring MVC의 DispatcherServlet이 매핑된 Spring Controller의 메서드를 호출
  3. Controller 내부에서 Service → Repository → DB 등 계층적으로 비즈니스 로직 수행
  4. 처리 결과를 Controller가 반환하면, ViewResolver 또는 MessageConverter가 이를 HTML/JSON 형태로 변환
  5. 변환된 응답은 HttpServletResponse 객체에 기록됨
  6. Tomcat이 이 응답 버퍼를 읽어 웹서버에 HTTP 응답(WAS 단일 구조면 바로 브라우저로 응답)

4. 응답 반영 및 UI 갱신

  1. 웹 서버가 이 응답을 브라우저로 전달
  2. 브라우저가 응답(JSON/HTML 등)을 해석하고, 프론트엔드 로직에 따라 화면을 동적으로 갱신

이렇게 웹과 관련된 전체적인 흐름과 개념들을 Spring을 예시로 알아보았다.
사실 이러한 것들을 몰라도 웹 앱을 개발할 수 있지만
서블릿이나 웹 서버, WAS 같은 개념들은 무시하고 지나치기엔 꽤나 자주 마주치기도 하고, 프론트엔드에 대해서도 같이 한번 정리를 할 필요가 있다고 생각했다.

정리하고 나니 확실히 전체적인 흐름이 머릿속에 그려지며 마음에 평화가 찾아온다.
물론 이걸 몰라도 웹 앱은 충분히 개발할 수 있겠다는 생각도 같이 든다.

여담

뭔가 웹 서핑을 할 때는 하나의 브라우저 창에서 네이버도 켰다가,
유튜브에서 영상도 봤다가, 마치 같은 공간에서 이동하는 것처럼 느껴졌었는데,
실제로는 전혀 다른, 쌩판 남인 별개의 서버에 접속해서
요청을 보내고 응답을 받아서 화면에 띄우는 과정이었다는게
당연한거긴 한데 새삼 다시 한번 깨달을 수 있었다.

profile
안녕하세요

0개의 댓글