Skip to content

domukLog

웹 아키텍쳐 101 - 번역

아키텍쳐, DevOps8 min read


​--- title: "웹 아키텍쳐 101 - 번역" date: 2020-11-01 description: "Web Architecture 101 한국어 번역" slug: "/web-architecture101" tags:

  • 아키텍쳐
  • DevOps

Web Architecture 기본 개념 - 웹 개발을 시작할 때 알았다면 좋았을 것들

Jonathan Fulton 님의 글 을 의역했습니다.

web architecture diagram

이 다이어그램은 Storyblocks의 서비스 아키텍쳐를 제법 잘 표현한 그림입니다. 경험 많은 웹개발자가 아니시라면, 꽤 복잡해보이실 수 있어요. 각 컴포넌트를 자세히 알아보기 전에, 아래 내용을 보면 좀 더 접근하기 편할 겁니다.

구글에 “Strong Beautiful Fog And Sunbeams In The Forest” 를 입력하면, 첫번째 검색결과로 Storyblocks이 나옵니다. *stock 이미지와 벡터 이미지 사이트입니다.

사용자가 검색 결과를 클릭하면 유저의 브라우저가 Storyblocks의 이미지 상세페이지로 리디렉션합니다. 내부적으로, 유저의 브라우저는 DNS 서버에 Storyblocks의 주소를 조회하는 요청을 하고, 그 결과를 가지고 요청합니다.

요청은 Storyblocks의 Load Balancer에 도달하고, 요청을 처리 중에 우리가 서비스 중인 10개 이상의 웹 앱 서버 중 하나를 랜덤으로 결정합니다. 웹 앱 서버캐싱 서비스에서 이미지에 대한 정보를 조회하고 데이터베이스에서 남아있는 데이터를 가져옵니다. 우리는 이미지를 위한 color profile이 처리되지 않았다는 걸 알아차리고, Job Queue에 "color profile" job을 보냅니다. Job Queue는 우리가 명령한 job들을 비동기로 처리하고 결과를 적절히 데이터베이스에 업데이트합니다.

그런 다음, 우리는 input으로서 사진의 제목을 가지고 full text search service에 요청을 보내서 유사한 사진을 찾는 시도를 합니다. 사용자가 Storyblocks 회원으로 로그인 된 상태라면, 그 사람의 계정 정보를 우리의 계정 서비스에서 가져옵니다. 마지막으로, data firehose에 페이지뷰 이벤트를 보내서 우리의 cloud storage system에 저장되고, 결국 Data warehouse에 로드되도록 합니다. 데이터 분석가들은 이를 바탕으로 비즈니스 문제를 연구할 수 있죠.

이제 웹 앱 서버는 HTML문서를 렌더링하고 로드밸런서를 통해 유저의 브라우저에 돌려보냅니다. 우리가 CDN으로 연결해둔 cloud storage system을 통해 로드된 Javascript와 CSS asset이 페이지에 포함되고, 결국 유저의 브라우저는 CDN와 통신하여 컨텐츠를 읽어옵니다.

끝으로, 유저의 브라우저는 유저에게 페이지를 렌더링하여 보여줍니다.

이제, 여러분들에게 아키텍처의 각 구성요소를 안내 해드릴게요. 초심자를 위한 설명으로 웹 아키텍처에 대한 이해를 넓힐 수 있도록 mental model을 제공하겠습니다. Storyblocks에 있는 동안 제가 공부한 바를 바탕으로, 특정한 구현방식이 담긴 글들로 팔로업 해드릴 예정입니다.

  1. DNS

    DNS는 "Domain Name System"을 말합니다. World Wide Web(www)이 가능하게 하는 기반 기술이죠. 제일 기본으로 DNS는 IP 주소(e.g. 12.237.48.129)과 도메인 네임(e.g. google.com)의 매핑관계에서 키/값 조회를 제공합니다. 이 덕분에 당신의 브라우저가 올바른 서버로 요청을 라우팅할 수 있는 것이죠. 휴대전화번호 처럼, 도메인 네임과 IP 주소는 "홍길동"과 "02-123-3456"의 관계입니다. 홍길동의 전화번호를 연락처에서 찾아야 했던 것처럼, 도메인을 찾으려면 IP주소를 찾으려면 DNS가 필요합니다.

    더 다룰 수 있는 자세한 내용이 많지만, 초심자 대상인 지금 수준에서는 핵심이 아니기 때문에 넘어가겠습니다.

  2. 로드 밸런서 Load Balancer

    load balancing에 대해 말하기 전에, 잠깐 물러나서 horizontal scaling수평적 확장과 vertical scaling수직적 확장를 알아보죠. 그게 무엇이고, 차이는 뭘까요? 이 stackoverflow 글에 간단히 다뤄진 것처럼, 수평적 확장은 리소스 풀에 - 갖춰놓은 서버 네트워크 등 - 장비를 증설해서 확장하는 것을 말합니다. 반면, 수직적 확장은 지금 있는 장비에 스펙(e.g. CPU, RAM)을 업그레이드하는 것을 말합니다.

웹 개발에서는 거의 언제나 수평적 확장을 선호할 겁니다. 일단 쉽게 말해서, 서버가 터지니까요. 그것도 랜덤으로 터집니다. 네트워크 성능도 저하되죠. 전체 데이터 센터가 가끔 오프라인이 되기도 하죠. 중단없는 서비스를 위해서 하나 이상의 서버를 운영해야합니다. 다시 말해, 웹앱을 'fault tolerant'(내결함성: 결함에 내성있는) 하게 해야죠. 둘째로, 수평적 확장을 이용하면 - 서버를 증설하면 - 웹앱을 위한 백엔드 서비스들의 각 부분이 각각의 서버에서 최소한으로 연결시킬 수 있습니다. (웹 서버나, 데이터베이스, 00 서비스 등) 마지막으로, 더이상 수직적으로 scale할 수 없는 수준까지 증설할겁니다. 당신의 어플리케이션의 연산을 모두 수행할 만큼 거대한 컴퓨터는 없습니다. 훨씬 작은 규모의 회사에 적용되는 이야기지만 Google의 검색 플랫폼을 전형적인 예라고 할 수 있죠. 예를 들어 Storyblocks는 어떤 순간에는 150 ~ 400 개의 AWS EC2 인스턴스를 실행합니다. 수직 확장을 통해 전체 컴퓨팅 성능을 제공하는 것은 어려울 것입니다.

좋아요, 이제 load balancer로 돌아갑시다. Load balancer는 수평적 확장을 위한 기술입니다. load balancer는 들어오는 요청을 어플리케이션 서버들에게 각각 나눠 준 다음 돌려받은 응답을 클라이언트에게 전송합니다. 어플리케이션 서버들은 보통 서로의 동일한 이미지입니다. 각각의 서버 모두가 동일하게 요청을 처리해야만 서버 세트에 요청을 분산하여 과부하가 발생하지 않게 됩니다.

이제 됐습니다. 개념적으로 load balancer는 충분히 명료하죠. 내부적으로는 - under the hood - 분명 복잡하지만 역시 초심자 대상에서는 불필요하게 파보지는 말도록 하죠.

  1. 웹 어플리케이션 서버 Web Application Servers

    수준 높은 웹 어플리케이션 서버는 상대적으로 설명하기 간단합니다. 이 서버는 유저(의 브라우저)로 부터 요청을 받아 유저의 브라우저로 HTML 문서를 보내는 핵심 비즈니스 모델을 수행합니다. 그 일을 하기 위해 보통 수많은 백엔드 인프라와 통신합니다. DB, cacheing layer, job queue, search service, 또 다른 micro service들, data/logging queue 등등 이 있죠. 위에서 말한대로, 최소한 2개, 대부분 더 많은 인프라를 load balancer에 연결해서 요청을 처리합니다.

    웹 앱 서버를 구현하는 데에는 특정 언어, 그리고 그에 맞는 웹 프레임워크가 필요합니다. Node.js에는 Express, Ruby에는 Ruby on Rails, Scala에는 Play, PHP에는 Laravel, 등등 이죠.

  1. Database Servers

    모든 모던 웹 어플리케이션은 데이터 저장을 위해 하나 이상의 DB를 사용합니다. 데이터베이스는 데이터 구조를 정의하고, 새 데이터를 추가하고, 존재하는 데이터를 찾고, 업데이트/삭제하고, 데이터들로 연산하는 등을 위한 방법을 제공합니다. 대부분 웹 앱 서버나 job server나 DB서버와 직접 통신하죠.

    각 백엔드 서비스는 대체로 다른 앱들과는 연결되지 않은 자신만의 DB를 갖고 있습니다.

    각각의 아키텍처 구성요소에 대해 깊이 파고들지 않으려고 했지만, SQL과 NoSQL에 대해서는 설명드려야 겠습니다.

    SQL은 "Structured Query Language"로 1970년대에 발명되었습니다. 대중적으로 접근할 수 있는 관계형 데이터 셋에 쿼리를 날리는 표준 방식으로 제안된 것이죠. SQL은 테이블로 데이터를 저장하는 데, 테이블들은 각각 보통 정수 형태인 ID로 서로 연결되어 있습니다. 사용자의 주소 정보를 저장하는 간단한 예시를 보죠. users 테이블과 user_address 테이블 2개의 테이블이 있고, user의 id로 서로 연결되어 있습니다. 아래 간단한 수준으로 그린 이미지가 있습니다. user_address 테이블에 user_id 컬럼은 FK(foreign key)로, users 테이블의 id 컬럼과 연결되어 있으니 두 테이블은 연결된 것입니다.

    테이블 연결

    SQL을 잘 모른다면, 꼭 튜토리얼을 해보길 권해드립니다. 웹 개발에서는 어디서나 쓰이고, 하나의 어플리케이션을 설계할 때 기본이 되니까, 알고 있어야 합니다.

    NoSQL은 대규모 웹 어플리케이션이 만들어 낼 만한 거대한 양의 데이터를 처리하기 위해 떠오른 데이터베이스 기술들을 말합니다. - 대부분의 SQL에서 나온 DB들은 수평적 확장이 어렵고, 어떤 떄는 수직적 확장만 가능합니다. NoSQL을 전혀 모른다면, 수준 높은 소개자료로 시작하길 권해드립니다.

또한 업계는 전반적으로 NoSQL 데이터베이스의 경우에도 인터페이스로 SQL을 조정하고 있으므로 SQL을 모르는 경우 꼭 배워야합니다. 요즘에는 피할 방법이 거의 없습니다.

  1. Caching Service

    캐싱 서비스는 간단한 key/value 저장소를 제공합니다. 덕분에 O(1) 에 가까운 시간복잡도로 정보를 저장하고 조회할 수 있죠. 어플리케이션들은 캐싱 서비스를 활용하여 무거운 연산의 결과를 저장합니다. 필요할 때 다시 연산하는 대신 캐시로 부터 데이터를 불러오는 것이죠. 어플리케이션은 DB에 날린 쿼리의 결과, 외부 서비스 호출 결과, 특정 uri에 대응하는 html문서 등등을 캐싱합니다. real world의 예시를 들어보죠.

  • 구글은 "고양이", "비틀즈" 같은 일반적인 검색어에 대한 검색결과를 캐싱합니다.

  • 페이스북은 당신이 로그인했을 때 보게되는 대부분의 데이터를 캐싱합니다. 게시글, 친구목록 등등이죠. 관련된 더 자세한 설명을 여기서 볼 수 있습니다.

  • 스토리북은 서버사이드 리액트 렌더링의 HTML결과를 캐시합니다. 검색 결과, 자동완성 결과 등등 이죠.

    가장 많이 사용되는 캐싱 서버 기술은 Redis와 Memcache입니다. 다른 포스팅에서 다뤄보죠.

  1. Job Queue & Job Servers

  2. Full-text Search Service

  3. Services

  4. Data

  5. Cloud storage

  6. CDN

나가며..

Web Architecture 101의 마무리입니다. 도움이 되길 바래요. 내년이나 내후년는 소개드린 아키텍쳐의 구성요소들 중 몇 개에 대해 deep dive할 수 있는 글을 연재할 수 있기 바랍니다.

Web Architecture 기본 개념 - 웹 개발을 시작할 때 알았다면 좋았을 것들

Jonathan Fulton 님의 글 을 의역했습니다.

web architecture diagram

이 다이어그램은 Storyblocks의 서비스 아키텍쳐를 제법 잘 표현한 그림입니다. 경험 많은 웹개발자가 아니시라면, 꽤 복잡해보이실 수 있어요. 각 컴포넌트를 자세히 알아보기 전에, 아래 내용을 보면 좀 더 접근하기 편할 겁니다.

구글에 “Strong Beautiful Fog And Sunbeams In The Forest” 를 입력하면, 첫번째 검색결과로 Storyblocks이 나옵니다. *stock 이미지와 벡터 이미지 사이트입니다.

사용자가 검색 결과를 클릭하면 유저의 브라우저가 Storyblocks의 이미지 상세페이지로 리디렉션합니다. 내부적으로, 유저의 브라우저는 DNS 서버에 Storyblocks의 주소를 조회하는 요청을 하고, 그 결과를 가지고 요청합니다.

요청은 Storyblocks의 Load Balancer에 도달하고, 요청을 처리 중에 우리가 서비스 중인 10개 이상의 웹 앱 서버 중 하나를 랜덤으로 결정합니다. 웹 앱 서버캐싱 서비스에서 이미지에 대한 정보를 조회하고 데이터베이스에서 남아있는 데이터를 가져옵니다. 우리는 이미지를 위한 color profile이 처리되지 않았다는 걸 알아차리고, Job Queue에 "color profile" job을 보냅니다. Job Queue는 우리가 명령한 job들을 비동기로 처리하고 결과를 적절히 데이터베이스에 업데이트합니다.

그런 다음, 우리는 input으로서 사진의 제목을 가지고 full text search service에 요청을 보내서 유사한 사진을 찾는 시도를 합니다. 사용자가 Storyblocks 회원으로 로그인 된 상태라면, 그 사람의 계정 정보를 우리의 계정 서비스에서 가져옵니다. 마지막으로, data firehose에 페이지뷰 이벤트를 보내서 우리의 cloud storage system에 저장되고, 결국 Data warehouse에 로드되도록 합니다. 데이터 분석가들은 이를 바탕으로 비즈니스 문제를 연구할 수 있죠.

이제 웹 앱 서버는 HTML문서를 렌더링하고 로드밸런서를 통해 유저의 브라우저에 돌려보냅니다. 우리가 CDN으로 연결해둔 cloud storage system을 통해 로드된 Javascript와 CSS asset이 페이지에 포함되고, 결국 유저의 브라우저는 CDN와 통신하여 컨텐츠를 읽어옵니다.

끝으로, 유저의 브라우저는 유저에게 페이지를 렌더링하여 보여줍니다.

이제, 여러분들에게 아키텍처의 각 구성요소를 안내 해드릴게요. 초심자를 위한 설명으로 웹 아키텍처에 대한 이해를 넓힐 수 있도록 mental model을 제공하겠습니다. Storyblocks에 있는 동안 제가 공부한 바를 바탕으로, 특정한 구현방식이 담긴 글들로 팔로업 해드릴 예정입니다.

  1. DNS

    DNS는 "Domain Name System"을 말합니다. World Wide Web(www)이 가능하게 하는 기반 기술이죠. 제일 기본으로 DNS는 IP 주소(e.g. 12.237.48.129)과 도메인 네임(e.g. google.com)의 매핑관계에서 키/값 조회를 제공합니다. 이 덕분에 당신의 브라우저가 올바른 서버로 요청을 라우팅할 수 있는 것이죠. 휴대전화번호 처럼, 도메인 네임과 IP 주소는 "홍길동"과 "02-123-3456"의 관계입니다. 홍길동의 전화번호를 연락처에서 찾아야 했던 것처럼, 도메인을 찾으려면 IP주소를 찾으려면 DNS가 필요합니다.

    더 다룰 수 있는 자세한 내용이 많지만, 초심자 대상인 지금 수준에서는 핵심이 아니기 때문에 넘어가겠습니다.

  2. 로드 밸런서 Load Balancer

    load balancing에 대해 말하기 전에, 잠깐 물러나서 horizontal scaling수평적 확장과 vertical scaling수직적 확장를 알아보죠. 그게 무엇이고, 차이는 뭘까요? 이 stackoverflow 글에 간단히 다뤄진 것처럼, 수평적 확장은 리소스 풀에 - 갖춰놓은 서버 네트워크 등 - 장비를 증설해서 확장하는 것을 말합니다. 반면, 수직적 확장은 지금 있는 장비에 스펙(e.g. CPU, RAM)을 업그레이드하는 것을 말합니다.

웹 개발에서는 거의 언제나 수평적 확장을 선호할 겁니다. 일단 쉽게 말해서, 서버가 터지니까요. 그것도 랜덤으로 터집니다. 네트워크 성능도 저하되죠. 전체 데이터 센터가 가끔 오프라인이 되기도 하죠. 중단없는 서비스를 위해서 하나 이상의 서버를 운영해야합니다. 다시 말해, 웹앱을 'fault tolerant'(내결함성: 결함에 내성있는) 하게 해야죠. 둘째로, 수평적 확장을 이용하면 - 서버를 증설하면 - 웹앱을 위한 백엔드 서비스들의 각 부분이 각각의 서버에서 최소한으로 연결시킬 수 있습니다. (웹 서버나, 데이터베이스, 00 서비스 등) 마지막으로, 더이상 수직적으로 scale할 수 없는 수준까지 증설할겁니다. 당신의 어플리케이션의 연산을 모두 수행할 만큼 거대한 컴퓨터는 없습니다. 훨씬 작은 규모의 회사에 적용되는 이야기지만 Google의 검색 플랫폼을 전형적인 예라고 할 수 있죠. 예를 들어 Storyblocks는 어떤 순간에는 150 ~ 400 개의 AWS EC2 인스턴스를 실행합니다. 수직 확장을 통해 전체 컴퓨팅 성능을 제공하는 것은 어려울 것입니다.

좋아요, 이제 load balancer로 돌아갑시다. Load balancer는 수평적 확장을 위한 기술입니다. load balancer는 들어오는 요청을 어플리케이션 서버들에게 각각 나눠 준 다음 돌려받은 응답을 클라이언트에게 전송합니다. 어플리케이션 서버들은 보통 서로의 동일한 이미지입니다. 각각의 서버 모두가 동일하게 요청을 처리해야만 서버 세트에 요청을 분산하여 과부하가 발생하지 않게 됩니다.

이제 됐습니다. 개념적으로 load balancer는 충분히 명료하죠. 내부적으로는 - under the hood - 분명 복잡하지만 역시 초심자 대상에서는 불필요하게 파보지는 말도록 하죠.

  1. 웹 어플리케이션 서버 Web Application Servers

    수준 높은 웹 어플리케이션 서버는 상대적으로 설명하기 간단합니다. 이 서버는 유저(의 브라우저)로 부터 요청을 받아 유저의 브라우저로 HTML 문서를 보내는 핵심 비즈니스 모델을 수행합니다. 그 일을 하기 위해 보통 수많은 백엔드 인프라와 통신합니다. DB, cacheing layer, job queue, search service, 또 다른 micro service들, data/logging queue 등등 이 있죠. 위에서 말한대로, 최소한 2개, 대부분 더 많은 인프라를 load balancer에 연결해서 요청을 처리합니다.

    웹 앱 서버를 구현하는 데에는 특정 언어, 그리고 그에 맞는 웹 프레임워크가 필요합니다. Node.js에는 Express, Ruby에는 Ruby on Rails, Scala에는 Play, PHP에는 Laravel, 등등 이죠.

  1. Database Servers

    모든 모던 웹 어플리케이션은 데이터 저장을 위해 하나 이상의 DB를 사용합니다. 데이터베이스는 데이터 구조를 정의하고, 새 데이터를 추가하고, 존재하는 데이터를 찾고, 업데이트/삭제하고, 데이터들로 연산하는 등을 위한 방법을 제공합니다. 대부분 웹 앱 서버나 job server나 DB서버와 직접 통신하죠.

    각 백엔드 서비스는 대체로 다른 앱들과는 연결되지 않은 자신만의 DB를 갖고 있습니다.

    각각의 아키텍처 구성요소에 대해 깊이 파고들지 않으려고 했지만, SQL과 NoSQL에 대해서는 설명드려야 겠습니다.

    SQL은 "Structured Query Language"로 1970년대에 발명되었습니다. 대중적으로 접근할 수 있는 관계형 데이터 셋에 쿼리를 날리는 표준 방식으로 제안된 것이죠. SQL은 테이블로 데이터를 저장하는 데, 테이블들은 각각 보통 정수 형태인 ID로 서로 연결되어 있습니다. 사용자의 주소 정보를 저장하는 간단한 예시를 보죠. users 테이블과 user_address 테이블 2개의 테이블이 있고, user의 id로 서로 연결되어 있습니다. 아래 간단한 수준으로 그린 이미지가 있습니다. user_address 테이블에 user_id 컬럼은 FK(foreign key)로, users 테이블의 id 컬럼과 연결되어 있으니 두 테이블은 연결된 것입니다.

    테이블 연결

    SQL을 잘 모른다면, 꼭 튜토리얼을 해보길 권해드립니다. 웹 개발에서는 어디서나 쓰이고, 하나의 어플리케이션을 설계할 때 기본이 되니까, 알고 있어야 합니다.

    NoSQL은 대규모 웹 어플리케이션이 만들어 낼 만한 거대한 양의 데이터를 처리하기 위해 떠오른 데이터베이스 기술들을 말합니다. - 대부분의 SQL에서 나온 DB들은 수평적 확장이 어렵고, 어떤 떄는 수직적 확장만 가능합니다. NoSQL을 전혀 모른다면, 수준 높은 소개자료로 시작하길 권해드립니다.

또한 업계는 전반적으로 NoSQL 데이터베이스의 경우에도 인터페이스로 SQL을 조정하고 있으므로 SQL을 모르는 경우 꼭 배워야합니다. 요즘에는 피할 방법이 거의 없습니다.

  1. Caching Service

    캐싱 서비스는 간단한 key/value 저장소를 제공합니다. 덕분에 O(1) 에 가까운 시간복잡도로 정보를 저장하고 조회할 수 있죠. 어플리케이션들은 캐싱 서비스를 활용하여 무거운 연산의 결과를 저장합니다. 필요할 때 다시 연산하는 대신 캐시로 부터 데이터를 불러오는 것이죠. 어플리케이션은 DB에 날린 쿼리의 결과, 외부 서비스 호출 결과, 특정 uri에 대응하는 html문서 등등을 캐싱합니다. real world의 예시를 들어보죠.

  • 구글은 "고양이", "비틀즈" 같은 일반적인 검색어에 대한 검색결과를 캐싱합니다.

  • 페이스북은 당신이 로그인했을 때 보게되는 대부분의 데이터를 캐싱합니다. 게시글, 친구목록 등등이죠. 관련된 더 자세한 설명을 여기서 볼 수 있습니다.

  • 스토리북은 서버사이드 리액트 렌더링의 HTML결과를 캐시합니다. 검색 결과, 자동완성 결과 등등 이죠.

    가장 많이 사용되는 캐싱 서버 기술은 Redis와 Memcache입니다. 다른 포스팅에서 다뤄보죠.

  1. Job Queue & Job Servers

  2. Full-text Search Service

  3. Services

  4. Data

  5. Cloud storage

  6. CDN

나가며..

Web Architecture 101의 마무리입니다. 도움이 되길 바래요. 내년이나 내후년는 소개드린 아키텍쳐의 구성요소들 중 몇 개에 대해 deep dive할 수 있는 글을 연재할 수 있기 바랍니다.