소프트웨어 사색

웹개발 패러다임의 거대한 변화 "Reactive"

[하마] 이승현 (wowlsh93@gmail.com) 2017. 2. 15. 11:25


현재 작성된 이 포스트는 나중에 다양한 원인에 의해 수정될 수 있으며 ,100% 정확한 정보를 담고 있지 않을 가능성이 있다라는 것을 먼저 말씀드립니다.



" 막힘없이 흘러다니는 데이터(이벤트)를 통해 사용자에게 자연스러운 응답을 주고, 규모 탄력적으로 리소스를 사용하며 실패에 있어서 유연하게 대처한다" 


서론

현재 페이스북 및 각종 세미나들을 보면 딥러닝을 위시한 데이타분석 기술들이 점령하고있다. 물론 그러한 것들의 인기를 그닥 나쁘게 볼 필요는 없지만 다만 아쉬운점은 너무 편중되었다는 것이다.

특히 서버기술들은 모든 IT 서비스들의 허리를 이루는 중추인데 별로 관심을 못받는거 같아 아쉽다. 그래서 웹개발/서버 서비스 개발 방법론으로 떠오르는 Reactive 에 대해서 간단히 정리 하여 써보려한다. 먼저 고백하자면 나는 이 분야의 경험이 많은 수준높은 개발자는 아니다. 이 흐름에 먼저 올라타서 함께 가자고 독려하는 동료일뿐..

Reactive 기술의 아이디어는 1980년대에 논문("On the Development of Reactive System") 이 나왔고,1990년대, 2000년대초반에 이미 저수준은 제공되고 있어왔다. (Select, ePoll, IOCP등 네트워크 비동기화에서 부터 쓰레드의 추상층등) 그런것들을 토대로 자연스러운 데이터흐름을 다루는것에 대한 벽돌이 쌓아 올려져 RxJava, Node.js, Play(Akka Streaming), Microsoft Reactive Extensions 등이 생겨났다.

Rest API 를 통해 자신들의 데이터를 외부로 서비스 하는 회사(예: 트위터,사물인터넷,주식관련등)들이 많아 지면서 그러한 서비스들의 데이터 흐름을 이용 할 수 있는 장도 마련되었다.

아주 오래전에 만들어진 신경망 논문(기술)이 지금 쉽게 사용할 수 있는 툴 등의 등장으로 더욱 활발하게 활용,시도하는 것 처럼 Reactive 도 이제 본격적으로 대중화 되기 위한 만반의 준비를 갖추고 날아오를 준비를 하고 있다.

모델2

지금까지 웹개발은 한번 개발 파라다임이 변화했는데 그것은 객체지향 설계가 전폭적으로 반영된 MVC 패턴 기반의 방식이었다. 저레벨에 대한 변화라기 보다는 1. 유지보수하기 편한 공통화된 설계 방식 - 역할에 따른 분리 2. 객체지향의 정점을 고스라니 물려받음 등에 있다. 이 분야에 관련된 대표적인 저술인 PEAA (엔터프라이즈 어플리케이션 패턴-마틴파울러) 의 패턴들을 보면 그 색채가 아주 뚜렷히 나타난다.

참고로 PEAA에서 다루는 내용은 아래와 같다. 

◎ 엔터프라이즈 애플리케이션을 여러 계층으로 분할하는 방법
◎ 비즈니스 논리를 구성하는 여러 주요 방식
◎ 객체와 관계형 데이터베이스 간 매핑에 대한 심도 깊은 논의
◎ 모델 뷰 컨트롤러를 통한 웹 프레젠테이션 운영
◎ 여러 트랜잭션에 걸친 데이터의 동시성을 처리하는 방법
◎ 분산 객체 인터페이스 설계

물론 이러한 모델2가 모델1보다 무조건 좋은것은 아니다. 적절한 사용처가 따로 있을뿐. 이 논리는 그대로 Reactive 까지 이어질 것이다. 즉 모든것에 Reactive 를 적용할 필요는 없다는 말이다. (예를들어 나는 웬만한것들은 그냥 멀티쓰레드기반의 소켓통신을 사용한다. IOCP 를 직접사용하거나 boost asio 라든지 Java NIO2,  Python Twisted 같은 라이브러리등도 정말 그게 꼭 필요하다 싶을 때 아니면 손대지 않을 것 같다.)


Reactive 파라다임

한마디로 표현하면 "막힘없이 흘러다니는 데이터(이벤트)를 통해 사용자에게 자연스러운 응답을 주고, 규모 탄력적으로 리소스를 사용하며 실패에 있어서 유연하게 대처한다" 이다. "모든 지점에서 블럭 되지 않게 하자." 로 더 짧고 개발자 친화적으로 설명할 수도 있을 거 같다.

이렇게 먼가 중간 중간 끊어지는것이 아니다.

연속된 비동기의 흐름이 연속되게 이어지는 것이다.


Reactive 파라다임은 저레벨부터 시작한다. 일단 비동기적인 통신모델이 필요하다. 그 역할은 Netty 등이 하고 있으며 그 위에 데이터흐름을 처리하는 것에 대한 설계지침 및 도우미 기능 (Observerble, Future, await, Actor,Reactive Streaming등)이 얹어졌다.최종적으로그러한 것을 처리하는 풀스택개발환경인 Akka, Play,Node.js와 형제들이 나타났고..(Spring 도 최신버전에서 열심히 변화하려고 하고 있는 듯하다. 하지만 과거의 영광이 발목을 잡지 않을까..현재는 Play ,Akka 가 가장 잘 지원하고 있다라고 생각된다.)

즉 응용개발자들이 신경쓰지 않아도 될 만큼 저레벨 부분에 대한 수준높은 추상화가 드디어 이루졌다라는 것이며 이제 그것을 가져다 사용하기만 하면 된다. ( 사실 쉽게 말했지만 시퀀셜한 로직보다 이해하기 어렵긴 할 것이다...내가 순수함수형 개발이 대중화 될 가능성이 0%라고 항상 말해왔다시피.. 이 Reactive 파라다임이 어떻게 대중에게 받아드려질지에 관해서 또한 귀추가 주목된다.)


참고:  비동기 그리고 Reactive 파라다임의 권위자이신 Erik Meijer (LINQ 설계자)의 reactive 개념 동영상 

https://www.youtube.com/watch?v=sTSQlYX5DU0

동영상에서 그의 목소리가 떨리는 이유는 다음 글에서 찾을 수 있을거 같다.

임백준 작가의 Erik Meijer 에 대한 헌시 

Erik Meijer 의 한마디

“이보게, 브라이언 괴츠, C#, 파이선, 자바스크립트는 물론, 심지어 PHP도 async, await를 지원하고 있다네. 그런 기능이 없는 언어는 자바일 뿐이야. 람다를 이용해서 콜백callback 함수를 사용하면 된다고? 천만에. 콜백은 최악이야. 도움이 안 된다고. 자바 9 버전에 담으려고 하는 걸 다 내려놓고 지금 당장 async, await부터 넣으라고. 그래야 모두가 행복해질 수 있어.”

completableFuture 는   -.-a


Reactive 선언문

http://www.reactivemanifesto.org/ko


Reactive 의 4가지 주요 속성

요약하면 아래와 같다.

- Responsive : 사용자에 대한 반응(React)

- Scalable(Elastic)  : 부하(road)에 대한 반응(React)

- Resillent : 실패상황에 대한 반응(React)

- Event-driven : 이벤트에 대한 반응(React)


각각에 대해 좀 더 살펴보자.


Responsive
쉽게 말해서 웹브라우저의 사용자가 한참을 기다리지 않게 하는 것이다. 즉 정해진 시간안에 반드시 결과를 받아 볼 수 있게 하자는것. 그 결과가 진짜 결과가 아니라 " 지금 처리중입니다~~~" 라는 메세지일지라도.

추가적으로

우리가 엑셀을 사용 할때 A 가 =SUM(B1,C1)  이것이라면 , C1 의 값을 97로 변경하면 자연스럽게 A 는 100이 될것임을 알 수 있다. 이것처럼 우리가 어떤 행동을 했을 때 자연스럽게 사용자에게 반응하기 위한 노력을 하자는 의미로 볼 수 있다.



Scalable(Elastic)

익히 알고 있는 규모 변경성질이다. Scalable 은 주로 확장의 의미가 있기 때문에 요즘은 확장되었다가 다시 축소도 시킬 수 있다는 의미로 Elastic 을 사용하기도 한다. 어플리케이션을 수평확장시키는 방식은 여러모로 굉장히 어려운 도전이긴하다.

서버사이드쪽의 유저 세션 또는 캐쉬등의 복제가 필요로하며, 데이타베이스 레벨에서는 다양한 복제시나리오 (master to master 등) 가 추가되어야 할것이다. Deployment 할 때의 추가 복잡성도 굉장히 클거라 본다. 다양한 AWS 서비스 및 Docker의 등장등 Reactive 파라다임의 가는 길에 좋은 도우미도 같이 발전하고 있다.


Resillent

New York 주식거래소는 2012년 8월 1일에 오전 9:30분에 개장을 했었을때, KCG 의 자동 거래 소프트웨어는 자동적으로 주식거래를 시작했고 오랫동안 일을 완수하고 있었습니다. 몇일전에 어플리케이션의 새로운 버전이 서버에 적용되었고 새로운 추가기능이 돌아가기 시작했습니다.  그 날은 먼가 이상한 조짐을 보였고 마켓이 열린지 45분후에 완전히 맛이 갔습니다. 440밀리언달러의 손실을 만들어내었습니다.

버그가없는,실패하지 않는 소프트웨어를 만드는것은 거의 불가능에 가깝다.  이러한 실패를 피해 완벽한 프로그램을 개발하는 것 보다 reactive 파라다임은 실패를 포함하는 설계를 하도록 한다. 즉 충돌하게 내버려둬~~ 라는 철학을 가지고 있다. 관리자 역할을 하는 액터는 자동으로 실패를 감지하고 원상태로 회복하게 만드는데 즉 재앙을 최소화하는것에 관심을 두고 있다.


Event-driven

웹서버에서 동기식 멀티쓰레드로 request 가 대응되는것이 아니라, 비동기식 event 별로 처리를 하게되면 리소스 활용성이 높아진다 (메모리 및 CPU). 하지만 공유상태를 나눠같는것에 있어서 어려움이 생길 수 있다. 따라서 그런 어려움을 방어 하기 위해 immutable 상태 지향의 개발, Actor, STM 등의 기술이 함께 따라다닌다.   

      

즉 데이터가 흘러감에 있어서 변경가능한 상태에서의 알수 없는 변화는 지옥의 버그를 창조하므로 자연스럽게 함수형파라다임이 가미가 되는 것이다. 


기술적으로 설명해보면 아래와 같다.

이미지출처: https://deepakpol.wordpress.com/2015/09/29/event-driven-and-reactive-architecture/

     

Event 를 처리하는 루프(쓰레드)가 있으며 해당 이벤트를 받기위해 구독을 신청한 노드의 핸들러에게 메세지(이벤트) 를 전달해준다. 물론 그 이벤트루프에 이벤트를 발생하는 녀석도 있을 것이다.

즉 

- Events   ( 웹으로 말하면 브라우저에서의 Request 및 미들웨어로의 요청)

- Event Loop (Reqeust 를 처리하는 엔진) 

- Event Handler (Request 를 받아서 비니지스로직을 구현. 이것은 주로 당신이 만드는것이다.)

로 이루어져있다.

좀 더 구체적인 예를 Akka 를 통해서 살펴보면

이미지출처: https://deepakpol.wordpress.com/2015/09/29/event-driven-and-reactive-architecture/


  1. sender Actor(A라고하자)는 ActorSystem 의 actorOf() 메소드를 통해서 초기화 한다.
  2. ActorSystem  는 수신될 Actor (B) 의 레퍼런스를 만든다. ( 이시점에 Actor(B) 가 만들어지는 것은 아니다)  ActorRef 는 실제 Actor(B)의 프록시로 행동한다. 
  3. sender Actor(A) 가 B 에게 이벤트를 보낸다. (비동기로~)
  4. ActorRef 는  MessageDispatcher에게 그 이벤트를 넘긴다 (dispatche)
  5. MessageDispatcher 는 전역MessageQueue에 이벤트를 넣는다.
  6. MessageDispatcher 는 또한 수신 Actor에 대한 메일함을 발견하고 활용가능한 쓰레드풀의 쓰레드를 이용해서 실행한다.
  7. 실제 수신액터의 onReceive 핸들러에서 이벤트를 처리한다. 


Reactive : 간단한 코드로 말해요

나 포함 대부분의 개발자들은 사실 메뉴얼 및 API 를 꼼꼼히 읽거나, 개념을 글로 이해하기 보다 코드(Hello world) 로 먼저 시도해 보고, 문서보고 그러한 반복 과정을 통해 이해해 왔을 것이다.

그래!! 이제 간단한 코드를 살펴 볼 시간이다.

=> 다음포스트에서..



참고:

https://deepakpol.wordpress.com/2015/09/29/event-driven-and-reactive-architecture/

https://www.youtube.com/watch?v=oS9w3VenDW0

Reactive web applications 

https://www.lightbend.com/blog/reactive-manifesto-20