메인 콘텐츠로 건너뛰기

파사드란

파사드는 애플리케이션의 서비스 컨테이너에서 사용 가능한 클래스에 대한 “정적” 인터페이스를 제공합니다. Laravel에는 거의 모든 기능에 접근할 수 있는 많은 파사드가 함께 포함되어 있습니다. Laravel의 파사드는 서비스 컨테이너 내의 실체 클래스에 대한 “정적 프록시”로 기능하며, 기존의 정적 메서드보다 테스트하기 쉽고 유연성을 유지하면서 간결하고 표현력이 풍부한 문법을 제공합니다. 모든 Laravel 파사드는 Illuminate\Support\Facades 네임스페이스에 정의되어 있습니다.
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;

Route::get('/cache', function () {
    return Cache::get('key');
});
파사드의 구조를 완벽하게 이해하지 못해도 문제 없습니다. 우선 사용법을 익히고 Laravel 학습을 계속해 나갑시다.

파사드의 구조

Laravel 애플리케이션에서 파사드는 컨테이너에서 객체로의 접근을 제공하는 클래스입니다. 이 구조는 Facade 클래스에 의해 실현되고 있습니다. Laravel의 모든 파사드, 그리고 커스텀 파사드는 기저 클래스 Illuminate\Support\Facades\Facade를 상속합니다. Facade 기저 클래스는 __callStatic() 매직 메서드를 사용해 파사드로의 호출을 컨테이너에서 해결된 객체로 위임합니다.
<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;

class UserController extends Controller
{
    /**
     * 지정된 사용자의 프로필을 표시한다
     */
    public function showProfile(string $id): View
    {
        $user = Cache::get('user:'.$id);

        return view('profile', ['user' => $user]);
    }
}
파일 시작 부분에서 Cache 파사드를 임포트하고 있습니다. 이 파사드는 Illuminate\Contracts\Cache\Factory 인터페이스 구현으로의 접근을 프록시합니다. 파사드를 사용한 호출은 모두 Laravel의 캐시 서비스의 내부 인스턴스로 전달됩니다. Illuminate\Support\Facades\Cache 클래스를 보면 정적 메서드 get은 존재하지 않습니다.
class Cache extends Facade
{
    /**
     * 컴포넌트의 등록명을 가져온다
     */
    protected static function getFacadeAccessor(): string
    {
        return 'cache';
    }
}
Cache 파사드는 기저 Facade 클래스를 상속하고, getFacadeAccessor() 메서드를 정의하고 있습니다. 이 메서드는 서비스 컨테이너의 바인딩 이름을 반환합니다. 사용자가 Cache 파사드의 정적 메서드를 호출하면 Laravel은 서비스 컨테이너에서 cache 바인딩을 해결하고, 그 객체에 대해 요청된 메서드(이 경우 get)를 실행합니다.

파사드를 사용하는 상황·사용하지 않는 상황

파사드의 장점

파사드에는 많은 장점이 있습니다. 수동으로 주입·설정해야 하는 긴 클래스명을 외우지 않고도 Laravel의 기능을 사용할 수 있는 간결하고 기억하기 쉬운 문법을 제공합니다. 또한 PHP의 다이내믹 메서드의 독자적인 사용법을 통해 테스트가 용이합니다.

스코프 크리프에 주의한다

파사드를 사용할 때의 주된 위험은 클래스의 “스코프 크리프”입니다. 파사드는 사용하기 쉽고 주입을 필요로 하지 않으므로 클래스가 비대화되어 많은 파사드를 계속해서 사용하게 되기 쉽습니다. 의존성 주입을 사용하면 큰 생성자가 시각적인 피드백을 줍니다. 파사드를 사용하는 경우에는 클래스 크기에 주의하며 책임 범위를 좁게 유지합시다.
클래스가 너무 커졌다고 느끼면 여러 개의 작은 클래스로 분할하는 것을 검토해 주세요.

파사드 vs. 의존성 주입

의존성 주입의 주요 장점 중 하나는 주입된 클래스의 구현을 교체할 수 있다는 것입니다. 이는 테스트 시에 유용합니다. 모의 객체나 스텁을 주입해 스텁에 대해 다양한 메서드가 호출되었음을 어서션할 수 있습니다. 진정으로 정적인 클래스 메서드는 일반적으로 모의 객체나 스텁으로 만들 수 없지만, 파사드는 다이내믹 메서드를 사용해 서비스 컨테이너에서 해결된 객체로의 메서드 호출을 프록시하기 때문에, 주입된 클래스 인스턴스를 테스트하는 것과 같은 방법으로 파사드를 테스트할 수 있습니다.
use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});
이 라우트에 대해 다음 테스트를 작성해 Cache::get이 기대하는 인수로 호출되었음을 검증할 수 있습니다.
use Illuminate\Support\Facades\Cache;

test('basic example', function () {
    Cache::shouldReceive('get')
        ->with('key')
        ->andReturn('value');

    $response = $this->get('/cache');

    $response->assertSee('value');
});

파사드 vs. 헬퍼 함수

파사드에 더해 Laravel은 뷰 생성, 이벤트 발생, 잡 디스패치, HTTP 응답 전송 등 일반적인 작업을 실행할 수 있는 “헬퍼” 함수를 제공합니다. 많은 헬퍼 함수는 대응하는 파사드와 같은 기능을 실행합니다.
// 파사드를 사용한 호출
return Illuminate\Support\Facades\View::make('profile');

// 헬퍼 함수를 사용한 동등한 호출
return view('profile');
파사드와 헬퍼 함수 사이에는 실질적인 차이가 없습니다. 헬퍼 함수를 사용하고 있는 경우에도 대응하는 파사드와 같은 방법으로 테스트할 수 있습니다.
use Illuminate\Support\Facades\Cache;

test('cache helper test', function () {
    Cache::shouldReceive('get')
        ->with('key')
        ->andReturn('value');

    $response = $this->get('/cache');

    $response->assertSee('value');
});

실시간 파사드

실시간 파사드를 사용하면 애플리케이션 내의 임의의 클래스를 파사드로 다룰 수 있습니다. 사용법을 설명하기 위해 먼저 실시간 파사드를 사용하지 않는 코드를 보겠습니다. 예를 들어 Podcast 모델에 publish 메서드가 있다고 가정합니다. 다만 팟캐스트를 공개하려면 Publisher 인스턴스를 주입해야 합니다.
<?php

namespace App\Models;

use App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * 팟캐스트를 공개한다
     */
    public function publish(Publisher $publisher): void
    {
        $this->update(['publishing' => now()]);

        $publisher->publish($this);
    }
}
실시간 파사드를 사용하면 같은 테스트 용이성을 유지하면서 Publisher 인스턴스를 명시적으로 전달할 필요가 없어집니다. 실시간 파사드를 생성하려면 임포트할 클래스의 네임스페이스에 Facades라는 프리픽스를 붙입니다.
<?php

namespace App\Models;

use Facades\App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * 팟캐스트를 공개한다
     */
    public function publish(): void
    {
        $this->update(['publishing' => now()]);

        Publisher::publish($this);
    }
}
실시간 파사드가 사용되면 Facades 프리픽스 뒤에 나타나는 인터페이스 또는 클래스명 부분을 사용해 서비스 컨테이너에서 퍼블리셔의 구현이 해결됩니다.
<?php

use App\Models\Podcast;
use Facades\App\Contracts\Publisher;
use Illuminate\Foundation\Testing\RefreshDatabase;

pest()->use(RefreshDatabase::class);

test('podcast can be published', function () {
    $podcast = Podcast::factory()->create();

    Publisher::shouldReceive('publish')->once()->with($podcast);

    $podcast->publish();
});
실시간 파사드는 테스트 시의 모의 객체 생성을 쉽게 하면서, 인수로 전달할 필요를 없애고 싶은 경우에 편리합니다.

파사드의 테스트

파사드를 테스트하려면 shouldReceive 메서드를 사용합니다. 이를 통해 Mockery의 모의 객체 인스턴스가 반환됩니다. 파사드는 실제로 서비스 컨테이너에 의해 해결·관리되기 때문에 일반적인 정적 클래스보다 훨씬 테스트하기 쉽습니다.
use Illuminate\Support\Facades\Cache;

test('사용자 프로필을 표시한다', function () {
    Cache::shouldReceive('get')
        ->once()
        ->with('user:1')
        ->andReturn(['name' => 'Taylor']);

    $response = $this->get('/users/1');

    $response->assertSee('Taylor');
});
자주 사용하는 모의 메서드는 다음과 같습니다.
메서드설명
shouldReceive('method')메서드가 호출될 것을 기대한다
once()한 번만 호출될 것을 기대한다
times(n)n번 호출될 것을 기대한다
with(args)특정 인수로 호출될 것을 기대한다
andReturn(value)지정한 값을 반환한다
andReturnNull()null을 반환한다

주요 파사드 목록

자주 사용하는 파사드와 그 실체 클래스, 서비스 컨테이너의 바인딩 이름 대응표입니다.
파사드클래스바인딩
AppIlluminate\Foundation\Applicationapp
AuthIlluminate\Auth\AuthManagerauth
CacheIlluminate\Cache\CacheManagercache
ConfigIlluminate\Config\Repositoryconfig
CookieIlluminate\Cookie\CookieJarcookie
CryptIlluminate\Encryption\Encrypterencrypter
DBIlluminate\Database\DatabaseManagerdb
EventIlluminate\Events\Dispatcherevents
FileIlluminate\Filesystem\Filesystemfiles
GateIlluminate\Contracts\Auth\Access\Gate
HashIlluminate\Contracts\Hashing\Hasherhash
HttpIlluminate\Http\Client\Factory
LogIlluminate\Log\LogManagerlog
MailIlluminate\Mail\Mailermailer
NotificationIlluminate\Notifications\ChannelManager
QueueIlluminate\Queue\QueueManagerqueue
RateLimiterIlluminate\Cache\RateLimiter
RedirectIlluminate\Routing\Redirectorredirect
RequestIlluminate\Http\Requestrequest
RouteIlluminate\Routing\Routerrouter
SchemaIlluminate\Database\Schema\Builder
SessionIlluminate\Session\SessionManagersession
StorageIlluminate\Filesystem\FilesystemManagerfilesystem
URLIlluminate\Routing\UrlGeneratorurl
ValidatorIlluminate\Validation\Factoryvalidator
ViewIlluminate\View\Factoryview

다음 단계

Contracts(계약)

파사드와 짝을 이루는 Contracts의 개념과 구분 사용을 배웁니다.
마지막 수정일 2026년 7월 13일