Tuesday, 20 November 2018

[번역] 웹 아키텍처 101

웹 아키텍처 101


웹 개발자로서 시작했을 때 알았으면 좋았을 기본 아키텍처

최신 웹 애플리케이션 아키텍처 개요

위 다이어그램은 스토리블록(Storyblocks)의 아키텍처를 꽤 잘 나타낸 것 입니다. 숙련된 웹 개발자가 아닐지라도 꽤 복잡해보인다는 것을 알 수 있을 것 입니다. 각각의 구성 요소들의 자세한 정보들을 알아보기 전에 아래의 짧은 글은 아키텍처를 좀 더 이해하기 쉽게 도와줄 것 입니다.

한 사용자는 구글에 "Strong Beautiful Fog And Sunbeams In The Forest"를 검색한다. 첫번째 결과는 스토리블록에서 나온다. 사용자 브라우저가 이미지 상세 페이지로 리다이렉트하는 결과를 클릭한다. 그 아래에서는 사용자의 브라우저DNS에 스토리블록에 어떻게 접근할 수 있는지 검색하고 스토리블록에 요청을 한다.

그 요청은 그 요청을 처리하기 위해서 동시에 운영하는 10개 정도의 웹 서버들 중 하나를 랜덤으로 선택하는 로드 밸런서에 이른다. 이제 웹 서버는 이미지에 대한 정보를 캐싱 서비스에서 찾아보고 나머지 데이터는 데이터베이스에서 가져온다. 우리는 이미지에 대한 색상 프로필 정보가 아직 계산되지 않은 것을 알아 차리고 "color profile" 작업작업 큐에 넣는다. 작업 서버들이 이제 이 작업들을 결과를 적절히 데이터베이스에 업데이트하면서 비동기적으로 처리한다.

다음으로, 풀 텍스트 서치 서비스에 사진의 제목을 입력으로 요청하면서 비슷한 사진들을 찾기를 시도한다. 사용자가 스토리블록에 멤버로 로그인하면 계정 서비스에 사용자의 정보를 검색한다. 마지막으로, 클라우드 스토리지 시스템에 기록될 페이지 뷰 이벤트를 데이터 파이어호스에 보낸다. 결국 데이터 웨어하우스에 저장되어 분석가가 비즈니스에 대한 질문에 대답하는데 사용한다.

서버는 HTML로 뷰를 렌더링하고 로드 밸런서를 통해 먼저 전달되는 사용자의 브라우저에 돌려 보낸다. 그 페이지는 CDN에 연결된 우리의 클라우드 스토리지 시스템에 있는 javascript와 css를 포함하고 있다. 그래서 사용자의 브라우저CDN을 통해 그 내용물을 획득한다. 마지막으로, 브라우저는 사용자가 볼 수 있게 페이지를 렌더링한다.

다음으로는 각 구성 요소를 살펴보면서 "101"의 각 구성 요소를 소개하고자 합니다. 각 구성 요소에 대한 소개는 앞으로 웹 아키텍처를 통해 생각할 수 있는 훌륭한 멘탈 모델을 줄 것 입니다. 추후에 스토리블록에서 배운 내용을 바탕으로 구체적인 구현 권장 사항을 제시하는 또 다른 글을 다룰 것 입니다.

1. 도메인 네임 시스템 DNS

DNS는 Domain Name System의 약어이고 월드 와이드 웹을 가능하게 만드는 뼈대 기술입니다. 가장 기본적인 단계의 DNS는 도메인 이름(예. google.com)으로 IP 주소(예. 85.129.83.120)를 얻을 수 있는 키/값 검색 기능을 제공합니다. 그리고 이러한 과정은 당신의 컴퓨터가 적절한 서버로 요청을 보내기 위해 꼭 필요합니다. 전화번호에 빗대어 보면, domain name과 IP 주소의 차이는 "John Doe에게 전화 걸기"와 "201-867-5309에 전화 걸기"의 차이와 같습니다. 옛날에 John에게 전화걸기 위해서 주소록을 뒤져보았던 것 처럼 domain name으로 IP 주소를 찾기 위해 DNS가 필요합니다. DNS를 인터넷을 위한 주소록으로 생각해도 되겠습니다.

더 자세히 다룰 주제가 있지만 101-레벨 인트로에서는 중요하지 않으니 생략하겠습니다.

2. 로드 밸런서 Load Balancer

로드 밸런싱에 대한 상세한 정보에 뛰어들기 전에, 수평적 애플리케이션 확장 vs 수직적 애플리케이션 확장에 대해 알 필요가 있습니다. 이것들이 무엇이고 무엇이 다를까요? 이 StackOverFlow 글에서는 아주 간단하게 이렇게 말했습니다. "수평적" 애플리케이션 확장은 기계를 더 추가하는 것으로 확장하는 것을 말하고 "수직적" 애플리케이션은 있는 기계에 CPU나 RAM 같은 것을 업그레이드하는 것으로 확장하는 것 의미합니다.

웹 개발에서는 대부분 간단함을 유지하기 위해서 수평적으로 확장하길 원합니다. 서버는 랜덤으로 망가질 수 있습니다. 네트워크가 안 좋을 수도 있고 전체 데이터 센터가 오프라인 상태가 될 수도 있습니다. 서버를 하나 이상 갖는다는 것은 애플리케이션이 계속 돌아가는 것을 가능케 합니다. 다르게 말하면 애플리케이션이 "고장에 내성이 있다"라고 할 수 있습니다. 두번째로, 수평적 애플리케이션 확장은 백엔드 애플리케이션의 구성 요소인 웹 서버, 데이터베이스, 서비스 같은 것 들이 각각 다른 서버에서 동작하게 해서 최소량으로 결합하는 것을 가능케합니다. 마지막으로, 수직적으로 확장으로 불가능한 정도를 수평적으로는 확장할 수 있습니다. 세상에는 모든 계산을 다 처리할만한 큰 컴퓨터는 없습니다. Google의 검색 플랫폼은 비록 훨씬 작은 규모의 회사들에게 적용되지만 전형적인 예라고 할 수 있습니다. 예를 들어, 스토리블록은 특정 시점에 150~450개의 AWS EC2 인스턴스를 실행합니다. 수직적 확장을 통해 전체 컴퓨팅 성능을 제공하기는 어렵습니다.

이제 로드 밸런서로 돌아갑시다. 로드 밸런서가 바로 수평적 확장을 가능하게 하는 마법의 소스입니다. 로드 밸런서는 들어오는 요청들을 수 많은 복제된 애플리케이션 서버들 중 하나로 보내고 애플리케이션 서버의 응답을 클라이언트로 다시 보냅니다. 모든 서버들이 동일한 방식으로 요청을 처리해야 합니다. 그래서 서버들 중 어느 하나에 몰리지 않게 요청들을 분배하는 것이 문제입니다.

바로 그겁니다. 개념적으로는 로드 밸런서는 상당히 간단합니다. 그 아래에는 분명 복잡한 것이 있지만 101 버전에서는 알 필요가 없습니다.

3. 웹 애플리케이션 서버 Web Application Servers

고수준의 웹 애플리케이션 서버는 상대적으로 설명하기 쉽습니다. 사용자의 요청을 다루고 핵심 비즈니스 로직을 수행하여 사용자의 브라우저에 HTML을 돌려 보냅니다. 이런 작업을 하기 위해서는 데이터베이스, 캐싱 레이어, 작업 큐, 서칭 서비스, 다른 마이크로서비스, 데이터/로깅 큐 와 같은 백엔드 인프라와 통신해야 합니다. 위에서 언급했듯이, 웹 애플리케이션 서버는 적어도 2개나 그보다 많게 사용자의 처리를 처리하기 위해 로드 밸런서에 연결되어 있습니다.

앱 서버를 만들기 위해서는 언어(Node.js, Ruby, PHP, Scala, Java, C#, .NET 등), 웹 MVC 프레임워크(Express, Ruby on Rails, Play for Scala, Laravel for PHP 등)를 선택해야 합니다. 이러한 언어들과 프레임워크를 상세하게 다루는 것은 이 글의 범위를 벗어납니다.

4. 데이터베이스 서버 Database Servers

모든 최신 웹 애플리케이션은 정보를 저장하기 위해 1개 혹은 그 이상의 데이터베이스를 사용합니다. 데이터베이스는 데이터 구조를 정의하고 데이터를 저장하고 검색하고 업데이트하고 삭제하는 등의 방법을 제공합니다. 대부분의 웹 애플리케이션 서버는 하나의 데이터베이스와 직접 통신합니다. 그리고 작업 서버 또한 그렇습니다. 추가적으로 각각 백엔드 서비스는 다른 애플리케이션으로부터 고립된 자신만의 데이터베이스를 가집니다.

특정한 기술에 깊게 빠져드는 것을 피하고 있지만 SQL과 NoSQL에 대해 다루지 않을 수가 없습니다.

SQL은 "Structured Query Language"의 약어이고 많은 사람들이 접근 가능한 관계 데이터 셋을 질의하기 위한 보편적인 방법을 제공하기 위해서 1970년대에 발명되었습니다. SQL 데이터베이스는 보통 정수형 값인 ID로 연결된 테이블에 데이터를 저장합니다. 사용자 주소 정보를 저장하는 예를 살펴보겠습니다. 사용자의 ID로 연결된 users와 user_addresses 2개의 테이블이 있습니다. 아래의 간단한 버전의 이미지를 보세요. user_addresses 테이블에 있는 user_id는 user 테이블에 id의 "외래 키"입니다.


SQL에 대해서 잘 모른다면 Khan Academy 여기에서 튜토리얼을 해볼 것을 추천합니다. 웹 개발에서는 아주 흔하기 때문에 애플리케이션을 잘 설계하기 위해서 기본을 알길 원할 것입니다.

NoSQL은 "Non-SQL"의 약어인데 아주 큰 웹 애플리케이션에서 생산되는 많은 양의 데이터들을 다루기 위해 생겨난 새로운 데이터베이스 기술입니다. 대부분의 SQL은 수평적으로 확장할 수 없어서 어떤 시점에서는 수직적으로만 확장할 수 있습니다. NoSQL에 대해서 잘 모른다면, 아래의 소개글을 읽어보길 권합니다.
그리고 명심해야할 것이 있는데 대체로 업계에서 NoSQL 데이터베이스에 대한 인터페이스로 SQL을 사용하고 있으므로 SQL을 모를 경우 배워야 합니다. 요즘은 피할 방법이 거의 없습니다.

5. 캐싱 서비스 Caching Service

캐싱 서비스는 O(1) 시간에 데이터를 저장하고 조회할 수 있는 간단한 키/값 데이터 저장소를 제공합니다. 캐시에서 비싼 비용이 드는 결과를 저장해 두어서 다음에 필요할 때 데이터를 재계산하는 대신에 캐시에서 결과값을 얻는 식으로 캐싱 서비스를 활용합니다. 애플리케이션은 데이터베이스 쿼리, 외부 서비스호출, url로 주어진 html 등 다양한 정보를 캐시에 저장합니다. 실세계의 예를 살펴봅시다.
  • 구글은 "dog", "Taylor Swift"와 같은 쿼리에 대한 결과를 매번 계산하기보다 캐시에 저장합니다.
  • 페이스북은 당신이 보는 많은 데이터들(포스트, 친구들 등)을 캐시에 저장해둡니다. 페이스북의 캐싱 기술에 대한 자세한 것은 이 글을 읽어보세요.
  • 스토리블록은 React server-side rendering의 HTML 결과물, 검색 결과, typeahead 결과 등을 캐시에 저장합니다.
2가지 가장 널리 알려진 캐싱 서버기술은 레디스멤캐시드입니다. 이것들은 다른 글에서 자세히 다루겠습니다.

6. 작업 큐 & 서버 Job Queue & Servers

대부분의 웹 애플리케이션은 사용자의 요청과 직접적으로 관련된 것이 아니어서 비동기적으로 뒤에서 처리해야할 것이 필요합니다. 예를 들어, 구글은 검색 결과를 제공하기 위해서 인터넷 전체를 크롤링하고 인덱싱해야 합니다. 이러한 과정은 검색할 때 마다 하진 않습니다. 대신에, 비동기적으로 웹을 크롤링하고 검색 인덱싱을 업데이트 합니다.

비동기적으로 작업을 가능하게 하는데 많은 아키텍처들이 있지만 가장 흔히 쓰이는 것은 "작업 큐" 아키텍처입니다. 2가지로 구성되어 있는데 실행되어야 할 "작업"들의 큐와 이 큐안에 있는 작업들을 실행하는 한개 이상의 작업 서버들입니다. 작업 서버는 workers라고도 합니다.

작업 큐는 비동기적으로 실행해야할 작업들을 저장합니다. 대부분의 애플리케이션은 우선순위를 가진 큐 시스템을 필요로 하지만 가장 간단한 것은 first-in-first-out (FIFO) 큐입니다. 앱이 실행되어야할 작업이 필요할때 마다(정기적인 스케쥴이던 사용자의 액션으로 결정된 것이던) 큐에 적절한 작업을 추가합니다.

예를 들어, 스토리블록은 마켓 플레이스를 지지하는데 필요한 많은 양의 뒷 작업에 작업 큐를 활용합니다. 영상과 사진을 인코딩하고 CSV 파일을 메타데이터 태깅을 위해 처리하고 유저 통계를 모으고 비밀번호 초기화 메일을 보내는 등에 쓰입니다. 처음에는 간단한 FIFO 큐로 시작했지만 나중에는 비밀번호 초기화 메일을 보내는 것과 같이 빠르면 빠를수록 좋은 시간에 민감한 작업들을 보장하기 위해 우선순위 큐로 업그레이드 했습니다.

작업 서버는 작업들을 처리합니다. 작업 큐를 폴링하여 할 작업이 있는지 만약 있다면 큐에서 작업을 꺼내어 실행합니다. 웹 서버에 대해 말하자면 기반하는 언어나 프레임워크의 선택은 너무나 많아서 이 글에서는 다루지 않겠습니다.

7. 풀 텍스트 서치 서비스 Full-text Search Service

대부분의 웹 앱들은 사용자들이 "쿼리"라고 불리는 텍스트를 입력하면 앱이 "관련된" 결과를 반환하는 검색 기능을 지원합니다. 이러한 기능을 제공하는 기술은 일반적으로 "풀 텍스트 서치(full-text search)"라고 합니다. 이 기술은 반전된 색인(Inverted Index)을 활용하여 쿼리 키워드가 포함된 문서를 빠르게 검색합니다. 
예시 : 3개의 문서 제목이 제목에 있는 키워드로 특정한 키워드가 있는 문서를 빠르게 검색하기 위해 반전된 색인으로 변환된 것 입니다. 주목할 것은 "in", "the", "with" 와 같은 정지 단어라고 불리는 단어들은 일반적으로 반전된 색인에 포함되지 않습니다.
풀 텍스트 서치는 데이터베이스로부터 직접 사용가능하기도 하지만(MySQL은 지원합니다), 반전된 색인을 계산하고 저장하며 쿼리 인터페이스를 제공하는 "서치 서비스"를 분리해서 운영하는게 일반적입니다. 최근 가장 유명한 풀 텍스트 서치 플랫폼은 엘라스틱 서치입니다. 다른 선택지로는 스핑크스아파치 솔라가 있습니다.

8. 서비스 Services

앱이 특정 규모에 도달하면 별도의 애플리케이션으로 실행되도록 분할된 특정 "서비스"가 있을 수 있습니다. 그들은 외부 세계에 노출되지 않지만 앱과 다른 서비스들은 그들과 상호작용합니다. 예를 들어, 스토리 블록에는 몇 가지 운영 중이거나 계획된 서비스들이 있습니다.
  • 계정 서비스는 더 통일된 사용자 경험을 만들고 교차 판매의 기회를 쉽게 제공하기 위해서 우리의 모든 사이트에 걸친 사용자 데이터를 저장합니다.
  • 컨텐츠 서비스는 비디오, 오디오, 이미지 컨텐츠에 대한 메타 데이터를 저장합니다. 그리고 컨텐츠를 다운로드 받거나 다운로드 기록을 보여주는 인터페이스도 제공합니다.
  • 지불 서비스는 고객에게 비용을 지불하는 인터페이스를 제공합니다
  • HTML → PDF 서비스는 HTML을 받아서 PDF로 변환하는 간단한 인터페이스를 제공합니다.

9. 데이터 Data

오늘날 데이터를 얼마나 잘 이용하느냐에 따라 회사는 살거나 죽습니다. 대부분의 요즘 앱들은 특정 크기에 이르면 데이터를 모으고 저장하고 분석할 수 있는 데이터 파이프라인을 활용합니다. 일반적인 파이프라인은 3가지 단계를 가집니다.
  1. 앱이 파이어호스로 데이터(일반적으로 사용자 상호작용에 대한 이벤트)를 보냅니다. 파이어 호스는 데이터를 제공 받고 처리하는 스트리밍 인터페이스를 제공합니다. 종종 미가공 데이터가 변형되거나 증가되고 다른 파이어 호스로 전달됩니다. AWS 키네시스카프카는 이러한 목적에 가장 흔한 기술입니다.
  2. 미가공 데이터와 최종 변형/증가된 데이터들이 클라우드 스토리지에 저장됩니다. AWS 키네시스는 미가공 데이터를 클라우드 스토리지(S3)에 매우 쉽게 저장할 수 있도록 "파이어호스"라는 설정을 제공합니다.
  3. 변형/증가된 데이터들은 종종 분석을 위해 데이터 웨어하우스에 저장됩니다. 우리는 AWS 레드시프트를 사용하고 있고 스타트업 세계에서는 점점 커지고 있습니다. 반면 큰 기업들은 오라클이나 기타 독점적인 웨어하우스 기술을 사용합니다. 데이터셋이 충분히 크면 하둡과 유사한 NoSQL 맵리듀스 기술이 분석에 필요할 수도 있습니다.
아키텍처 다이어그램에 있지 않은 다른 단계가 하나 더 있습니다. 앱과 서비스의 운영 데이터베이스로부터 데이터를 불러와 데이터 웨어하우스에 저장하는 것입니다. 예를 들어 스토리 블록은 비디오블록, 오디오블록, 스토리블록, 계정 서비스, 기부자 포탈 데이터 베이스를  레드시프트에 매일 밤 불러옵니다. 유저 상호 작용 이벤트와 핵심 비즈니스 데이터를 함께 모아놓아서 전체적인 데이터셋을 분석가에게 제공합니다.

10. 클라우드 스토리지 Cloud storage

"클라우드 스토리지는 인터넷을 통해 데이터를 저장, 검색, 공유할 수 있는 간단하고 확장가능한 방법입니다."라고 AWS가 말하고 있습니다. HTTP를 이용한 RESTful API를 통해서 로컬 파일 시스템에 저장했어야할 것에 더 많이 혹은 덜 접근하거나 저장할 수 있습니다. 아마존의 S3 오퍼링은 오늘날까지 가장 널리 사용되는 클라우드 스토리지이며, 여기서는 비디오, 사진, 및 오디오 자산, CSS 및 Javascript, 사용자 데이터 등을 저장하는 데 광범위하게 사용하고 있습니다.

11. 컨텐츠 딜리버리 네트워크 CDN 

CDN은 "Content Delivery Network"를 의미하며, 이 기술은 웹 상에서 단일 원본 서버에서 제공하는 것보다 훨씬 빠르게 정적 HTML, CSS, Javascript 및 이미지와 같은 자산을 서비스하는 방법을 제공합니다. 이 기능은 전 세계 여러 "엣지" 서버에 컨텐츠를 배포하여 사용자가 원본 서버가 아닌 "엣지" 서버에서 자산을 다운로드하게 됩니다. 예를 들어 아래 이미지에서 스페인 사용자는 뉴욕에 원본 서버가 있는 사이트의 웹 페이지를 요청하지만 해당 페이지의 정적 자산은 영국의 CDN "엣지" 서버에서 로드되어 많은 느린 대서양을 건너는 HTTP 요청을 방지합니다.


더 자세한 내용은 이 글에서 확인해보길 바랍니다. 일반적으로 웹 앱은 항상 CDN을 이용하여 CSS, Javascript, 이미지, 비디오 및 기타 자산을 서비스해야 합니다. 일부 앱은 CDN을 활용하여 정적 HTML 페이지를 제공할 수도 있습니다.

마무리

이것이 웹 아키텍처 101 마무리입니다. 이 글이 유용하기를 바랍니다. 내년이나 2년 후에 여기에 나오는 구성 요소들을 다루는 201 시리즈를 포스팅하길 희망합니다.

이 글은 Web Architecture 101를 번역한 글입니다.

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home