AXON 프레임워크로 CQRS와 Event Sourcing 정복하기: 단계별 가이드 🚀

AXON 프레임워크

복잡한 비즈니스 로직을 처리할 수 있는 확장 가능하고 유지보수하기 쉬운 Java 애플리케이션을 구축하고 싶으신가요? AXON 프레임워크만한 것이 없습니다. 이 강력한 도구를 사용하면 Command Query Responsibility Segregation (CQRS)Event Sourcing 패턴을 쉽게 구현할 수 있습니다. 이 종합 가이드에서는 AXON 설정, 명령 및 이벤트 객체 생성, Spring 프레임워크와의 통합 과정을 단계별로 안내해 드리겠습니다. 같이 살펴볼까요? 🌊

AXON 프레임워크란? 🤔

AXON은 CQRS와 Event Sourcing 아키텍처 패턴을 기반으로 애플리케이션을 구축할 수 있는 탄탄한 기반을 제공하는 Java 기반 프레임워크입니다. 복잡한 비즈니스 로직을 효과적으로 모델링하고 확장성과 일관성을 모두 갖춘 마이크로서비스 아키텍처를 구축하는 데 도움이 됩니다.

📌 AXON의 주요 기능:

  • CQRS 지원으로 읽기 모델과 쓰기 모델 분리 가능
  • Event Sourcing을 통해 시스템 변경 사항의 완전한 감사 추적 보장
  • Spring 프레임워크와 원활하게 통합
  • 강력하고 유연한 명령 및 이벤트 처리 메커니즘 제공

AXON 프레임워크 설정하기 🛠️

AXON을 시작하려면 먼저 프로젝트에 필요한 종속성을 추가해야 합니다. Maven 기반 프로젝트를 사용하는 경우 pom.xml 파일에 다음 내용을 포함하기만 하면 됩니다:

<dependency>
    <groupId>org.axonframework</groupId>
    <artifactId>axon-spring-boot-starter</artifactId>
    <version>4.6.3</version>
</dependency>

이렇게 하면 AXON 프레임워크와 Spring Boot와의 통합이 프로젝트에 포함됩니다.

명령과 이벤트 객체 생성하기 📦

다음 단계는 AXON에서 CQRS와 Event Sourcing을 구현하는 데 중요한 명령과 이벤트 객체를 생성하는 것입니다. 명령은 시스템의 상태를 변경하라는 요청을 나타내고, 이벤트는 시스템의 상태 변경 사항을 나타냅니다.

명령 객체의 예시입니다:

public class CreateOrderCommand {
    private final String orderId;
    private final List<OrderLine> orderLines;

    // 생성자, 게터 등
}

해당 이벤트 객체의 예시입니다:

public class OrderCreatedEvent {
    private final String orderId;
    private final List<OrderLine> orderLines;

    // 생성자, 게터 등
}

이러한 객체는 애플리케이션 내에서 명령과 이벤트의 흐름을 처리하는 데 사용됩니다.

AXON을 Spring 프레임워크와 통합하기 🌱

AXON은 Spring 프레임워크와 원활하게 작동하도록 설계되었습니다. AXON 설정을 완료하고 집계(Aggregate)와 명령 처리기(Command Handler)를 Spring Bean으로 등록하려면 Spring의 @Configuration 어노테이션을 사용하면 됩니다.

@Configuration
public class AxonConfig {

    @Bean
    public AggregateFactory<Order> orderAggregateFactory() {
        return new GenericAggregateFactory<>(Order.class);
    }

    @Bean
    public CommandHandler<CreateOrderCommand> createOrderCommandHandler() {
        return new CreateOrderCommandHandler();
    }

    // 다른 Bean과 설정
}

이렇게 설정하면 AXON이 자동으로 집계와 명령 처리기를 발견하고 등록하므로 애플리케이션 내에서 바로 사용할 수 있습니다.

CQRS와 Event Sourcing 구현 테스트하기 🧪

AXON 구현 설정이 완료되었으니 이제 모든 것이 예상대로 작동하는지 확인할 차례입니다. JUnit을 사용하여 명령 처리기와 집계에 대한 단위 테스트를 작성할 수 있습니다.

테스트 케이스 예시입니다:

@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderTest {

    @Autowired
    private CommandGateway commandGateway;

    @Test
    public void testCreateOrder() {
        String orderId = UUID.randomUUID().toString();
        List<OrderLine> orderLines = Arrays.asList(
            new OrderLine("product1", 2),
            new OrderLine("product2", 1)
        );

        CreateOrderCommand command = new CreateOrderCommand(orderId, orderLines);
        commandGateway.sendAndWait(command);

        // 주문이 성공적으로 생성되었는지 확인
        // ...
    }
}

포괄적인 테스트를 작성하면 AXON을 사용한 CQRS와 Event Sourcing 구현이 올바르게 작동하고 비즈니스 요구사항을 충족하는지 확인할 수 있습니다.

결론 🎉

AXON 프레임워크는 복잡한 비즈니스 요구사항을 해결하고 확장 가능하며 유지보수하기 쉬운 애플리케이션을 구축하는 강력한 도구입니다. AXON으로 CQRS와 Event Sourcing 패턴을 활용하면 가장 까다로운 문제에 대해서도 우아한 솔루션을 설계하고 구현할 수 있습니다.

향후 게시물에서는 AXON 프레임워크의 보다 고급 기능과 사용 사례를 살펴보고 그 잠재력을 최대한 발휘할 수 있도록 도와드리겠습니다. 기대해 주세요! 🎉

추천 링크

AXON 공식 문서: AXON 프레임워크에 대한 가장 공식적이고 포괄적인 정보를 제공합니다. 세부적인 설명과 다양한 사용 예시가 포함되어 있어요. DZone – CQRS pattern: CQRS 패턴을 마이크로서비스에 적용하는 방법에 대해 잘 설명한 글입니다. CQRS의 개념과 장단점, 활용 예시 등을 확인할 수 있어요. Event Sourcing Pattern: Event Sourcing 패턴에 대해 자세히 설명하는 Martin Fowler의 글입니다. Event Sourcing의 기본 개념부터 구현 방법, 주의사항 등을 폭넓게 다루고 있죠. Spring CQRS/ES Workshop: AXON과 Spring을 활용해 실제로 CQRS와 Event Sourcing을 구현해볼 수 있는 워크샵입니다. 코드 예제와 함께 단계별 가이드를 제공해요. Greg Young – CQRS and Event Sourcing: CQRS와 Event Sourcing의 창시자 중 한 명인 Greg Young의 강연 영상입니다. CQRS와 Event Sourcing의 기본 개념과 패턴에 대해 심도있는 인사이트를 얻을 수 있어요.

Mastering CQRS and Event Sourcing with AXON Framework: A Step-by-Step Guide 🚀

AXON Framework

Are you looking to build scalable and maintainable Java applications that can handle complex business logic? Look no further than the AXON Framework, a powerful tool for implementing Command Query Responsibility Segregation (CQRS) and Event Sourcing patterns. In this comprehensive guide, we’ll walk you through the process of setting up AXON, creating command and event objects, and integrating it with the Spring Framework. Let’s dive in! 🌊

What is AXON Framework? 🤔

AXON is a Java-based framework that provides a solid foundation for building applications based on the CQRS and Event Sourcing architectural patterns. It helps you effectively model complex business logic and build microservice architectures that are both scalable and consistent.

📌 Key Features of AXON:

  • Supports CQRS, allowing you to separate read and write models
  • Enables Event Sourcing, ensuring a complete audit trail of system changes
  • Integrates seamlessly with Spring Framework
  • Provides a robust and flexible command and event handling mechanism

Setting Up AXON Framework 🛠️

To get started with AXON, the first step is to add the necessary dependencies to your project. If you’re using a Maven-based project, simply include the following in your pom.xml file:

<dependency>
    <groupId>org.axonframework</groupId>
    <artifactId>axon-spring-boot-starter</artifactId>
    <version>4.6.3</version>
</dependency>

This will include the AXON Framework and its integration with Spring Boot in your project.

Creating Command and Event Objects 📦

The next step is to create command and event objects, which are crucial for implementing CQRS and Event Sourcing with AXON. Commands represent requests to change the system’s state, while events represent the actual changes in the system’s state.

Here’s an example of a command object:

public class CreateOrderCommand {
    private final String orderId;
    private final List<OrderLine> orderLines;

    // Constructor, getters, etc.
}

And here’s an example of a corresponding event object:

public class OrderCreatedEvent {
    private final String orderId;
    private final List<OrderLine> orderLines;

    // Constructor, getters, etc.
}

These objects will be used by AXON to handle the flow of commands and events within your application.

Integrating AXON with Spring Framework 🌱

AXON is designed to work seamlessly with the Spring Framework. To complete the AXON setup and register your aggregates and command handlers as Spring beans, you can use Spring’s @Configuration annotation.

@Configuration
public class AxonConfig {

    @Bean
    public AggregateFactory<Order> orderAggregateFactory() {
        return new GenericAggregateFactory<>(Order.class);
    }

    @Bean
    public CommandHandler<CreateOrderCommand> createOrderCommandHandler() {
        return new CreateOrderCommandHandler();
    }

    // Other beans and configurations
}

With this setup, AXON will automatically discover and register your aggregates and command handlers, making them available for use within your application.

Testing Your CQRS and Event Sourcing Implementation 🧪

Now that you have your AXON implementation set up, it’s time to test it to ensure that everything is working as expected. You can use JUnit to write unit tests for your command handlers and aggregates.

Here’s an example test case:

@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderTest {

    @Autowired
    private CommandGateway commandGateway;

    @Test
    public void testCreateOrder() {
        String orderId = UUID.randomUUID().toString();
        List<OrderLine> orderLines = Arrays.asList(
            new OrderLine("product1", 2),
            new OrderLine("product2", 1)
        );

        CreateOrderCommand command = new CreateOrderCommand(orderId, orderLines);
        commandGateway.sendAndWait(command);

        // Assert that the order was created successfully
        // ...
    }
}

By writing comprehensive tests, you can ensure that your CQRS and Event Sourcing implementation using AXON is functioning correctly and meeting your business requirements.

Conclusion 🎉

The AXON Framework is a powerful tool for tackling complex business requirements and building scalable, maintainable applications. By leveraging CQRS and Event Sourcing patterns with AXON, you can design and implement elegant solutions to even the most challenging problems.

In future posts, we’ll explore more advanced features and use cases of the AXON Framework, helping you unlock its full potential. Stay tuned! 🎉

추천 링크

  • AXON 공식 문서: AXON 프레임워크에 대한 가장 공식적이고 포괄적인 정보를 제공합니다. 세부적인 설명과 다양한 사용 예시가 포함되어 있어요.
  • DZone – CQRS pattern: CQRS 패턴을 마이크로서비스에 적용하는 방법에 대해 잘 설명한 글입니다. CQRS의 개념과 장단점, 활용 예시 등을 확인할 수 있어요.
  • Event Sourcing Pattern: Event Sourcing 패턴에 대해 자세히 설명하는 Martin Fowler의 글입니다. Event Sourcing의 기본 개념부터 구현 방법, 주의사항 등을 폭넓게 다루고 있죠.
  • Spring CQRS/ES Workshop: AXON과 Spring을 활용해 실제로 CQRS와 Event Sourcing을 구현해볼 수 있는 워크샵입니다. 코드 예제와 함께 단계별 가이드를 제공해요.
  • Greg Young – CQRS and Event Sourcing: CQRS와 Event Sourcing의 창시자 중 한 명인 Greg Young의 강연 영상입니다. CQRS와 Event Sourcing의 기본 개념과 패턴에 대해 심도있는 인사이트를 얻을 수 있어요.

[2023] 리눅스에서 Nexus 설치 및 설정

Nexus 설치

안녕하세요! 오늘은 소프트웨어를 쉽게 배포할 수 있도록 도와주는 Nexus 설치 및 설정 방법에 대해 소개하려 합니다. 

Nexus는 저장소 관리자로서, 종속성을 프록시, 수집, 관리함으로써 JAR 파일들을 지속적으로 관리할 수 있게 해줍니다. 

내부적으로 Nexus에 아티팩트를 게시하도록 빌드를 구성하면, 다른 개발자들이 해당 아티팩트를 사용할 수 있게 됩니다. 

이 포스트는 리눅스에서 Nexus 설치하고 설정는 방법에 대한 가이드입니다.

Step1: Java 8 설치

Nexus를 실행하기 위해서는 리눅스 서버에 Java 8이상이 설치되어 있어야 합니다. 패키지 목록 업데이트를 한 후, Java 8을 설치해보겠습니다.

sudo dnf update -y
sudo dnf install java-1.8.0-openjdk-devel -y

설치가 완료된 후, 다음 명령어를 실행하여 Java 버전을 확인합니다.

# java -version

또한, 설치 경로를 알고 싶다면 다음 명령어를 실행해보세요.

<em># dirname $(dirname $(readlink -f $(which javac)))</em>
Step2: Nexus 설치

다음으로 Nexus 설치 파일을 가져와야 합니다. 저는 Sonatype 홈페이지에서 FreeOSS 버전을 다운 받아 리눅스 서버에 옮겼습니다.

# Nexus 파일을 /opt 위치로 이동하기
cp /파일경로 /opt

# 압축 해제
sudo tar -xvf latest-unix.tar.gz

# 파일명 변경
mv /opt/latest-unix /opt/nexus
Step3: Nexus 사용자 생성

Nexus를 안전하게 운영하기 위해 별도의 사용자를 생성하겠습니다. ‘nexus’라는 이름의 사용자를 생성하고 해당 사용자를 /opt/nexus 디렉토리의 소유자로 지정합니다.

sudo useradd -r -m -U -d /opt/nexus -s /bin/bash nexus
sudo chown -R nexus:nexus /opt/nexus
sudo chown -R nexus:nexus /opt/sonatype-work
Step4: Nexus를 서비스로 구성

Nexus를 시스템 서비스로 등록하면, 시스템 부팅 시 자동으로 Nexus가 실행되며, 필요에 따라 서비스를 시작/중지할 수 있습니다.

sudo vi /etc/systemd/system/nexus.service

그 다음, 아래의 내용을 입력하고 저장합니다.

[Unit]
Description=nexus service
After=network.target

[Service]
Type=forking
LimitNOFILE=65536
User=nexus
Group=nexus
ExecStart=/opt/nexus/bin/nexus start
ExecStop=/opt/nexus/bin/nexus stop
Restart=on-abort

[Install]
WantedBy=multi-user.target
Step5: Nexus 시작 및 확인

설정한 Nexus 서비스를 시작하고, 상태를 확인해봅시다.

sudo systemctl daemon-reload
sudo systemctl start nexus
sudo systemctl status nexus

Nexus가 정상적으로 작동하면 서비스를 시스템 부팅 시 자동으로 시작되도록 설정합니다.

sudo systemctl enable nexus
Step6: Nexus 접속

Nexus는 기본적으로 8081 포트에서 동작합니다. 이 포트를 방화벽에서 열어주어야 외부에서 Nexus에 접속할 수 있습니다.

sudo firewall-cmd --permanent --add-port=8081/tcp
sudo firewall-cmd --reload

이제 웹 브라우저를 통해 Nexus에 접속해보세요!

이상으로 Nexus Repository Manager의 설치 및 설정에 대한 가이드를 마치겠습니다. 이 포스트가 도움이 되었기를 바라며, 다음 포스트에서 뵙겠습니다!

[우영이네]

[wooyung’s IT 블로그]

2023 자바 개발의 핵심 요소: JRE와 JDK 이해하기

세계에서 가장 널리 사용되는 프로그래밍 언어 중 하나인 자바의 이해는 그 핵심 구성요소들인 JRE와 JDK 그리고 JVM의 이해로부터 시작됩니다. 이 글에서는 이들의 기능과 상호 작용에 대해 설명하고, 개발 환경에 대한 깊은 이해를 바탕으로 효율적인 개발 전략을 구축하는 방법에 대해 다룰 것입니다.

1. JVM (Java Virtual Machine)이란?

자바 개발의 이해를 위해서는 JDK와 JRE 외에 JVM에 대한 이해가 필수적입니다. JVM은 Java Virtual Machine의 약자로, 자바 바이트코드를 해석하고 실행하는 런타임 환경을 제공합니다. JVM은 플랫폼 독립적이라는 자바의 핵심 원칙을 가능하게 하는 중요한 요소입니다. 즉, 자바로 작성된 코드는 다양한 하드웨어와 운영 체제에서 동일하게 작동할 수 있습니다. 이는 JVM이 각 운영체제에 맞게 코드를 해석하고 실행하기 때문입니다.

2. JRE (Java Runtime Environment) 이해하기

JRE와 JDK
JRE 구조

JRE는 ‘Java Runtime Environment’의 약자로, 자바로 작성된 애플리케이션을 실행하는 데 필요한 환경을 제공합니다. JRE는 핵심적으로는 JVM (Java Virtual Machine)과, 이 JVM이 자바 애플리케이션을 실행하는 데 필요한 클래스 라이브러리와 각종 API를 포함하고 있습니다. 다시 말해, JRE는 자바 프로그램을 ‘실행’하는 데 중점을 둡니다. 여기서 중요한 점은 JRE가 자바 애플리케이션의 ‘실행’에만 초점을 맞추며, 개발 도구는 포함하지 않는다는 것입니다.

3. JDK (Java Development Kit)를 이해하고 활용하기

JRE와 JDK
JDK 구조

다음으로 이해해야 할 것은 JDK, 즉 ‘Java Development Kit’입니다. JDK는 JRE를 포함하고 있으며, 자바 프로그램을 ‘개발’하는 데 필요한 도구를 제공합니다. JDK에는 추가적으로 자바 소스코드를 바이트코드로 컴파일하는 컴파일러(javac), 문서 작성을 돕는 도구(javadoc), 디버거 등의 개발 도구가 포함되어 있습니다. JDK를 사용하면, 자바로 프로그램을 작성하고 이를 실행해 볼 수 있습니다. JDK는 개발자들에게 프로그램을 개발하고 디버깅 할 수 있는 환경을 제공하며, 이는 프로그래밍 생산성 향상에 큰 기여를 합니다.

이렇게 JRE와 JDK의 이해는 자바 프로그래밍에 있어서 기본적이면서도 필수적인 요소입니다. 이들의 정확한 이해 없이는 자바의 동작 원리를 제대로 이해하기 어렵고, 효율적인 개발 환경을 구축하는 데도 어려움이 있습니다.

4. JIT 컴파일러와 가비지 컬렉션

JVM의 핵심 기능 JVM은 또한 Just-In-Time (JIT) 컴파일러와 가비지 컬렉션 등의 핵심 기능을 제공합니다. JIT 컴파일러는 자바의 성능 향상을 위해 사용되며, 프로그램 실행 중에 바이트코드를 기계어로 변환하여 최적화된 성능을 제공합니다. 가비지 컬렉션은 자동 메모리 관리 기능으로, 프로그램에서 더 이상 사용되지 않는 메모리를 자동으로 회수하여 메모리 누수를 방지합니다.

5. JRE와 JDK의 상호작용

JRE와 JDK는 자바 개발과 실행에 있어서 서로 밀접하게 관련되어 있습니다. JDK가 제공하는 개발 도구를 사용하여 작성된 자바 코드는 바이트코드로 컴파일되며, 이 컴파일된 바이트코드는 JRE가 제공하는 JVM 위에서 실행됩니다. 이러한 상호작용을 통해, 개발자들은 JDK를 사용하여 코드를 작성하고, 사용자들은 JRE를 통해 이 코드를 실행할 수 있습니다.

6. JRE와 JDK 버전 관리하기

더 나아가, 개발자들은 여러 버전의 자바(JDK와 JRE 모두)를 관리하고 필요에 따라 사용하는 방법도 알아야 합니다. 이를 위해 jEnv와 같은 버전 관리 도구를 사용할 수 있습니다. 이는 다양한 자바 버전을 쉽게 관리할 수 있게 도와줍니다. 자바의 신규 버전이 출시될 때마다 신규 버전을 적용하거나, 특정 프로젝트에 맞는 버전을 선택할 수 있게 도와줍니다.

또한, 여러 종류의 JDK가 있으며, 어떤 것을 선택할지는 개발자의 선택에 달려 있습니다. OpenJDK, Oracle JDK, AdoptOpenJDK 등 다양한 JDK 버전들이 존재하며, 이들은 성능, 지원 기간, 라이센스 등의 면에서 차이를 보입니다. 이러한 차이를 이해하고 상황에 맞는 선택을 하는 것은 효율적인 개발 환경을 구축하는 데 중요합니다.

자바의 핵심 구성요소인 JRE, JDK, 그리고 JVM에 대한 이해는 자바의 동작 원리를 깊게 이해하는 데 중요하며, 이를 통해 효율적인 개발 환경을 구축하고, 생산적인 개발을 위한 전략을 세울 수 있습니다. 앞으로 자바를 활용한 프로그래밍에 있어서, 이 두 가지 요소가 어떻게 작용하는지, 그리고 이를 효과적으로 활용하기 위해 어떤 전략이 필요한지에 대한 생각을 계속해 나가시기 바랍니다.

[블로그]

[2023] JPA ‘No default constructor for entity’ 오류: 원인과 해결방법

No default constructor for entity

안녕하세요, 오늘은 Java Persistence API (JPA)와 관련된 한 가지 매우 흔한 문제에 대해 다루려 합니다. 그 문제는 바로 ‘No default constructor for entity’ 오류입니다. 저도 이 오류를 접하며 많은 시간을 보냈고, 이 포스트를 통해 독자 여러분이 이 문제를 쉽게 이해하고 해결할 수 있길 바랍니다.

안녕하세요, 오늘은 Java Persistence API (JPA)를 사용할 때 흔히 접하는 ‘No default constructor for entity’ 오류에 대해 다루려 합니다. 이 포스트에서는 해당 오류의 원인과 해결방법에 대해 설명하겠습니다.

1. ‘No default constructor for entity’ 오류 이해하기

JPA를 사용하면서 “No default constructor for entity” 오류를 마주치게 된다면, 복잡해 보일 수도 있습니다. 이 오류는 jakarta.persistence.PersistenceException: No default constructor for entity로 표시되며, 원인을 알아보기 위해서는 JPA의 동작 방식에 대한 이해가 필요합니다.

이 오류는 JPA가 데이터베이스에서 데이터를 검색하고 해당 데이터로부터 객체를 생성할 때 발생하는데요, 기본적으로 JPA는 엔터티 클래스의 기본 생성자를 사용해 인스턴스를 생성합니다. 즉, 아래와 같은 형태의 기본 생성자가 없다는 것을 알리는 것입니다.

<code>
  public Post() {
  }
</code>

그러나 만약 이 기본 생성자가 엔터티 클래스에 없다면, JPA는 객체를 생성할 수 없어 오류를 발생시키게 됩니다.

2. 기본 생성자를 추가하는 방법

오류 해결법은 매우 간단합니다. 엔터티 클래스에 기본 생성자를 추가하는 것이 전부입니다. 예를 들어, ‘Post’ 클래스에 기본 생성자를 추가하는 경우 다음과 같이 코드를 작성하면 됩니다.

<code>
  public class Post {
      // Your existing fields and methods
      public Post() {
      }
  }
</code>

이처럼 JPA의 핵심적인 동작 원리 중 하나를 이해하면, 이 오류를 쉽게 해결할 수 있습니다. 이를 통해 JPA의 작동 원리에 대한 더 깊은 이해를 얻으셨기를 바랍니다.

결론

‘No default constructor for entity’ 오류는 JPA의 작동 원리를 이해하고, 해당 기술의 규약을 준수하는 것이 중요함을 보여줍니다. 이러한 규약을 알아두면 더 복잡한 JPA 문제를 해결하는 데 도움이 될 것입니다. 앞으로 다룰 다른 개발 문제들에 대해서도 계속 알아보시길 바랍니다.

이상으로 JPA 오류에 대한 원인과 해결방법에 대한 포스트를 마치겠습니다. 다음 포스트에서 뵙겠습니다!

개발에 대한 더 많은 정보를 확인 하고 싶으시면 제 블로그를 방문해주세요~~~!

[우영이네]

[2023] AxonFramework와 Kafka를 활용한 Spring Boot 게시판 서비스 구현하기

프로젝트 개발에서 요구되는 요구사항을 효과적으로 관리하고, 빠르게 응답하면서도 견고한 애플리케이션을 구축하는 것은 언제나 도전적인 과제입니다. 이번 포스팅에서는 AxonFramework와 Kafka를 활용하여 간단한 게시판 서비스를 Spring Boot로 구현하는 방법을 소개하려 합니다.

AxonFramework와 Kafka

1. AxonFramework와 Kafka 개발환경 설정

  • Java JDK 8이상이 설치 되어있는지  확인
  • Eclipse or IntelliJ 와 같은 통합개발환경 (IDE)을 설치
  • 종속성 관리를 위한 Apache Maven 설치

2. Spring Boot 프로젝트 생성

  • Spring Start Project를 생성
  • pom.xml에 Web, Kafka, AxonFramework 및 JPA(또는 원하는 다른 데이터베이스)를 사용하기 위한 의존성을 추가

이 pom.xml 파일은 게시판 응용 프로그램에 필요한 종속성을 사용하여 Spring Boot 프로젝트를 설정합니다.

여기에는 다음과 같은 주요 종속성이 포함됩니다.

  • spring-boot-starter-web: REST API를 지원하는 웹 애플리케이션 생성용.
  • spring-boot-starter-data-jpa: JPA 및 Hibernate를 사용하여 데이터 액세스 관리용.
  • axon-spring-boot-starter: AxonFramework와 Spring Boot 통합용.
  • spring-kafka: Kafka를 Spring Boot와 통합하기 위한 것입니다.
  • h2: 개발용 인메모리 데이터베이스.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.0.5</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>axonProject</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>axonProject</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>19</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.axonframework</groupId>
            <artifactId>axon-spring-boot-starter</artifactId>
            <version>4.7.3</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
  • application.properties(프로젝트의 src/main/resources 폴더에 application.properties 있음)
# Server configuration
server.port=8080

# Kafka configuration
spring.kafka.consumer.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=bulletin-board-group
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.producer.bootstrap-servers=localhost:9092
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer

# Axon configuration
axon.axonserver.servers=localhost:8124

3. 게시판 설계

  • 집계, 명령, 이벤트 및 쿼리 모델과 같은 애플리케이션의 주요 구성 요소를 정의합니다.
  • AxonFramework를 사용하여 명령 및 이벤트 핸들러를 구현합니다.
  • Spring Kafka를 사용하여 메시지를 생성하고 소비합니다.

4. 게시판 구현

  • 게시판의 게시물을 나타내는 새로운 집계 클래스(예: PostAggregate)를 만듭니다.
  • 게시물을 만들고 업데이트하기 위한 명령 및 이벤트 클래스(예: CreatePostCommand, PostCreatedEvent)를 구현합니다.
  • 집계 내에서 명령 및 이벤트 처리기를 구현합니다(예: @CommandHandler, @EventHandler).
  • 프로젝션 클래스(예: PostProjection)를 구현하여 이벤트를 기반으로 쿼리 모델을 업데이트합니다.
  • 쿼리 모델을 유지하기 위한 저장소(예: PostRepository)를 만듭니다.
  • REST API(예: PostController)를 구현하여 애플리케이션의 기능을 노출합니다.
// PostAggregate.java
@Aggregate
public class PostAggregate {

    @AggregateIdentifier
    private String id;
    private String title;
    private String content;

    @CommandHandler
    public PostAggregate(CreatePostCommand command) {
        apply(new PostCreatedEvent(command.getId(), command.getTitle(), command.getContent()));
    }

    @EventHandler
    public void on(PostCreatedEvent event) {
        this.id = event.getId();
        this.title = event.getTitle();        
        this.content = event.getContent();
    }

    protected PostAggregate() {
        // For Axon Framework
    }
}
// CreatePostCommand.java
public class CreatePostCommand {

    private final String id;
    private final String title;
    private final String content;

    public CreatePostCommand(String id, String title, String content) {
        this.id = id;
        this.title = title;
        this.content = content;
    }

    // Getters ...
}
// PostProjection.java
@Component
public class PostProjection {

    private final PostRepository postRepository;

    public PostProjection(PostRepository postRepository) {
        this.postRepository = postRepository;
    }

    @EventHandler
    public void on(PostCreatedEvent event) {
        Post post = new Post(event.getId(), event.getTitle(), event.getContent());
        postRepository.save(post);
    }
}
// Post.java (Entity)
@Entity
public class Post {

    @Id
    private String id;
    private String title;
    private String content;

    public Post(String id, String title, String content) {
        this.id = id;
        this.title = title;
        this.content = content;
    }

    // Getters and setters ...
}
// PostRepository.java
public interface PostRepository extends JpaRepository<Post, String> {
}
// PostController.java
@RestController
@RequestMapping("/api/posts")
public class PostController {

    private final CommandGateway commandGateway;
    private final PostRepository postRepository;

    public PostController(CommandGateway commandGateway, PostRepository postRepository) {
        this.commandGateway = commandGateway;
        this.postRepository = postRepository;
    }

    @PostMapping
    public CompletableFuture<String> createPost(@RequestBody PostRequest postRequest) {
        String postId = UUID.randomUUID().toString();
        return commandGateway.send(new CreatePostCommand(postId, postRequest.getTitle(), postRequest.getContent()));
    }

    @GetMapping
    public List<Post> getAllPosts() {
        return postRepository.findAll();
    }
}
// PostRequest.java
public class PostRequest {

    private String title;
    private String content;

    // Getters and setters ...
}

5. 게시판 프로젝트 실행

6. AxonFramework와 Kafka 실행

  • kafka 시작
  • kafka를 설치 하지 않았다면(https://kafka.apache.org/)에서 kafka를 다운로드 하고 압축해제
  • 터미널 실행하여 kafka 설치 폴더로 이동
  • maxOS 기준(bin/zookeeper-server-start.sh config/zookeeper.properties)
  • 터미널 실행 2
  • maxOS 기준(bin/kafka-server-start.sh config/server.properties)
  • Spring Boot 애플리케이션을 시작합니다(예: 기본 클래스를 실행하거나 Maven의 경우 ./mvnw spring-boot:run 또는 Gradle의 경우 ./gradlew bootRun 사용).
  • Postman 또는 CURL과 같은 REST 클라이언트를 사용하여 포스트 생성 및 가져오기를 위한 /api/posts 엔드포인트를 테스트합니다.
  • AxonServer 다운로드: 공식 웹 사이트에서 AxonServer의 최신 릴리스를 다운로드합니다: https://axoniq.io/product-overview/axon-server. “Axon Server Standard Edition”을 선택하고 .jar 파일을 다운로드합니다.
  • AxonServer 실행: 터미널(또는 Windows의 경우 명령 프롬프트)을 열고 AxonServer .jar 파일을 다운로드한 디렉터리로 이동합니다. 다음 명령을 실행하여 AxonServer를 시작합니다.
java -jar axonserver.jar

기본적으로 AxonServer는 포트 8124에서 수신 대기합니다. 게시판 애플리케이션이 작동하려면 AxonServer가 백그라운드에서 실행 중이어야 하므로 터미널이 계속 실행되도록 허용하십시오.

애플리케이션 속성 업데이트: application.properties 파일의 axon.axonserver.servers 속성이 올바른 AxonServer 주소 및 포트(기본적으로 localhost:8124)를 가리키는지 확인하십시오. 아직 추가하지 않은 경우 application.properties 파일에 다음 행을 추가하십시오.(이미 추가하였음, 혹시 지웠다면 추가)

이렇게 AxonFramework와 Kafka를 활용한 Spring Boot 게시판 서비스 구현하기를 진행해 보았습니다. 다음 포스에서는 AxonFramework와 Kafka에 대해 더 많은 정보를 다루어 볼 예정이니 많은 관심 부탁드립니다.

[wooyung’s IT 블로그]

[2023] AXON Framework를 활용한 CQRS와 Event Sourcing 구현 방법

AXON Framework

안녕하세요! 오늘은 Java의 훌륭한 프레임워크인 AXON을 이용하여 CQRS(Command Query Responsibility Segregation)와 Event Sourcing을 어떻게 구현하는지 알아보겠습니다.

AXON 소개

AXON CQRS와 Event Sourcing을 지원하는 Java 기반의 프레임워크입니다. 복잡한 비즈니스 로직을 효과적으로 모델링하고, 확장성과 획일성을 동시에 제공하는 마이크로서비스 아키텍처를 구현하는 데 매우 유용합니다.

AXON 설정하기

AXON을 사용하기 위해 첫 번째 단계는 종속성을 추가하는 것입니다. Maven 기반의 프로젝트에서는 pom.xml에 아래 내용을 추가해 Framework를 프로젝트에 포함시킵니다.

<code>
  <dependency>
      <groupId>org.axonframework</groupId>
      <artifactId>axon-spring-boot-starter</artifactId>
      <version>4.6.3</version>
  </dependency>
</code>

명령과 이벤트 객체 생성하기

다음 단계는 명령(Command)과 이벤트(Event) 객체를 생성하는 것입니다. 이 객체들은 AXON Framework에서 CQRS와 Event Sourcing을 구현하는 핵심적인 부분입니다. 명령은 시스템의 상태를 변경하는 요청을 나타내고, 이벤트는 시스템의 상태 변경을 나타내는 객체입니다.

<code>
  public class CreateOrderCommand {
      //...
  }
  
  public class OrderCreatedEvent {
      //...
  }
</code>

AXON Framework와 Spring Framework 통합하기

AXON은 Spring Framework와 잘 통합되도록 설계되었습니다. 따라서 Spring의 @Configuration을 이용하여 AXON의 설정을 완료하고, Aggregate와 Command Handler를 Spring Bean으로 등록합니다.

이제 준비된 구현을 JUnit을 이용해 테스트할 수 있습니다. 이를 통해 AXON Framework를 활용한 CQRS와 Event Sourcing 구현이 정확히 작동하는지 확인할 수 있습니다.

결론적으로, AXON은 복잡한 비즈니스 요구 사항을 처리하는 데 매우 유용한 도구입니다. 이 프레임워크를 활용하면 복잡한 시스템도 우아하게 설계하고 구현할 수 있습니다. 다음 포스트에서는 AXON Framework의 더 많은 기능과 사용법에 대해 알아보겠습니다. 그럼 다음에 뵙겠습니다!

[wooyung’s IT 블로그]

[2023] 세 가지 핵심 자바 플랫폼에 대해 알아보자: Java SE, EE, ME

자바 플랫폼

안녕하세요, 오늘은 자바(Java)에 대해 다뤄볼까 합니다. 자바는 현대에서 가장 강력하고 널리 사용되는 프로그래밍 언어 중 하나입니다.

자바는 그 세계를 표준 에디션(Java SE), 엔터프라이즈 에디션(Java EE), 마이크로 에디션(Java ME)이라는 세 가지 주요 플랫폼으로 나눕니다.

이 세 가지 자바 플랫폼이 갖는 각각의 특징과 장점을 이해하는 것은 자바를 활용하는 개발자에게 매우 중요합니다.

그럼 이 세 가지 자바 플랫폼에 대해 알아볼까요?

자바 플랫폼

Java SE(Standard Edition)

자바 플랫폼의 핵심을 이루며, 가장 일반적인 사용 사례를 지원합니다. 이것은 우리가 일반적으로 ‘자바’라고 이해하는 대부분의 패키지와 라이브러리를 포함하고 있습니다.

Java SE의 API는 다양한 애플리케이션 개발을 가능하게 하는 자바 프로그래밍 언어의 핵심 기능을 제공합니다.

또한 가상 머신, 개발 도구, 배포 기술 등을 제공하여 개발자들이 보다 편리하게 작업할 수 있게 지원합니다.

Java EE (Enterprise Edition)

기업 환경에서의 대규모 애플리케이션 개발을 지원하는 플랫폼입니다.

Java SE를 기반으로 하되, 웹 프로그래밍과 대규모, 다계층 시스템의 확장성, 신뢰성, 보안 등에 필요한 기능을 추가로 제공합니다.

네트워킹 API와 환경 설정 기능을 통해 기업이 자신들의 요구에 맞는 애플리케이션을 개발하고 배포하는데 도움이 됩니다.

Java ME (Micro Edition)

작은 장치에서 실행되는 애플리케이션을 개발하기 위한 플랫폼입니다.

모바일 폰과 같은 장치에서 사용되는 소형 가상 머신을 지원합니다.

Java SE의 기반 위에 작은 장치에서 동작하는 전용 클래스 라이브러리를 제공하며, Java EE 서비스의 클라이언트 역할을 하기도 합니다.

이 세 가지 플랫폼을 이해하는 것은 자바 프로그래밍에 깊이를 더하고, 다양한 환경과 요구 사항에 맞는 최상의 솔루션을 선택하는 데 도움이 됩니다.

각 플랫폼은 자바의 유연성과 다양성을 보여주며, 각각의 환경과 요구 사항에 적합한 고유한 기능과 장점을 제공합니다.

개발자로서, 이 세 가지 플랫폼을 이해하고 활용하는 능력은 자바 프로그래밍 능력을 향상시키고, 다양한 애플리케이션과 솔루션을 만드는 데 필요한 도구를 제공합니다.

자바는 이 세 가지 주요 플랫폼을 통해 다양한 환경과 요구 사항에 대응할 수 있으며, 이는 개발자에게 매우 중요한 역량입니다.

이로써, 자바의 세 가지 자바 플랫폼인 Java SE, EE, ME에 대한 기본적인 이해를 제공하였습니다.

이들 각각이 어떻게 구성되어 있고 어떻게 작동하는지를 이해하면, 개발자로서 어떤 상황에서 어떤 플랫폼을 선택할지 결정하는 데 도움이 될 것입니다.

이 글이 자바 개발자가 되려는 분들에게 도움이 되었기를 바랍니다. 다음 글에서는 더 깊이 있는 자바 주제에 대해 다룰 예정입니다. 그럼, 행복한 코딩 되세요!

[oracle 공식 문서]

[wooyung’s IT 블로그]

[2023] Java Servlet이란 무엇인가?

Java Servlet

Java Servlet은 웹 페이지를 동적으로 생성하는 서버측 프로그램입니다. 자바를 기반으로 동작하며, 클라이언트의 요청에 따라 동적인 웹페이지를 생성하는 WAS(Web Application Server)의 주요 구성 요소 중 하나입니다.

Java Servlet 이란?

Servlet은 웹 서버 내에서 동작하는 Java 클래스입니다. 이 클래스는 HTTP 프로토콜을 통해 클라이언트의 요청을 받아 처리하고 결과를 클라이언트에게 반환합니다. 이 과정에서 정적인 페이지를 제공하는 웹 서버와 달리, 사용자의 입력에 따라 동적으로 웹 페이지를 생성하는 것이 가능합니다.

Servlet의 동작 원리

Servlet의 동작 원리를 이해하기 위해 우선 사용자의 요청에서 서블릿의 제거까지의 전체적인 흐름을 살펴봅시다.

1. 사용자 요청

먼저 사용자는 웹 브라우저를 통해 원하는 데이터를 요청합니다. 이 요청은 HTTP를 통해 이루어지며, 요청 받은 웹 서버는 이를 분석하여 정적인 페이지 요청인 경우 바로 처리하고, 동적인 페이지에 대한 요청인 경우 웹 컨테이너(서블릿 컨테이너)로 넘깁니다.

2. HttpServletRequest, HttpServletResponse 객체 생성

서블릿 컨테이너는 이어서 HttpServletRequest와 HttpServletResponse 객체를 생성합니다. HttpServletRequest 객체는 클라이언트의 요청 정보를 담고, HttpServletResponse 객체는 요청 처리 결과를 담습니다. 이 두 객체는 서블릿이 클라이언트와 통신하는데 필요한 모든 정보를 포함합니다.

3. web.xml 파싱

서블릿 컨테이너는 요청 정보를 바탕으로 web.xml, 즉 서블릿의 배포 서술자를 파싱합니다. web.xml 파일은 서블릿의 위치와 URL 매핑 정보 등을 담고 있어, 서블릿 컨테이너가 요청을 처리할 적절한 서블릿을 찾는데 도움을 줍니다.

4. 서블릿 초기화

이제 서블릿 컨테이너는 찾아낸 서블릿을 초기화합니다. 이 과정에서 서블릿 클래스가 로드되고 인스턴스가 생성되며, 이 인스턴스를 통해 서블릿의 init() 메서드가 호출됩니다. 서블릿 인스턴스는 싱글톤 패턴을 따르며, 따라서 서블릿의 생명 주기 동안 단 한 번만 생성됩니다.

5. service() 실행

초기화가 완료되면, 서블릿 컨테이너는 클라이언트의 요청을 처리하기 위해 서블릿의 service() 메서드를 호출합니다. 이 메서드는 doGet() 또는 doPost()와 같은 메서드를 호출하여 실제로 클라이언트의 요청을 처리합니다.

6. destroy() 실행

마지막으로, 서블릿 컨테이너는 더 이상 서블릿이 필요하지 않다고 판단하면 destroy() 메서드를 호출하여 서블릿을 제거합니다. 이는 서버가 종료되거나 오랫동안 사용되지 않는 서블릿에 대해 일어납니다.

Servlet의 특징과 장점

Servlet은 상태 유지를 지원하며, 쓰레드 방식으로 동작하기 때문에 효율적인 자원 사용이 가능합니다. 또한, 서블릿은 서버 측에서 동작하기 때문에 보안성이 높습니다.

Java Servlet은 웹 서버의 확장성을 향상시키는 데 중요한 역할을 합니다. 또한, 동적인 웹 페이지 생성과 데이터 처리를 위한 강력한 도구입니다. 이러한 이해를 바탕으로, 자바 기반의 웹 애플리케이션 개발에 있어서 중요한 역할을 합니다.

[spring 공식 문서]

[wooyung’s IT 블로그]