Akka, Actor, ActorSystem 등 기본 개념 이해하기
이 글은, 2주 전에 잠깐 공부했던 Akka에 대한 글이다. 필자가 Scala 언어에 익숙하지 않기 때문에 부득이하게 Java 기반으로 공부를 진행하였고, 애매한 내용이 많아서 블로그 글을 작성하지는 않았었는데, 당분간 Akka를 공부할 일이 없을 것 같아서 공부했던 내용만이라도 대충 글로 남겨본다. 추후에 기회가 되어서 Akka 프로젝트를 진행하게 된다면 그때 다시 공부를 진행 하겠다. 또한, 참조자료는 레퍼런스를 표시하였다. 혹시라도, 저작권에 문제가 되는 내용이 있다면 반드시 제보해주길 바란다.
Akka는 오픈 소스 툴킷으로, JVM 상의 동시성과 분산 애플리케이션을 단순화하는 런타임이다. Akka는 동시성을 위한 여러 프로그래밍 모델을 지원하지만, Erlang으로부터 영향을 받아 Actor 기반의 동시성이 두드러진다. 자바와 스칼라 언어 모두로 작성이 가능하다. [1]
아카는 액터 모델을 구현한 라이브러리이다. 액터를 활용한 고도의 동시성 코드를 작성하는 것을 가능하게 해준다. 액터는 ‘쓰레드’ 혹은 ‘객체’와 구별되는 추상이다. 액터가 차지하는 메모리 공간은 어느 다른 쓰레드 혹은 액터가 접근할 수 없다. 다시 말해서 액터 내부에서 일어나는 일은 어느 누구와도 ‘공유’되지 않는다. [2] The Actor Model provides a higher level of abstraction for writing concurrent and distributed systems. It alleviates the developer from having to deal with explicit locking and thread management, making it easier to write correct concurrent and parallel systems. Actors were defined in the 1973 paper by Carl Hewitt but have been popularized by the Erlang language, and used for example at Ericsson with great success to build highly concurrent and reliable telecom systems.[4]
Akka actor를 기반으로하는 애플리케이션의 구별되는 특징은 다음과 같다.
동시성은 메시지 기반이며 비동기 방식으로 이루어진다: 일반적으로 변형 가능한 데이터를 공유하거나 동기화되는 primitive를 사용해서는 안됩니다: Akka는 액터 모델을 구현한다.
동일한 호스트든 분산된 호스트들이든, 직접 통신하든, 몇몇 혹은 다수의 스레드 상에서 동작하는 라우팅 채널을 이용하여 통신하든, 혹은 이외의 방법으로 통신을 하든 actor들이 상호작용하는 방식은 동일하다. 이러한 세부사항들은 프로그램이 수정 없이 스케일-업(더 성능이 뛰어난 서버를 사용)하거나 스케일-아웃(더 많은 서버를 사용)하기 위해 배포 시점의 구성 메카니즘에 따라 변경할 수 있다.
Actor들은 프로그램의 오류를 연관성에 따라 계층적으로 분류한다. 이 오류들은 actor의 supervisor의 이벤트로 처리된다(어느 actor가 오류를 발생했다는 메시지인지를 가리지 않음). 얼랭과는 대조적으로 Akka는 parental supervision을 강조한다. 이는 각 actor가 parent actor에 의해 생성되고 감독받는 것을 의미한다.
위키피디아의 내용을 그대로 참고하였다. [1]
Akka 에서 Actors 를 사용하여 어떻게 프로그래밍을 하는지 알아보자. 이 글에서는 Scala 기반의 sbt 프로젝트와, Java 기반의 스프링부트를 동시에 검토할 것이다. sbt 와 스프링부트에 대한 설명은 따로 하지 않을 예정이다. 참고로, 필자가 Scala 프로그래밍에 익숙하지 않아서, 필자에게 익숙한 Java & 스프링부트 환경에서 조금 더 상세하게 다룰 예정이다. Scala 에 대해서는 나중에(?) 다시 공부할 예정이다.
Akka Actor 프로그래밍을 위해서, 프로젝트에 아래와 같은 디펜던시를 추가하자.
sbt(scala)
Scala 기반의 sbt 프로젝트에서, build.sbt 파일에 akka-actor 디펜던시를 추가하자.
Gradle(Java)
Java 기반의 스프링 부트 프로젝트에서, build.gradle 파일에 akka-actor 디펜던시를 추가한다.
ActorSystem 은 Actor 을 시작하고 Actor의 생명주기를 관리하는 객체이다. ActorSystem 은 딱 하나만 만들 것을 추천한다. An actor system is a hierarchical group of actors which share common configuration, e.g. dispatchers, deployments, remote capabilities and addresses. It is also the entry point for creating or looking up actors. [6]
필자가 영어를 잘 못해서, 번역이 어려운 문장은 영어 그대로 남겼다. 잘못 번역해서, 잘못된 정보를 전달하는 것보다는 차라리 영어 원문 그대로 전달하는게 낫겠다는 판단이다... ㅠㅠ
각각의 언어에서 ActorSystem을 어떻게 생성하는지 알아보자. 먼저 sbt에서는 아래와 같이 작성하면 된다.
sbt(scala)
자바 라이브러리에서는 아래와 같이 작성하면 된다.
Spring(Java)
중요한 사실은, ActorSystem 은 딱 하나만 생성하는게 효율적이다. 그래서 @Bean 으로 정의하였다. 하지만, 구글링을 통해서 검색한 Spring&Akka 연동 샘플 코드는 대부분 필자가 작성한 것 처럼 @Bean 으로 단순하게 정의하지 않고... Akka Extension 를 통해서 Akka 와 Spring을 통합한다. 필자가 해당 내용을 자세히 확인 하고 싶은데, 정확히 이해가 안되어서 일단 넘어갔다. 혹시라도 해당 내용에 대해서 아는 개발자가 있다면 피드백을 해주길 바란다. 즉, 필자가 @Bean 으로 정의한 방식이 잘못한 방법일 가능성이 높다. Baeldung 의 글을 확인하길 바란다.
해당 내용에 대한 자세한 내용은 아래 링크를 통해서 확인하길 바란다.
https://www.baeldung.com/akka-with-spring
Akka Actor 를 정의해보자.
sbt(scala)
생략한다. 지금부터 글은... Java 기반으로 작성하겠다.
Spring(Java)
AbstractActor 를 상속받아서 커스텀한 Actor 클래스를 작성하면 된다.
AbstractActor 에 대해서는 공식 문서를 참고하자.
https://doc.akka.io/japi/akka/current/akka/actor/AbstractActor.html
AbstracActor 를 상속받으면서 createReceive 메서드를 재정의하자.
An actor has to define its initial receive behavior by implementing the
createReceive method.
아래와 같이 간단하게 Thread.sleep(2초) 딜레이 시간을 추가해봤다.
추가로 AbstracActor 를 상속받은 클래스는 아래와 같은 메서드도 재정의할 수 있다. 참고만 하자.
Actor 라이프사이클에 대해서는 공식 레퍼런스를 참고하자.
간단하게 Actor를 실행시켜보자. 먼저 ActorSystem 을 주입받는다.
그리고, ActorRef 를 3개 생성한다. 필자는 해당 3개의 작업을 병렬로 실행할 것이다.
필자가, Actor 를 정의할 때 Thread.sleep(2초) 의 지연 시간을 넣었었다. actorRef01 에 2초의 지연시간이 있지만, actorRef01 과는 별개로 actorRef02 와 actorRef03는 개별적으로 실행될 것이다. 각자의 쓰레드 환경에서 실행이 되는 것이다. 아래오 같이 실행해보자. 어떻게 될까?
결과는. 아래 캡쳐를 참고해보면 3개의 작업이 동시에 거의 시작되었고, 2초의 지연시간도 각자 쓰레드에 걸리는 것을 확인할 수 있다.
음... 필자가 제대로 구현한게 맞는지 모르겠다. 맞겠지??
Akka 를 잠시 공부해봤는데, Akka를 실무에서 도입하기 위해서 기본적으로 이해해야 하는 개념이 꽤 많았다. ActorSystem, ActorRef, MailBox 등 전반적으로 이해를 하고, Akka 의 설계 철학에 대해서 이해하는게 중요할 것 같다. 필자가 구현한 샘플이 의미가 있는지는 모르겠지만, Akka 는 고성능이 요구되는 백엔드 플랫폼에 도입을 해보는 것도 좋은 대안이라고 생각한다. 회사 시스템에 도입하기에는 아직 필자 또는 팀원의 기술역량이 부족하여 당장 도입하기는 어렵겠지만, 나중에 Scala 언어를 배우고, 동시성 프로그래밍에 대한 기술역량이 높아지는 시점에서는 한번쯤은 도입해도 괜찮을 것 같다는 생각이다. 부족한 글이지만, 이만 글을 마치겠다. 끝!
https://github.com/sieunkr/akka-java/tree/master/akka-actors
[1] https://ko.wikipedia.org/wiki/Akka#cite_note-1
[2] http://www.zdnet.co.kr/view/?no=20140213110522&re=R_20140309153257
[3] https://developer.lightbend.com/guides/akka-quickstart-java/index.html
[4] https://doc.akka.io/docs/akka/current/index-actors.html
[5] https://www.youtube.com/watch?v=xddHqIcnvHw
[6] https://doc.akka.io/api/akka/current/akka/actor/ActorSystem.html