웹사이트를 운영하려면 서버가 필요하다. 그런데 인프라 구성도를 보면 웹서버, 애플리케이션 서버, DB 서버가 따로 나뉘어 있다. 그 앞에는 로드밸런서가 있고, 같은 역할을 하는 서버도 여러 대씩 배치되어 있다.

웹사이트 하나를 운영하는 데 왜 이렇게 구성을 나누는 것일까?

서버 한 대에 필요한 프로그램을 모두 설치하는 상황부터 생각해 보면, 3-Tier가 필요한 이유를 이해하기 쉽다.

웹사이트를 서버 한 대에 모두 올리면?

간단한 게시판 서비스를 만든다고 가정해 보자. 서버 한 대에 웹서버와 게시판 애플리케이션, 데이터베이스를 모두 설치할 수 있다.

웹서버는 브라우저의 요청을 받고, 애플리케이션은 게시글 조회나 작성 같은 기능을 처리한다. DB는 게시글과 회원 정보를 저장한다. 역할은 서로 다르지만, 같은 서버 안에서 실행되는 것이다.

브라우저·WEB SERVER·WEB APP·DB의 요청 처리 흐름

위 그림은 동적인 웹페이지를 만들어 응답하는 흐름을 보여준다. 그림 속 번호를 따라가면 다음과 같다.

  1. 브라우저가 웹서버에 HTTP 요청을 보낸다.
  2. 웹서버가 애플리케이션 처리가 필요한 요청을 WEB APP으로 전달한다.
  3. 애플리케이션이 필요한 데이터를 DB에서 조회한다.
  4. 조회한 데이터와 화면 틀인 템플릿을 이용해 HTML을 만든다.
  5. 웹서버를 거쳐 브라우저에 응답을 보낸다.

반면 CSS나 이미지처럼 준비된 정적 파일을 제공하는 요청은 애플리케이션과 DB를 거치지 않고 웹서버에서 처리할 수 있다. 그림은 서버가 HTML을 만드는 예시이며, 서비스에 따라 애플리케이션이 JSON 데이터를 응답하고 브라우저가 화면을 구성하기도 한다.

이 그림에서 먼저 볼 것은 각 구성 요소의 역할과 요청의 흐름이다. 그림에 상자가 나뉘어 있다고 해서 각각 별도의 서버에서 실행된다는 뜻은 아니다.

이 역할을 모두 한 서버에 배치하면 구성이 단순하다. 관리할 서버가 적고, 작은 서비스를 시작할 때 비용 부담도 줄일 수 있다. 충분히 선택할 수 있는 출발점이다.

페이지 하나를 열어도 요청은 하나가 아니다

서비스가 커지는 상황을 생각하기 전에, 웹페이지 하나를 불러올 때 어떤 일이 일어나는지 살펴보자.

브라우저는 HTML 문서를 받은 뒤, 화면을 구성하는 데 필요한 CSS, JavaScript, 이미지, 폰트 등을 추가로 요청한다. 실행된 JavaScript가 서버에 데이터를 요청하기도 한다.

네이버 메인 페이지와 개발자도구 Network 탭

네이버 메인 페이지를 연 위 화면을 보면, Network 탭 아래에 **270 requests**가 표시되어 있다. 사용자가 보는 것은 메인 페이지 하나지만, 캡처 시점까지 브라우저에는 270건의 요청이 기록된 것이다.

여기서 270건은 파일 270개와 같은 의미는 아니다. 파일을 가져오는 요청 외에도 데이터 조회, 광고·분석 관련 통신 등이 포함될 수 있다. 또한 사진에서는 Disable cache가 켜져 있으므로, 브라우저 캐시를 사용하는 평소 방문과 요청 수나 전송량이 달라질 수 있다. Network 탭은 이러한 네트워크 요청을 기록하고 확인하는 도구이다.

이 화면만으로 네이버의 서버 구성을 알 수는 없다. 다만 페이지를 한 번 여는 행동 뒤에 여러 종류의 요청이 발생한다는 점은 확인할 수 있다.

이제 이런 요청을 처리하는 서비스의 사용자가 늘어난다고 생각해 보자. 정적 파일 전송, 애플리케이션 실행, DB 조회가 모두 한 서버의 CPU·메모리·디스크 자원을 사용한다.

예를 들어 DB가 많은 메모리를 사용하면 애플리케이션이 사용할 여유가 줄어들 수 있다. 애플리케이션의 연산량만 늘었는데, 같은 서버에 있는 DB까지 함께 더 큰 서버로 옮겨야 할 수도 있다. 서버 자체를 재부팅하면 그 안의 웹서버와 애플리케이션, DB가 함께 영향을 받는다.

이런 상황에서 역할별로 실행 환경을 나누는 구성을 생각하게 된다.

역할에 따라 나누는 3-Tier

3-Tier는 애플리케이션을 표현, 업무 처리, 데이터 저장이라는 세 계층으로 나누어 배치하는 구조이다.

계층 담당하는 역할 웹 서비스에서의 구성 예시
Presentation Tier 사용자에게 화면을 제공하고 입력을 받는다. 화면과 정적 리소스를 제공하는 WEB 계층
Application Tier 요청을 해석하고 서비스의 업무 규칙을 실행한다. 로그인, 주문, 게시글 작성 등을 처리하는 APP 계층
Data Tier 데이터를 저장하고 조회·수정한다. 회원 정보와 게시글을 관리하는 DB 계층

클라우드 인프라에서는 이를 흔히 WEB–APP–DB 또는 WEB–WAS–DB 구성으로 설명한다. WAS는 Web Application Server의 약자로, 웹 애플리케이션이 실행되는 서버를 의미한다. 실제 화면은 브라우저에서 표시되며, WEB 계층은 그 화면을 구성하는 리소스를 제공하는 역할을 맡는다.

여기서 Layer와 Tier도 구분할 필요가 있다. Layer는 소프트웨어 내부의 논리적인 역할 구분이고, Tier는 그 역할을 별도의 실행 환경에 배치하는 구분이다. 코드의 폴더를 세 개로 나누는 것만으로 3-Tier가 되는 것은 아니다.

그렇다면 1-Tier와 2-Tier는 무엇일까? 일반적인 애플리케이션 구조를 기준으로 비교하면 다음과 같다.

구분 역할을 배치하는 방식 예시
1-Tier 화면, 업무 처리, 데이터 저장을 한 실행 환경에 둔다. 로컬 DB를 사용하는 단독 실행 프로그램
2-Tier 클라이언트와 데이터 서버로 나눈다. 업무 처리는 양쪽에 배치될 수 있다. 사용자 PC의 업무 프로그램이 DB 서버에 직접 접속하는 구조
3-Tier 표현, 업무 처리, 데이터 저장을 세 실행 계층으로 나눈다. WEB·APP·DB를 분리한 웹 서비스

웹 인프라 자료에서는 브라우저를 제외한 서버 측 구성을 기준으로, WEB·APP·DB를 한곳에 두면 1-Tier, WEB·APP과 DB를 분리하면 2-Tier라고 설명하기도 한다. 따라서 숫자만 보기보다 어떤 범위를 기준으로 무엇을 분리했는지를 함께 확인하는 편이 정확하다.

WEB Servers·APP Servers·Cloud DB가 구분된 NAVER Cloud Platform의 3-Tier 구성도

위 구성도에서는 WEB, APP, DB의 실행 환경이 분리되어 있다. WEB과 APP에는 여러 서버가 배치되어 있고, 로드밸런서가 각 계층의 서버로 요청을 분산한다.

오른쪽에는 정적 리소스를 위한 Object Storage와 CDN도 있다. 파일을 저장하는 공간과 콘텐츠를 전달하는 네트워크를 활용해, 정적 리소스 제공을 별도로 처리하는 구성이다. 3-Tier를 구성한다고 해서 반드시 그림의 모든 요소를 갖춰야 하는 것은 아니다.

계층을 나누면 무엇이 달라질까?

① 접근 경계를 나눌 수 있다

웹 서비스에 접속한 사용자에게 필요한 것은 서비스의 기능이다. 사용자의 브라우저가 DB에 직접 접속할 필요는 없다.

계층이 분리되어 있으면 서비스 요청의 경로를 다음과 같이 제한할 수 있다.

  • 외부 사용자에게는 웹 진입점을 공개한다.
  • APP 계층은 지정한 WEB 계층이나 로드밸런서의 요청만 받는다.
  • DB 계층은 지정한 APP 계층에서 필요한 DB 포트로 접근하는 통신만 허용한다.

이렇게 구성하면 각 계층에 누가 어떤 경로로 접근할 수 있는지를 따로 정할 수 있다. 실제 제한은 방화벽이나 보안 그룹 등의 규칙으로 적용한다. Microsoft의 N-Tier 가이드도 데이터 계층에 대한 접근을 중간 계층으로 제한하는 구성을 설명한다.

물론 서버를 나누기만 하면 보안이 완성되는 것은 아니다. 분리된 경계에 맞는 접근 규칙과 애플리케이션의 인증·권한 검사가 함께 있어야 한다.

② 바쁜 계층을 따로 확장할 수 있다

예를 들어 주문 처리량이 늘면서 APP 서버의 CPU 사용률이 높아졌다고 가정해 보자. WEB과 DB에는 아직 여유가 있다.

이때 APP 계층만 서버 사양을 높이거나, 서버 수를 늘리는 선택을 할 수 있다. 계층마다 필요한 자원을 따로 늘릴 수 있다는 것이 3-Tier의 장점이다.

다만 서버를 추가한 만큼 처리량이 그대로 늘어나는 것은 아니다. 여러 APP 서버가 요청을 나누어 처리하려면 요청 분산과 로그인 상태 관리 등을 고려해야 한다.

무엇보다 먼저 확인할 것은 병목의 위치이다. DB 조회가 느린 상황에서 APP 서버만 늘리면, DB에 전달되는 요청이 늘어 문제가 더 커질 수도 있다.

③ 자원과 변경의 영향을 줄일 수 있다

WEB·APP·DB가 별도의 가상 서버에서 실행되면 각자 할당된 CPU와 메모리를 사용한다. 예를 들어 APP 프로세스의 메모리 사용량이 급증해도, 같은 운영체제 안에서 DB의 메모리까지 함께 압박하는 상황은 줄일 수 있다.

변경 작업의 범위도 나누기 쉬워진다. WEB 서버의 운영체제를 재부팅하는 작업 때문에 DB 서버까지 함께 재부팅할 필요는 없다.

다만 계층 사이의 의존성은 남아 있다. APP의 응답이 느려지면 WEB에서 기다리는 요청이 쌓일 수 있고, DB 구조를 바꾸면 APP 코드도 수정해야 할 수 있다.

분리를 통해 얻는 것은 자원과 작업 범위를 조절할 여지이다. 계층 사이의 영향까지 모두 사라지는 것은 아니다.

계층 분리와 이중화는 어떻게 다른가?

3-Tier 구성도를 보면 서버가 여러 대 등장하기 때문에, 계층 분리와 이중화를 같은 개념으로 생각하기 쉽다. 하지만 두 가지는 해결하려는 문제가 다르다.

구분 중심 질문 구성 예시
계층 분리 역할을 어디에서 처리할 것인가? WEB·APP·DB를 별도의 서버에 배치
이중화 한 구성 요소가 멈추면 누가 대신 처리할 것인가? APP 서버를 두 대에 배치하고 정상 서버로 요청을 전달

WEB, APP, DB를 각각 한 대씩 두면 3-Tier이지만, 각 계층은 여전히 한 대에 의존한다. DB 서버가 멈추면 WEB 서버가 살아 있어도 DB를 사용하는 기능은 정상적으로 동작하기 어렵다.

장애에 대비하려면 각 계층에서 대체할 구성 요소를 마련하고, 장애를 감지해 정상 구성 요소로 요청이나 역할을 넘길 수 있어야 한다. 배치 위치도 함께 고려해야 한다.

세 번째 이미지의 DB에는 Master(write)와 Slave(read)가 표시되어 있다. 이는 쓰기와 읽기의 역할 구분을 보여준다. 이 그림만으로 장애 시 자동으로 역할이 전환된다고 판단할 수는 없다. 읽기 부하 분산을 위한 복제와 장애 대응을 위한 구성은 구체적인 동작을 따로 확인해야 한다.

모든 서비스에 3-Tier가 필요할까?

계층을 나누면 관리할 실행 환경과 통신 경로가 늘어난다. 서버 방식이라면 각 서버의 비용뿐 아니라 패치, 모니터링, 로그 확인 같은 운영 작업도 늘어난다. 계층 사이의 네트워크 통신도 고려해야 한다.

작은 실습용 서비스라면 한 서버에서 시작할 수 있다. 애플리케이션과 DB의 관리 요구가 달라지면 DB부터 분리하는 선택도 가능하다. 정적 파일만 제공하는 사이트라면 APP과 DB가 필요하지 않을 수도 있다.

3-Tier를 이해하고 나면 구성도를 볼 때 물어볼 질문이 생긴다. 이 경계는 어떤 접근을 제한하기 위해 나누었는지, 어느 계층을 따로 확장하려는지, 한 서버가 멈췄을 때 무엇이 계속 동작해야 하는지이다.

그 질문에 답할 수 있을 때, 계층을 나눈 이유도 설명할 수 있다.

참고 자료