Multi-tenancy Architecture
- 여러 사용자가 하나의 시스템을 공유하면서도,각자의 데이터를 독립적으로 관리할 수 있도록 하는 아키텍처 (tenant : 거주자)
1. Shared Database, Shared Schema (1 DB, 1 schema)
- 동일한 DB 사용
- table을 사용자별로 구분
- 같은 DB 안에 여러 tenant 존재
- 시작 단계의 소규모 SaaS에서 유용
2. Shared Database, Seperate Schema (1 DB, n schema)
- 동일한 DB 사용
- tenant마다 다른 schema를 사용하여 데이터 분리
- SaaS (Software as a Service)
3. n DB, d schema
- 각 사용자가 자신만의 DB를 가짐
- 사용자가 접속할 때마다 고유한 DB 사용
- 각 사용자가 독립적인 DB를 가질 수 있어, 데이터 간섭 없이 각 사용자의 데이터를 독립적으로 관리
- 고객 맞춤형 SaaS(보안 요구 사항이 매우 높은 경우 등)에서 유용
사용자마다 DB 분리하는 방법
동적 데이터 소스 변경
- AbstractRountingDataSource -> 동적으로 데이터 소스 선택
- 사용자의 sessionId나 기타 식별자를 기준으로 적잘한 DB 선택
- DataSourceRouting 설정
public class DataSourceRouting extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
// 사용자별로 다르게 DB를 선택하는 로직
String userId = SessionUtils.getUserId(); // 세션 또는 다른 기준으로 사용자 ID를 가져옴
return userId;
}
}
- DynamicDataSourceConfig 설정
@Configuration
public class DynamicDataSourceConfig {
@Bean
public DataSource dataSource() {
DataSourceRouting dataSourceRouting = new DataSourceRouting();
Map<Object, Object> dataSourceMap = new HashMap<>();
// DB 설정 예시: 여러 개의 DB 연결을 설정
DataSource userDb1 = createDataSource("jdbc:mysql://localhost:3306/userdb1", "user", "password");
DataSource userDb2 = createDataSource("jdbc:mysql://localhost:3306/userdb2", "user", "password");
dataSourceMap.put("user1", userDb1);
dataSourceMap.put("user2", userDb2);
dataSourceRouting.setTargetDataSources(dataSourceMap);
dataSourceRouting.setDefaultTargetDataSource(userDb1); // 기본 DB 설정
return dataSourceRouting;
}
private DataSource createDataSource(String url, String username, String password) {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
- SessionUtils
public class SessionUtils {
public static String getUserId() {
// 세션에서 사용자 ID를 가져오는 방법
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return (String) request.getSession().getAttribute("userId");
}
}
각 DB에 대한 설정
- 사용자가 처음 로그인할 때 해당 사용자의 DB를 생성하거나 연결
동적 DB 변경에 따른 트랜잭션 관리
- 각 DB마다 별도로 트랜잭션을 관리할 수 있도록 설정