[java] Akka와 웹 서비스의 통합

Akka는 액터 모델을 기반으로 하는 동시성 프레임워크로, 분산 시스템과 병렬 처리를 위한 강력한 도구입니다. 웹 서비스와의 통합은 많은 애플리케이션에서 필요한 기능입니다. 이번 글에서는 Akka와 웹 서비스의 통합에 대해 알아보겠습니다.

1. Akka-HTTP 사용하기

Akka-HTTP는 액터 모델과 통합하여 높은 수준의 웹 서비스를 제공하는 라이브러리입니다. 간단한 RESTful 웹 서비스를 구축하는 예제를 살펴보겠습니다.

import akka.actor.ActorSystem;
import akka.http.javadsl.Http;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.server.AllDirectives;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.server.directives.PathMatchers;

public class WebServiceIntegration extends AllDirectives {

    public static void main(String[] args) throws Exception {
        ActorSystem system = ActorSystem.create();
        final Http http = Http.get(system);
        final WebServiceIntegration app = new WebServiceIntegration();

        final Route route = app.route();

        http.bindAndHandle(route.flow(system, materializer), ConnectHttp.toHost("localhost", 8080), materializer);
    }

    private Route route() {
        return path(PathMatchers.segment("api").slash("users"), () ->
            get(() -> complete("Get all users"))
        );
    }
}

이 예제에서는 WebAndJSEngine 클래스를 사용하여 웹 서비스를 정의하고, ActorSystem을 생성합니다. 그리고 Http 객체를 통해 HTTP 서버를 바인딩하고 요청을 처리하는 라우팅을 정의합니다. 이 예제에서는 /api/users 경로로 GET 요청이 오면 “Get all users” 문자열을 반환하는 간단한 핸들러를 정의하였습니다.

2. Akka-HTTP와 Akka-Streams의 통합

Akka-HTTP와 Akka-Streams를 함께 사용하면 웹 소켓과 같은 이벤트 기반 작업을 처리하는 데 유용한 기능을 제공할 수 있습니다. 예를 들어, 웹 소켓으로 실시간 데이터를 전송하는 예제를 살펴보겠습니다.

import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.http.javadsl.Http;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.model.ws.Message;
import akka.http.javadsl.model.ws.TextMessage;
import akka.http.javadsl.server.AllDirectives;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.server.directives.PathMatchers;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Source;

import java.time.Duration;

public class WebSocketIntegration extends AllDirectives {

    public static void main(String[] args) throws Exception {
        ActorSystem system = ActorSystem.create();
        final Http http = Http.get(system);
        final WebSocketIntegration app = new WebSocketIntegration();
        final ActorMaterializer materializer = ActorMaterializer.create(system);

        final Route route = app.route();

        http.bindAndHandle(route.flow(system, materializer), ConnectHttp.toHost("localhost", 8080), materializer);
    }

    private Route route() {
        return path(PathMatchers.segment("ws"), () ->
            get(() -> handleWebSocketMessages(WebSocket.integration()))
        );
    }

    private static class WebSocket {
        public static Flow<Message, Message, NotUsed> integration() {
            Source<Message, NotUsed> source = Source.tick(Duration.ofSeconds(1), Duration.ofSeconds(1), TextMessage.create("Hello, world!"));
            Flow<Message, Message, NotUsed> flow = Flow.fromSinkAndSource(Flow.<Message>create().map(m -> TextMessage.create("Received: " + m.asTextMessage().getStrictText())), source);

            return flow;
        }
    }
}

이 예제에서는 /ws 경로로의 GET 요청에 대한 웹 소켓 핸들러를 정의하였습니다. 핸들러에서는 Source.tick 메소드를 사용하여 1초마다 “Hello, world!” 메시지를 생성하고, Flow.fromSinkAndSource 메소드를 통해 받은 메시지에 대해 “Received: “ 프리픽스를 붙여 반환합니다.

Conclusion

Akka와 웹 서비스의 통합은 간단하면서도 강력한 동시성 프로그래밍 모델과 높은 수준의 웹 서비스를 제공합니다. Akka-HTTP를 사용하여 RESTful 웹 서비스를 구축하고, Akka-Streams를 활용하여 이벤트 기반 작업을 처리하는 방법을 살펴보았습니다.

더 많은 자세한 내용과 예제 코드는 Akka Documentation을 참고하시기 바랍니다.