스프링 Spring
23. Spring Boot에서 Multi-Tenancy 아키텍처 구현
안녕하세요! 태마입니다.
Spring 기초 강좌입니다.
강좌의 경우
1. 주제 간단 정리
2. 상세 주제 정리
으로 이루어져 있습니다.
스프링 Spring
포스팅 시작하겠습니다 :)
1. 주제 간단 정리
1. Multi-Tenancy(멀티 테넌시)란?
✔ Multi-Tenancy(멀티 테넌시)는 하나의 애플리케이션이 여러 개의 테넌트(Tenant)를 지원하는 아키텍처
✔ 각 테넌트는 독립적인 데이터를 유지하면서도 동일한 애플리케이션을 공유 가능
📌 Multi-Tenancy의 주요 특징
여러 고객(테넌트)이 하나의 애플리케이션을 공유 | 동일한 코드베이스에서 여러 개의 데이터를 분리하여 운영 가능 |
독립적인 데이터 저장 | 테넌트마다 별도의 데이터베이스 또는 스키마를 유지 |
보안 및 격리 | 각 테넌트의 데이터는 서로 접근할 수 없음 |
유지보수 비용 절감 | 여러 고객을 하나의 애플리케이션에서 관리 가능 |
📌 멀티 테넌시는 "SaaS(Software as a Service) 모델에서 필수적인 아키텍처"
2. Single-Tenancy vs Multi-Tenancy 비교
✔ Single-Tenancy는 각 고객마다 개별 애플리케이션을 운영하고, Multi-Tenancy는 하나의 애플리케이션을 공유
📌 Single-Tenancy vs Multi-Tenancy 비교
애플리케이션 | 각 고객마다 개별 운영 | 하나의 애플리케이션을 공유 |
데이터 저장 방식 | 각 고객별 개별 데이터베이스 | 하나의 데이터베이스에서 고객별 데이터 분리 |
운영 비용 | 높음 (고객별 관리 필요) | 낮음 (하나의 시스템 관리) |
보안 및 격리 | 높은 보안 (고객별 분리) | 데이터 격리를 추가적으로 고려해야 함 |
적용 사례 | 금융, 엔터프라이즈 시스템 | SaaS 기반 서비스 (Slack, Shopify, Salesforce 등) |
📌 Multi-Tenancy를 사용하면 "비용을 절감하고 하나의 시스템으로 여러 고객을 지원 가능"
✅ 여기까지 Multi-Tenancy의 개념과 필요성을 배웠습니다!
👉 "그렇다면, Spring Boot에서 Multi-Tenancy를 어떻게 구현할까?"
✅ 2부에서 Spring Boot에서 Multi-Tenancy 아키텍처를 적용하는 방법을 배워봅시다!
2. 상세 주제 정리
1. Multi-Tenancy를 적용하는 방식
✔ Spring Boot에서 Multi-Tenancy를 적용하는 방법은 크게 3가지가 있음
📌 Multi-Tenancy 적용 방식
Separate Database | 테넌트마다 개별 데이터베이스 사용 | 데이터 격리 보장 | 비용 증가, 관리 복잡 |
Shared Database, Separate Schema | 하나의 데이터베이스에서 테넌트별 스키마 사용 | 데이터 격리 가능, 성능 최적화 | 복잡한 쿼리 관리 필요 |
Shared Database, Shared Schema | 하나의 데이터베이스에서 테넌트별 컬럼으로 구분 | 운영 비용 절감, 유지보수 용이 | 보안 및 성능 문제 가능 |
📌 SaaS 환경에서는 주로 "Shared Database, Separate Schema" 방식이 많이 사용됨
2. Multi-Tenancy 적용 (테넌트별 데이터베이스 분리 방식)
✔ 각 테넌트별로 별도의 데이터베이스를 유지하는 방식 구현
📌 1️⃣ Multi-Tenant DataSource 설정
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import java.util.Map;
public class MultiTenantDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return TenantContext.getCurrentTenant(); // 현재 테넌트 가져오기
}
public void setTenantDataSources(Map<Object, Object> dataSources) {
super.setTargetDataSources(dataSources);
super.afterPropertiesSet();
}
}
✔ determineCurrentLookupKey()를 통해 현재 테넌트의 데이터베이스 선택
📌 2️⃣ TenantContext (현재 테넌트 식별)
public class TenantContext {
private static final ThreadLocal<String> currentTenant = new ThreadLocal<>();
public static void setCurrentTenant(String tenantId) {
currentTenant.set(tenantId);
}
public static String getCurrentTenant() {
return currentTenant.get();
}
public static void clear() {
currentTenant.remove();
}
}
✔ 각 요청마다 ThreadLocal을 사용하여 현재 테넌트를 관리
📌 3️⃣ Multi-Tenant Filter (테넌트 식별 필터 추가)
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
public class TenantFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String tenantId = httpServletRequest.getHeader("X-Tenant-ID"); // 헤더에서 테넌트 ID 가져오기
TenantContext.setCurrentTenant(tenantId);
try {
chain.doFilter(request, response);
} finally {
TenantContext.clear();
}
}
}
✔ 클라이언트가 X-Tenant-ID 헤더를 보내면 해당 테넌트의 데이터베이스를 사용
📌 4️⃣ DataSource 설정 (다중 데이터베이스 지원)
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfig {
@Bean
public DataSource multiTenantDataSource(@Qualifier("tenant1DataSource") DataSource tenant1DataSource,
@Qualifier("tenant2DataSource") DataSource tenant2DataSource) {
MultiTenantDataSource dataSource = new MultiTenantDataSource();
Map<Object, Object> dataSources = new HashMap<>();
dataSources.put("tenant1", tenant1DataSource);
dataSources.put("tenant2", tenant2DataSource);
dataSource.setTenantDataSources(dataSources);
return dataSource;
}
@Bean(name = "tenant1DataSource")
public DataSource tenant1DataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/tenant1_db")
.username("user1")
.password("password1")
.build();
}
@Bean(name = "tenant2DataSource")
public DataSource tenant2DataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/tenant2_db")
.username("user2")
.password("password2")
.build();
}
}
✔ 각 테넌트에 대한 데이터베이스 연결을 설정하고, 동적으로 테넌트별 데이터베이스를 선택
📌 Multi-Tenancy를 적용하면 "하나의 애플리케이션에서 여러 고객을 분리하여 운영 가능"
✅ 여기까지 Spring Boot에서 Multi-Tenancy 아키텍처 구현 방법을 배웠습니다!
👉 "그렇다면, Spring Boot에서 Kafka 이벤트 스트리밍 시스템 구축은 어떻게 할까?"
✅ 다음 회차에서 Spring Boot에서 Kafka 이벤트 스트리밍 시스템 구축을 배워봅시다!
'IT Developer > Spring' 카테고리의 다른 글
Spring 기초 <27. Spring Boot에서 트랜잭션 관리 최적화 (@Transactional, REQUIRES_NEW)> (1) | 2025.04.13 |
---|---|
Spring 기초 <26. JPA + QueryDSL을 활용한 복잡한 쿼리 최적화> (0) | 2025.04.12 |
Spring 기초 <25. Spring Boot에서 GraphQL API 개발 (Spring GraphQL)> (0) | 2025.04.11 |
Spring 기초 <24. Spring Boot에서 Kafka 이벤트 스트리밍 시스템 구축> (0) | 2025.04.10 |
Spring 기초 <22. Spring Security에서 RBAC(Role-Based Access Control) 적용> (1) | 2025.04.08 |
Spring 기초 <21. Spring Boot에서 웹소켓(WebSocket)과 실시간 데이터 처리> (1) | 2025.04.07 |
Spring 기초 <20. Spring WebFlux와 비동기 프로그래밍 (Reactor, Mono, Flux 개념)> (1) | 2025.04.06 |
Spring 기초 <19. Spring Boot에서 API Gateway 및 Rate Limiting 설정 (Rate Limiter)> (0) | 2025.04.05 |