[Laravel 기초] 6. Laravel Facade

Laravel Facade

Laravel Facade 는 라라벨 서비스 컨테이너에서 사용 가능한 클래스들에 대한 ‘정적인 인터페이스’를 제공하는 역할을 합니다. 서비스 컨테이너에 등록된 클래스들의 ‘정적 프록시’ 역할을 합니다. 뉴비 개발자에게 이 두 문장으로 파사드를 이해하기엔 부족한 느낌이 있었습니다. 제가 파사드를 이해한 흐름으로 설명하고자 합니다. 익숙한 단어들 위주로 공부해 보았습니다.

Proxy

인터넷 하면서 많이 봤다 프록시??

Proxy 라는 개념 자체가 소프트웨어 공학에서 자주 등장하는 개념입니다. 컴퓨터를 공부하기 전 사용하면서 어디서 많이 봤다고 생각했는데 방화벽이 설정으로 웹 페이지 접속이 안되는 경우 저런 문구를 많이 보았습니다. 프록시라는 단어 자체도 익숙한데 개념은 익숙하지 않습니다. 프록시란 무엇일까요??

Proxy 는 누군가의 대리인이다.

무언가( 프록시 프로그램, 서버, 클래스 등)의 대리인 입니다. ‘무언가’의 기능은 그대로 제공하면서 제어의 흐름만 프록시로 가져오는 역할을 합니다. 제어의 흐름을 프록시로 가져오면서 보호 받아야할 ‘무언가’ (실제 서버, 실제 구현체) 에 대한 이점을 취할 수 있게 됩니다. (위키 참조 – Proxy pattern) 포스팅을 위해 프록시에 대한 내용들을 찾아보았는데 다양한 곳에서 사용되고 양이 방대하여 이쯤에서 정리하고 넘어가겠습니다. 제어 흐름을 가져오는 대리인 정도로 기억하겠습니다.

Facade Pattern

Facade Pattern 은 복잡한 내부 설계를 간단한 인터페이스를 통해 제공한다.

디자인 패턴 중에는 Facade Pattern 이 있습니다. Facade란 용어는 건물의 출입구로 이용되는 정면 외벽 부분 이라는 뜻입니다. 건축에서는 이 파사드를 가지고 디자인, 설계 등 다양한 요소를 파악한다고 합니다. 이와 비슷하게 소프트웨어 공학에서는 Facade Pattern 이란 복잡한 내부 설계를 간단한 인터페이스로 제공하는 것이라고 볼 수 있습니다. Proxy 패턴과 비슷하지만 Proxy는 기능을 그대로 제공하는 것에 비해 Facade 패턴은 복잡한 설계를 가공한 새로운 인터페이스를 만들어 제공합니다. (Proxy vs Facede 비교 정리)

Facade Pattern 에 대해 간략히 알아보았는데 사실 라라벨 Facade 와는 다른 점이 있습니다. 저같이 Facade Pattern 몰랐던 분은 디자인 패턴 하나를 익혔다고 생각하고 알고 계시던 분은 Facade Pattern 에 대한 개념은 잠시 접어두고 라라벨 Facade에 대해 알아보겠습니다. 이유는 아래서 언급하겠습니다.

Laravel Facade ??

라라벨 Facade 사용에 대한 다음 예제를 살펴보도록 하겠습니다. Cache 라는 서비스의 동적 메소드인 get(‘key’) 를 통해 데이터를 가져오고 싶습니다. 소스 코드로는 아래 처럼 구현할 수 있습니다.

<?php

$cache = new \Illuminate\Filesystem\Cache();
$cache->get();

// Cache 는 Application 클래스의 register()에 등록(binding)되어 있다. 
// Cache 를 서비스 컨테이너에서 가져오고자 하면 다음과 같은 코드가 될 수 있다.
// $this->app->make('cache')->get('key');

Facade 를 사용하면 동적 메소드를 정적 메소드 처럼 사용할 수 있습니다. Illuminate\Support\Facades 에 미리 등록된 Cache를 사용하면 위에 코드와 같이 동작합니다. Illuminate\Support\Facades 에 있는 Cache 를 사용함으로 \Illuminate\Filesystem\Cache 클래스명을 (현재는 심플하지만 복잡한 클래스명의 경우) 기억하지 않고 사용할 수 있다는 이점이 있습니다.

<?php

use Illuminate\Support\Facades\Cache;

Cache::get('key');

라라벨 Facade 는 서비스 컨테이너에 등록된 클래스들을 정적인 메소드 형태로 호출하게 해주는 Wrapper 클래스의 형태를 하고 있는 것을 알 수 있습니다.

Create Laravel Facade

라라벨 Facade 는 어떻게 만들까요? 추상 클래스 Facade를 상속받아 구현하면 됩니다. Facade 클래스를 열어보니 두 가지 메소드가 제일 먼저 보였습니다. resolved() 메소드는 말 그대로 서비스 컨테이너에서 서비스를 Resolving 하며 __callStatic() 에서는 해당 서비스 동적 메소드가 정적 메소드로 사용할 수 있도록 구성되어 있었습니다.

<?php

namespace Illuminate\Support\Facades;

abstract class Facade
{
    //...//
    // resolved : 서비스 컨테이너 $app 에서 등록된 실제 서비스를 가져온다. $app->afterResolving('className')
    // getFacadeAccessor()에 서비스 이름을 리턴하여 사용한다.
    public static function resolved(Closure $callback)
    {
        static::$app->afterResolving(static::getFacadeAccessor(), function ($service) use ($callback) {
            $callback($service);
        });
    }

    // __callStatic() 를 통해 서비스의 동적 메소드가 정적 메소드처럼 사용할 수 있게 한다.
    public static function __callStatic($method, $args)
    {
        $instance = static::getFacadeRoot();

        if (! $instance) {
            throw new RuntimeException('A facade root has not been set.');
        }

        return $instance->$method(...$args);
    }
    //...//
}

Facade를 상속받는 구현체는 getFacadeAccessor() 에서 등록된 서비스 이름을 리턴해주면 Facade로 사용할 수 있습니다. 아래는 Cache Facade 객체인데 resolved 메소드를 참조하면 실제로는 $app->afterResolving(‘cache’)가 된다는 것을 알 수 있습니다.

<?php

class Cache extends Facade
{
    protected static function getFacadeAccessor() { return 'cache'; }
}

Laravel Facade References

라라벨에서 이미 등록된 Facade 들은 config/app.php 에서 찾아볼 수 있습니다.

config/app.php aliases 에 라라벨에서 제공하는 다양한 Facade 들을 살펴볼 수 있다.

Facade 란 명칭에 대해 (Laravel Facade != Facade Pattern)

지금까지 살펴본 라라벨 Facade는 뭔가 어색한 점이 있습니다. 디자인 패턴으로 다뤘던 Facade Pattern 과 매칭이 되지 않습니다. Facade Pattern 에서는 복잡한 설계를 가공한 새로운 인터페이스를 제공한다고 하였습니다. 하지만 필자는 라라벨 Facade는 서비스 컨테이너에서 서비스를 인스턴스화해서 같은 메소드를 제공하는 것이 Proxy Pattern 에 더 밀접한 관계가 있는 것으로 느껴졌습니다.

라라벨 Facade Naming 이란 키워드로 여러가지 서칭을 해보았는데 개발자 커뮤니티등 개발자들 사이에서 네이밍에 대한 논란이 있는 것을 알 수 있었습니다. Facade 란 이름이 혼란을 줄 여지가 있다고 이름을 변경을 요구하고 있는 경우를 찾아볼 수 있었습니다.

필자는 Facade Word 고유의 뜻 건물의 정면 이라는 개념으로 다가가는 것이 좋을 것 같다고 느꼈습니다. Facade 이라는 명칭은라라벨 프레임 워크를 이해하는데 방해가 되는 것은 분명합니다. 이미 명칭이 되어 온 것이라 지금 명칭을 새로 하는 것 또한 혼란을 가져올 것이기 때문에 필자는 좋은 방법이 떠오르지 않습니다. 프로그래밍에 있어 Naming 은 정말 중요한 것을 다시 한번 깨닫게 합니다. 이미 명칭된 것이기에 라라벨을 접하시는 분들은 이점을 고려해서 보셨으면 좋겠습니다.

TL;DR

  • 라라벨 Facade 는 서비스 컨테이너에 등록되어 있는 서비스를 정적 메소드 형태로 사용해 줄 수 있게 한다.
  • 라라벨 Facade 는 getFacadeAccessor() 를 구현하면 되며 config/app.php 에 라라벨 Facade 들을 확인해 볼수 있다.
  • 라라벨 Facade 는 디자인 패턴 Facade Pattern 과는 개념이 다르다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다