Akka는 자바와 스칼라를 위한 액터 기반 프레임워크입니다. 액터는 동시성을 처리하기 위한 식별 가능한 엔티티로, 각각 독립적으로 실행되며 메시지를 주고받을 수 있습니다. 이러한 액터 모델은 선점형 스레드 대신 비선점형 메시지 패싱을 사용하여 동시성 문제를 해결합니다.
액터의 개념
액터는 최소 기능 단위로, 동작을 정의하고 메시지를 받거나 전송할 수 있는 개체입니다. 각 액터는 고유한 식별자(ID)를 가지며, 동작을 수행하는 동안 상태를 유지할 수 있습니다. 액터는 다른 액터와 상호작용하기 위해 메시지를 전송하며, 메시지는 비동기적으로 처리됩니다.
액터는 다음과 같이 정의할 수 있습니다.
public class MyActor extends AbstractActor {
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Message.class, this::handleMessage)
.build();
}
private void handleMessage(Message message) {
// 메시지 처리 로직
}
}
액터 클래스는 AbstractActor
를 상속하고 createReceive
메서드를 오버라이드하여 메시지 핸들링 로직을 정의합니다. receiveBuilder
를 사용하여 메시지 타입에 따른 처리를 등록할 수 있습니다.
메시지 패싱
액터는 메시지를 비동기적으로 전송하고 처리합니다. 메시지는 불변(immutable)하며, 액터 간에 전송될 때 복사되어 전달됩니다. 메시지를 보내려면 액터의 ActorRef
를 획득하여 tell
메서드를 호출합니다.
ActorRef myActorRef = actorSystem.actorOf(Props.create(MyActor.class));
myActorRef.tell(new Message(), ActorRef.noSender());
ActorRef
는 액터에 대한 참조로, 액터에게 메시지를 보내는 데 사용됩니다. tell
메서드의 두 번째 인자는 응답을 받을 액터의 ActorRef
입니다. ActorRef.noSender()
를 사용하여 응답 미수신을 나타낼 수 있습니다.
메시지 처리
액터가 메시지를 수신하면 createReceive
메서드에서 정의한 핸들러가 호출됩니다. 핸들러는 메시지 타입에 따라 분기하여 로직을 수행합니다. 메시지 처리 중 다른 액터와의 상호작용이 필요한 경우, 해당 액터에게 메시지를 보내거나 ActorRef
를 전달하여 응답을 받을 수 있습니다.
private void handleMessage(Message message) {
// 다른 액터에게 메시지 전송
otherActorRef.tell(new OtherMessage(), getSelf());
// 응답 처리
getContext().become(waitingForResponse());
}
private PartialFunction<Object, BoxedUnit> waitingForResponse() {
return ReceiveBuilder
.match(Response.class, this::handleResponse)
.build()
}
private void handleResponse(Response response) {
// 응답 처리 로직
}
getSelf
메서드는 현재 액터의 ActorRef
를 반환합니다. getContext
를 통해 액터의 상태와 동작을 변경할 수 있는 메서드에 접근할 수 있습니다. 예를 들어, become
메서드를 사용하여 다음 메시지 처리를 위한 새로운 핸들러를 등록할 수 있습니다.
결론
Akka의 액터 모델과 메시지 패싱은 동시성 문제를 해결하는 강력한 도구입니다. 메시지를 주고받는 액터는 독립적으로 실행될 수 있으며, 비선점형 패러다임을 통해 더욱 안정적인 동시성 처리를 가능하게 합니다. Akka를 사용하여 복잡한 동시성 문제를 간결하게 해결할 수 있습니다.