PHP 8과 Laravel을 활용한 멀티 테넌트(Multi-Tenant) 애플리케이션 개발
멀티 테넌트(Multi-Tenant) 아키텍처는 하나의 애플리케이션 인스턴스에서 여러 개의 고객(테넌트)을 지원하는 방식입니다. 이를 통해 인프라 비용 절감, 유지보수 편의성, 데이터 격리를 제공할 수 있습니다.
Laravel은 PHP 8의 최신 기능과 결합하여 멀티 테넌트 환경을 구축하는 데 강력한 도구를 제공합니다. 이 글에서는 멀티 테넌트 애플리케이션의 개념, 구현 전략, 그리고 Laravel에서의 실전 적용 방법을 다룹니다.
1. 멀티 테넌트 애플리케이션이란?
멀티 테넌트 아키텍처는 하나의 애플리케이션에서 여러 개의 독립적인 사용자 그룹(테넌트)이 자신의 데이터를 관리할 수 있도록 설계된 방식입니다.
1.1 멀티 테넌트 유형
1. 데이터베이스 공유 (Single Database, Shared Schema)
• 모든 테넌트가 동일한 데이터베이스를 사용하며, 테이블에서 tenant_id를 통해 구분
• 비용이 적게 들며, 간단한 구현 가능
2. 스키마 분리 (Single Database, Multiple Schemas)
• 하나의 데이터베이스 안에서 테넌트별로 스키마를 분리
• 데이터 격리 및 보안 강화
3. 데이터베이스 분리 (Multiple Databases)
• 테넌트마다 별도의 데이터베이스를 사용
• 높은 보안성 및 독립성 제공
2. Laravel에서 멀티 테넌트 아키텍처 구현 전략
Laravel에서는 다음과 같은 방법으로 멀티 테넌트 애플리케이션을 구현할 수 있습니다.
2.1 테넌트 식별 방법
테넌트를 식별하기 위해 일반적으로 다음의 방법을 사용합니다.
1. 서브도메인 기반 식별 (tenant1.example.com)
2. URL 경로 기반 식별 (example.com/tenant1)
3. 사용자 로그인 기반 식별 (Auth 정보 활용)
2.2 서브도메인을 통한 테넌트 구분
1) 미들웨어를 이용한 테넌트 식별
namespace App\Http\Middleware;
use Closure;
use App\Models\Tenant;
class IdentifyTenant {
public function handle($request, Closure $next) {
$host = $request->getHost(); // example: tenant1.example.com
$subdomain = explode('.', $host)[0];
$tenant = Tenant::where('subdomain', $subdomain)->first();
if (!$tenant) {
abort(404, '테넌트를 찾을 수 없습니다.');
}
app()->instance('tenant', $tenant);
return $next($request);
}
}
미들웨어 등록:
// app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\IdentifyTenant::class,
],
];
라우트 설정:
Route::middleware('IdentifyTenant')->group(function () {
Route::get('/dashboard', function () {
$tenant = app('tenant');
return "Welcome to " . $tenant->name;
});
});
2.3 데이터베이스 공유 모델 (Shared Schema) 설정
모든 테넌트가 동일한 데이터베이스를 사용하고, tenant_id 컬럼을 추가하여 구분합니다.
1) 마이그레이션 수정
Schema::create('projects', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('tenant_id');
$table->string('name');
$table->timestamps();
});
2) 모델 수정 (Global Scope 적용)
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Project extends Model {
protected static function booted() {
static::addGlobalScope('tenant', function (Builder $builder) {
$builder->where('tenant_id', session('tenant_id'));
});
}
}
3) 테넌트 ID 설정 미들웨어 추가
public function handle($request, Closure $next) {
$tenantId = auth()->user()->tenant_id ?? null;
session(['tenant_id' => $tenantId]);
return $next($request);
}
2.4 데이터베이스 분리 방식 적용 (Multiple Databases)
각 테넌트별로 별도의 데이터베이스를 연결하려면 동적으로 연결을 변경해야 합니다.
1) 동적 데이터베이스 연결 설정
use Illuminate\Support\Facades\DB;
public function switchDatabase($tenant) {
config([
'database.connections.tenant' => [
'driver' => 'mysql',
'host' => $tenant->db_host,
'database' => $tenant->db_name,
'username' => $tenant->db_user,
'password' => $tenant->db_pass,
],
]);
DB::purge('tenant');
DB::reconnect('tenant');
}
2) Eloquent 모델에서 동적 연결 적용
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TenantModel extends Model {
protected $connection = 'tenant';
}
3. 멀티 테넌트 애플리케이션 성능 최적화
멀티 테넌트 시스템에서는 성능 최적화가 중요합니다.
1. 캐싱 적용
• Redis를 활용한 테넌트별 데이터 캐싱
• Cache::put('tenant_1_projects', $projects, 3600);
2. 쿼리 최적화
• 테넌트 관련 쿼리에 인덱스 추가
• ALTER TABLE projects ADD INDEX idx_tenant_id (tenant_id);
3. 로드 밸런싱 적용
• 여러 데이터베이스 인스턴스를 활용한 로드 분산
4. 멀티 테넌트 구현 시 고려할 보안 요소
멀티 테넌트 시스템에서 보안은 필수적입니다. 다음과 같은 보안 요소를 고려해야 합니다.
1. 데이터 격리 강화
• 테넌트 ID를 항상 검증
• 잘못된 테넌트 접근 방지
2. 액세스 제어
• Laravel의 Policy와 Gates를 활용하여 테넌트 권한 관리
3. 서브도메인 인증
• 테넌트별 SSL 인증서 적용
5. 결론
Laravel과 PHP 8을 활용한 멀티 테넌트 애플리케이션을 구축하면 유연성과 확장성을 극대화할 수 있습니다.
핵심 요약:
• 서브도메인 또는 URL 기반으로 테넌트 구분
• 공유 DB, 스키마 분리, DB 분리 전략 비교
• 성능 최적화를 위한 캐싱 및 로드 밸런싱 적용
• 보안을 고려한 테넌트별 데이터 격리
Laravel의 강력한 기능을 활용하여 효과적인 멀티 테넌트 시스템을 설계해 보세요!
'PHP & Laravel' 카테고리의 다른 글
PHP 8의 가변 변수 기능과 Laravel에서의 동적 데이터 처리 (0) | 2025.01.22 |
---|---|
PHP 8의 스트링 함수 개선 사항과 Laravel에서의 효율적인 문자열 처리 (0) | 2025.01.22 |
PHP 8의 Match Expression과 Laravel에서의 조건문 최적화 (0) | 2025.01.21 |
Laravel 프로젝트의 성능 최적화를 위한 PHP 8 기능 활용법 (0) | 2025.01.21 |
Laravel과 PHP 8에서의 테스트 주도 개발(TDD) 전략 (0) | 2025.01.21 |
Laravel과 PHP 8을 활용한 REST API 개발 베스트 프랙티스 (0) | 2025.01.21 |
PHP 8의 새롭게 도입된 문자열(String) 함수와 Laravel에서의 활용 (1) | 2025.01.21 |
PHP 8의 JIT 컴파일러와 Laravel 성능 향상 전략 (0) | 2025.01.21 |