[MSA] 영속성 계층의 개념과 질문

min.c00·2023년 4월 6일
0

MSA + Spring Boot

목록 보기
3/7
post-thumbnail

영속성 계층의 개념과 질문


이책은 스프링으로 하는 마이크로서비스 구축(스프링 부트와 스프링 클라우드를 이용한 도커/쿠버네티스 마이크로서비스) 책을 읽고 학습한 내용을 정리한 글입니다.

목차


  1. MSA에서 영속성 계층의 개념
  2. 영속성 계층에 대한 질문과 답변
  3. 영속성 계층에 대한 정리

1. MSA에서 영속성 계층의 개념


  • 영속성 계층이란?

💡 MSA (Microservices Architecture)에서 "영속성 계층"은 데이터베이스와 같은 영구 저장소를 의미합니다. MSA에서 각 마이크로서비스는 독립적으로 구성되어 작동하며, 따라서 데이터를 관리하기 위해 각 서비스는 자체적으로 데이터를 저장하고 검색할 수 있어야 합니다. 이 때 각 마이크로서비스가 데이터를 저장하고 검색할 수 있는 저장소를 "영속성 계층"이라고 부릅니다.

영속성 계층은 MSA 아키텍처의 중요한 요소 중 하나입니다. 각 마이크로서비스는 데이터를 다른 서비스와 공유할 필요가 없기 때문에, 이 계층을 통해 서로 다른 저장소에 데이터를 저장하고 검색할 수 있습니다. 이를 통해 마이크로서비스 간 결합도를 줄이고, 각 서비스가 독립적으로 관리될 수 있는 환경을 제공합니다.

여기서 "각 마이크로서비스는 데이터를 다른 서비스와 공유할 필요가 없기 때문에" 에 대해 저는 궁굼했습니다


2. 영속성 계층에 대한 질문과 답변


  • 질문1 : 왜 마이크로서비스는 데이터를 다른 서비스와 공유할 필요가 없는가?

💡 MSA는 각 마이크로서비스가 독립적으로 구성되어 작동하는 아키텍처입니다. 이는 각 마이크로서비스가 서로 다른 업무를 수행하고, 서로 다른 데이터를 처리하기 때문에, 다른 서비스와 데이터를 공유할 필요가 없다는 의미입니다.

예를 들어, 전자상거래 웹사이트를 운영하는 MSA 환경에서는 주문 관리, 결제 처리, 상품 검색 등의 기능을 각각의 마이크로서비스로 분리할 수 있습니다. 각 마이크로서비스는 서로 다른 역할을 수행하므로, 서로 다른 데이터를 처리하고 저장할 필요가 있습니다.

따라서, 각 마이크로서비스는 자체적으로 데이터를 저장하고 검색할 수 있어야 합니다. 이 때, 각 마이크로서비스가 서로 다른 데이터를 공유할 필요가 없으므로, 각각의 마이크로서비스는 자체적인 데이터 저장소를 가지고 있게 됩니다.

이러한 독립적인 마이크로서비스 아키텍처는 시스템 전체가 더욱 견고하고 확장 가능한 구조를 가지게 되며, 각각의 마이크로서비스는 독립적으로 개발, 배포, 관리될 수 있게 됩니다.

📌 MSA 아키텍처 목표중 하나는 느슨한 결합서비스간 독립성을 유지할 수 있는 설계를 해야한다.


  • 질문2 : MSA에서 각 서비스의 영속성 계층 즉, 데이터 저장소에서 관리하는 테이블의 중복을 최소화하는 것이 가장 이상적인 설계인가?

💡 각 데이터 저장소에서 관리하는 테이블의 중복을 최소화하면 데이터 일관성과 결합도를 낮출 수 있습니다. 하지만 모든 경우에서 중복을 최소화하는 것이 최선인 것은 아닙니다.

예를 들어, 여러 마이크로서비스가 동시에 동일한 데이터를 필요로 하는 경우에는 중복(테이블의 중복)을 허용하고, 중복된 데이터를 동기화하는 방식으로 구현하는 것이 더 나을 수 있습니다.

따라서, 각 마이크로서비스에서 필요한 데이터를 관리하면서 중복을 최소화하고, 동기화가 필요한 경우에는 적절한 방법으로 데이터를 공유하면서도, 마이크로서비스 아키텍처의 목표인 느슨한 결합도와 서비스 간 독립성을 유지할 수 있는 설계가 중요합니다.

📌 데이터 저장소에서 관리하는 테이블의 중복을 최소화하는 것이 항상 이상적인 것은 아니다.


  • 질문3 : 중복된 데이터를 동기화하는 구체적인 방법은 뭘까?

💡 Spring Boot에서 각 마이크로서비스의 데이터 저장소에 테이블의 중복이 필연적이라면, 중복된 데이터를 동기화하는 방법으로는 데이터베이스 복제(Database Replication) 기능을 사용할 수 있습니다.

데이터베이스 복제는 마스터 데이터베이스에서 변경된 데이터를 슬레이브 데이터베이스로 전달하는 과정을 말합니다. 슬레이브 데이터베이스는 마스터 데이터베이스에서 변경된 데이터를 복제하여 동일한 데이터를 가지게 됩니다. 이를 통해 중복된 데이터를 동기화할 수 있습니다.

Spring Boot에서는 JPA와 Hibernate를 사용하여 데이터베이스를 다룰 수 있습니다. JPA는 데이터베이스 복제를 지원하는 기능을 제공하지 않지만, Hibernate는 데이터베이스 복제를 지원하는 기능을 제공합니다. Hibernate를 사용하여 데이터베이스 복제를 설정하는 방법은 다음과 같습니다.

  1. Hibernate 설정 파일에 다음과 같이 설정합니다.
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto=update
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/testdb
hibernate.connection.username=root
hibernate.connection.password=root
hibernate.connection.provider_class=org.hibernate.connection.C3P0ConnectionProvider
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50
hibernate.c3p0.idle_test_period=1800
hibernate.connection.isolation=2
hibernate.cache.use_second_level_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
hibernate.cache.use_query_cache=true
hibernate.cache.use_minimal_puts=true
hibernate.jdbc.batch_size=100
hibernate.order_inserts=true
hibernate.order_updates=true
hibernate.jdbc.batch_versioned_data=true
hibernate.generate_statistics=true
hibernate.cache.use_structured_entries=true
hibernate.current_session_context_class=thread
hibernate.connection.release_mode=auto
  1. 데이터베이스에서 마스터 데이터베이스와 슬레이브 데이터베이스를 설정합니다. 슬레이브 데이터베이스는 마스터 데이터베이스와 동일한 스키마를 사용해야 합니다.

  2. Hibernate 설정 파일에 다음과 같이 복제 관련 설정을 추가합니다.

hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto=update
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/testdb
hibernate.connection.username=root
hibernate.connection.password=root
hibernate.connection.provider_class=org

  • 질문4 : 각 마이크로서비스 별로 데이터베이스를 따로 만들었을 때 각 데이터베이스에 동일한 이름의 테이블이 물리적으로 생성됬을 경우가 존재할 수 있을까?

💡 각 마이크로서비스에서 동일한 이름의 테이블을 물리적으로 생성하는 것은 피해야 합니다. 이는 데이터 일관성을 유지하기 어렵게 만들기 때문입니다.

그러나 이미 동일한 이름의 테이블이 생성되어 있다면, 각 데이터베이스에서 해당 테이블을 동기화하는 것이 가능합니다.

동기화를 위해서는 각 데이터베이스에서 해당 테이블을 공유하는 공통 데이터베이스를 두어야 합니다. 이 공통 데이터베이스는 각 데이터베이스에서 발생하는 변경 사항을 적용할 수 있도록 설정되어 있어야 합니다. 이를 위해 스키마를 일치시키고 데이터의 일관성을 유지할 수 있는 방법으로는 Master-Slave 복제, Master-Master 복제, 클러스터링 등이 있습니다.

Spring Boot에서는 JPA를 사용하여 각 데이터베이스에 접근합니다. JPA에서는 트랜잭션을 사용하여 데이터 일관성을 유지합니다. 트랜잭션을 사용하면 데이터베이스 간의 일관성을 유지하기 위해 커밋이나 롤백 등의 작업이 필요합니다.

아래는 각 데이터베이스에서 동일한 이름의 테이블을 공유하는 방법의 예시이다.

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    @Transactional
    public void saveUser(User user) {
        userRepository.save(user);

        String sql = "INSERT INTO common_database.user(id, name, email) VALUES(?, ?, ?)";
        jdbcTemplate.update(sql, user.getId(), user.getName(), user.getEmail());
    }
}

위 코드에서는 UserServiceImpl 클래스에서 UserRepository를 사용하여 각 마이크로서비스의 데이터베이스에 User 정보를 저장하고, JdbcTemplate을 사용하여 공통 데이터베이스의 user 테이블에도 저장합니다. 이때, @Transactional 어노테이션을 사용하여 트랜잭션을 관리하고, 데이터 일관성을 유지합니다.


  • 질문5 : 예를들어 RDBMS를 설계했을 때 두개의 MSA중 첫번째는 회원 정보 관리를 위해 데이터 저장소에 회원테이블을 두고, 두 번째는 상품 정보 관리를 담당하기 위해 상품 테이블을 두고 MSA를 설계했을 경우 각 테이블을 "Join"하고 싶은 경우는 어떻게 처리할까?

💡 MSA에서 각 마이크로서비스가 독립적인 데이터 저장소를 가지고 있기 때문에, 다른 마이크로서비스의 데이터에 직접 접근하여 Join을 수행하는 것은 불가능합니다.

이 경우 각 마이크로서비스에서 필요한 데이터를 API를 통해 제공하고, 필요한 경우 클라이언트에서 Join을 수행하는 것이 이상적입니다.

예를 들어, 첫 번째 마이크로서비스에서는 회원 정보를 제공하는 API를 제공하고, 두 번째 마이크로서비스에서는 상품 정보를 제공하는 API를 제공합니다. 이때 클라이언트에서는 두 API를 호출하여 필요한 데이터를 가져와 Join을 수행할 수 있습니다.

Spring Boot에서는 이러한 API를 쉽게 개발할 수 있는 방법을 제공합니다. 각 마이크로서비스는 Spring Data JPA를 사용하여 자신의 데이터 저장소에 접근하고, Spring MVC를 사용하여 RESTful API를 제공할 수 있습니다. 또한, 필요한 경우 Spring Cloud Netflix의 Eureka나 Consul과 같은 서비스 디스커버리 툴을 이용하여 마이크로서비스의 위치를 파악하고 호출할 수 있습니다.


3. 영속성 계층에 대한 정리


Spring Boot에서는 다양한 데이터베이스와 연동할 수 있는 방법을 제공합니다. MSA에서는 각 마이크로서비스별로 독립적인 데이터베이스를 사용하므로, Spring Boot에서는 이를 위해 데이터베이스 커넥션을 분리할 수 있는 방법을 제공합니다.

일반적으로 Spring Boot에서는 JPA(Java Persistence API)와 Hibernate를 사용하여 데이터베이스와 연동합니다. 이를 이용하여 각 마이크로서비스에서 필요한 데이터 모델을 정의하고, 데이터베이스에 테이블을 생성할 수 있습니다. 각 마이크로서비스에서 사용하는 데이터베이스는 서로 다른 데이터베이스를 사용하므로, 테이블 이름이 중복되지 않도록 지정해야 합니다.

또한, 각 마이크로서비스에서 필요한 데이터를 조회하기 위해 다른 마이크로서비스의 데이터베이스에 접근하는 것은 지양해야 합니다. 대신, 각 마이크로서비스의 API를 통해 데이터를 요청하고, 필요한 경우 데이터를 복제하여 로컬 데이터베이스에 저장하는 방법을 사용할 수 있습니다.

마지막으로, 데이터베이스 스키마의 변경이나 데이터베이스 업그레이드를 수행할 때에는 각 마이크로서비스에서 독립적으로 수행할 수 있도록 마이그레이션 스크립트를 작성하고, 버전 관리 시스템을 이용하여 관리하는 것이 좋습니다.

이러한 방법을 통해 Spring Boot에서도 MSA의 느슨한 결합을 실현할 수 있으며, 각 마이크로서비스에서 독립적으로 데이터 저장소를 설계하고 관리할 수 있습니다.

0개의 댓글