본문 바로가기

파사드

업데이트됨

번역일: 2026년 8월 26일

이 페이지는 원문이 업데이트되어 번역이 갱신되었습니다.

원문 수정
2026년 8월 26일
번역 갱신
2026년 8월 26일

파사드

소개

Laravel 공식 문서 곳곳에서 "파사드(Facade)"를 통해 Laravel 기능을 사용하는 예제를 볼 수 있습니다. 파사드는 애플리케이션의 서비스 컨테이너에 등록된 클래스에 "정적(static)" 인터페이스처럼 접근할 수 있게 해줍니다. Laravel에는 거의 모든 기능을 커버하는 다양한 내장 파사드가 포함되어 있습니다.

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은 다양한 전역 "헬퍼 함수"도 제공합니다. view, response, url, config 등이 대표적입니다. 각 헬퍼 함수는 해당 기능 문서에서 설명되며, 전체 목록은 헬퍼 문서에서 확인할 수 있습니다.

예를 들어, JSON 응답을 반환할 때 Illuminate\Support\Facades\Response 파사드 대신 response 헬퍼 함수를 사용할 수 있습니다. 헬퍼 함수는 전역으로 사용 가능하므로 별도의 클래스 임포트가 필요 없습니다.

use Illuminate\Support\Facades\Response; // 파사드 사용 Route::get('/users', function () { return Response::json([ // ... ]); }); // 헬퍼 함수 사용 (동일한 결과) Route::get('/users', function () { return response()->json([ // ... ]); });

파사드를 언제 사용할까

파사드는 여러 장점을 제공합니다. 긴 클래스 이름을 외우거나 별도로 주입·설정하지 않아도 Laravel 기능을 간결하게 사용할 수 있습니다. 또한 PHP의 동적 메서드를 활용하기 때문에 테스트 작성도 수월합니다.

하지만 한 가지 주의할 점이 있습니다. 파사드는 사용하기 너무 편리한 나머지, 하나의 클래스에 파사드를 과도하게 사용해 클래스가 지나치게 커지는 "범위 팽창(scope creep)" 문제가 생길 수 있습니다. 의존성 주입을 사용할 때는 생성자 인자가 많아지면 시각적으로 "이 클래스가 너무 커졌다"는 신호를 받을 수 있지만, 파사드는 그런 피드백이 없습니다. 파사드를 사용할 때는 클래스의 크기와 책임 범위에 특별히 신경 쓰고, 클래스가 너무 커진다 싶으면 여러 개의 작은 클래스로 분리하는 것을 고려하세요.

파사드 vs. 의존성 주입

의존성 주입의 가장 큰 장점은 주입하는 클래스의 구현체를 쉽게 교체할 수 있다는 것입니다. 테스트 시에 모의 객체(mock)나 스텁(stub)을 주입하고 특정 메서드 호출 여부를 검증할 수 있어 유용합니다.

일반적인 정적 메서드는 모킹이 어렵지만, 파사드는 서비스 컨테이너에서 해석된 객체에 동적으로 메서드 호출을 위임하기 때문에 주입된 클래스 인스턴스를 테스트하는 것과 동일하게 테스트할 수 있습니다. 아래 라우트를 예로 들어보겠습니다.

use Illuminate\Support\Facades\Cache; Route::get('/cache', function () { return Cache::get('key'); });

Laravel의 파사드 테스트 메서드를 활용하면 Cache::get이 기대한 인자와 함께 호출됐는지 다음과 같이 검증할 수 있습니다.

Pest

use Illuminate\Support\Facades\Cache; test('기본 캐시 예제', function () { Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $response = $this->get('/cache'); $response->assertSee('value'); });

PHPUnit

use Illuminate\Support\Facades\Cache; /** * 기본 기능 테스트 예제 */ public function test_basic_example(): void { Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $response = $this->get('/cache'); $response->assertSee('value'); }

파사드 vs. 헬퍼 함수

파사드 외에도 Laravel은 뷰 생성, 이벤트 발행, Job 디스패치, HTTP 응답 반환 등 자주 쓰이는 작업을 위한 다양한 헬퍼 함수를 제공합니다. 헬퍼 함수 중 상당수는 대응하는 파사드와 동일하게 동작합니다. 예를 들어 아래 두 코드는 완전히 동일합니다.

return Illuminate\Support\Facades\View::make('profile'); return view('profile');

파사드와 헬퍼 함수 사이에는 실질적인 차이가 없습니다. 헬퍼 함수를 사용할 때도 대응하는 파사드와 동일한 방법으로 테스트할 수 있습니다. 예를 들어 아래 라우트가 있다면,

Route::get('/cache', function () { return cache('key'); });

cache 헬퍼는 내부적으로 Cache 파사드가 감싸고 있는 클래스의 get 메서드를 호출합니다. 따라서 헬퍼 함수를 사용하더라도 파사드와 동일하게 테스트를 작성할 수 있습니다.

use Illuminate\Support\Facades\Cache; /** * 기본 기능 테스트 예제 */ public function test_basic_example(): void { Cache::shouldReceive('get') ->with('key') ->andReturn('value'); $response = $this->get('/cache'); $response->assertSee('value'); }

파사드의 동작 원리

Laravel 애플리케이션에서 파사드는 서비스 컨테이너에 등록된 객체에 접근하는 클래스입니다. 이 동작의 핵심 메커니즘은 Facade 기반 클래스에 구현되어 있습니다. Laravel의 모든 내장 파사드와 직접 만드는 커스텀 파사드는 Illuminate\Support\Facades\Facade 기반 클래스를 상속합니다.

Facade 기반 클래스는 PHP의 __callStatic() 매직 메서드를 활용해, 파사드에서 발생하는 정적 메서드 호출을 서비스 컨테이너에서 해석된 실제 객체에 위임합니다.

아래 코드를 보면 Cache 클래스의 정적 메서드 get을 직접 호출하는 것처럼 보입니다.

<?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)를 실행합니다.

실시간 파사드

실시간 파사드(Real-Time Facade)를 사용하면 애플리케이션의 어떤 클래스든 파사드처럼 취급할 수 있습니다. 이해를 돕기 위해 먼저 실시간 파사드를 사용하지 않는 코드를 살펴보겠습니다. 예를 들어 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 구현체를 주입하면 모킹을 통해 독립적으로 테스트할 수 있습니다. 하지만 publish를 호출할 때마다 항상 Publisher 인스턴스를 명시적으로 전달해야 합니다.

실시간 파사드를 사용하면 동일한 테스트 용이성을 유지하면서도 Publisher 인스턴스를 명시적으로 전달할 필요가 없습니다. 실시간 파사드를 만들려면 임포트하는 클래스의 네임스페이스 앞에 Facades를 붙이면 됩니다.

<?php
namespace App\Models;
use App\Contracts\Publisher; //
use Facades\App\Contracts\Publisher; //
use Illuminate\Database\Eloquent\Model;
class Podcast extends Model
{
/**
* 팟캐스트를 발행합니다.
*/
public function publish(Publisher $publisher): void //
public function publish(): void //
{
$this->update(['publishing' => now()]);
$publisher->publish($this); //
Publisher::publish($this); //
}
}

실시간 파사드를 사용하면 Facades 접두사 뒤에 오는 인터페이스 또는 클래스 이름을 기준으로 서비스 컨테이너에서 해당 구현체를 해석합니다. 테스트 시에는 Laravel 내장 파사드 테스트 헬퍼를 사용해 메서드 호출을 모킹할 수 있습니다.

Pest

<?php use App\Models\Podcast; use Facades\App\Contracts\Publisher; use Illuminate\Foundation\Testing\RefreshDatabase; pest()->use(RefreshDatabase::class); test('팟캐스트를 발행할 수 있다', function () { $podcast = Podcast::factory()->create(); Publisher::shouldReceive('publish')->once()->with($podcast); $podcast->publish(); });

PHPUnit

<?php namespace Tests\Feature; use App\Models\Podcast; use Facades\App\Contracts\Publisher; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class PodcastTest extends TestCase { use RefreshDatabase; /** * 테스트 예제 */ public function test_podcast_can_be_published(): void { $podcast = Podcast::factory()->create(); Publisher::shouldReceive('publish')->once()->with($podcast); $podcast->publish(); } }

파사드 클래스 레퍼런스

아래 표에서 모든 파사드와 그에 대응하는 실제 클래스, 그리고 서비스 컨테이너 바인딩 키를 확인할 수 있습니다. 특정 파사드의 API 문서를 빠르게 찾아볼 때 유용하게 활용하세요.

파사드클래스서비스 컨테이너 바인딩
AppIlluminate\Foundation\Applicationapp
ArtisanIlluminate\Contracts\Console\Kernelartisan
Auth (Instance)Illuminate\Contracts\Auth\Guardauth.driver
AuthIlluminate\Auth\AuthManagerauth
BladeIlluminate\View\Compilers\BladeCompilerblade.compiler
Broadcast (Instance)Illuminate\Contracts\Broadcasting\Broadcaster 
BroadcastIlluminate\Contracts\Broadcasting\Factory 
BusIlluminate\Contracts\Bus\Dispatcher 
Cache (Instance)Illuminate\Cache\Repositorycache.store
CacheIlluminate\Cache\CacheManagercache
CloudIlluminate\Foundation\Cloud\CloudManager 
ConfigIlluminate\Config\Repositoryconfig
ContextIlluminate\Log\Context\Repository 
CookieIlluminate\Cookie\CookieJarcookie
CryptIlluminate\Encryption\Encrypterencrypter
DateIlluminate\Support\DateFactorydate
DB (Instance)Illuminate\Database\Connectiondb.connection
DBIlluminate\Database\DatabaseManagerdb
EventIlluminate\Events\Dispatcherevents
Exceptions (Instance)Illuminate\Contracts\Debug\ExceptionHandler 
ExceptionsIlluminate\Foundation\Exceptions\Handler 
FileIlluminate\Filesystem\Filesystemfiles
GateIlluminate\Contracts\Auth\Access\Gate 
HashIlluminate\Contracts\Hashing\Hasherhash
HttpIlluminate\Http\Client\Factory 
LangIlluminate\Translation\Translatortranslator
LogIlluminate\Log\LogManagerlog
MailIlluminate\Mail\Mailermailer
NotificationIlluminate\Notifications\ChannelManager 
Password (Instance)Illuminate\Auth\Passwords\PasswordBrokerauth.password.broker
PasswordIlluminate\Auth\Passwords\PasswordBrokerManagerauth.password
Pipeline (Instance)Illuminate\Pipeline\Pipeline 
ProcessIlluminate\Process\Factory 
Queue (Base Class)Illuminate\Queue\Queue 
Queue (Instance)Illuminate\Contracts\Queue\Queuequeue.connection
QueueIlluminate\Queue\QueueManagerqueue
RateLimiterIlluminate\Cache\RateLimiter 
RedirectIlluminate\Routing\Redirectorredirect
Redis (Instance)Illuminate\Redis\Connections\Connectionredis.connection
RedisIlluminate\Redis\RedisManagerredis
RequestIlluminate\Http\Requestrequest
Response (Instance)Illuminate\Http\Response 
ResponseIlluminate\Contracts\Routing\ResponseFactory 
RouteIlluminate\Routing\Routerrouter
ScheduleIlluminate\Console\Scheduling\Schedule 
SchemaIlluminate\Database\Schema\Builder 
Session (Instance)Illuminate\Session\Storesession.store
SessionIlluminate\Session\SessionManagersession
Storage (Instance)Illuminate\Contracts\Filesystem\Filesystemfilesystem.disk
StorageIlluminate\Filesystem\FilesystemManagerfilesystem
URLIlluminate\Routing\UrlGeneratorurl
Validator (Instance)Illuminate\Validation\Validator 
ValidatorIlluminate\Validation\Factoryvalidator
View (Instance)Illuminate\View\View 
ViewIlluminate\View\Factoryview
ViteIlluminate\Foundation\Vite 

이 문서는 Laravel 공식 문서(MIT)를 한국 개발자를 위해 번역·재구성한 것입니다.

번역일: 2026년 8월 26일