[Laravel] Global Variable / Constant / Function 정의 및 사용에 대한 고찰

Laravel Framework에서 global 변수, 상수, 함수에 대한 정의 및 사용방법은 무궁무진하다. global 전용 Provider를 만들어 라라벨 가동 시 전역으로 사용하게 할 수도 있고, Traits를 사용하여 사용할 수도 있고, 별도의 Service 폴더를 만들어 Class들을 모아놓고 new 연산자를 통해 사용할 수도 있고, Basic Controller를 상속받은 Function(혹은 Variable, Constant) Controller를 만들어서 extends 하여 사용할 수도 있고, Helpers밑에 globalFuncgtion.php 파일을 만들어 composer.json에 autoload 하여 사용할 수도 있다. 

 

무엇이 가장 좋은 방법인가? 에 대하여 생각해봤는데 정답은 없었고, 그렇기에 필자가 생각했던 것들을 기록한다.

(아래에서는 Variable, Constant, Function 등 중 Function을 예로 사용.)


1. Global Function 전용 Service Provider를 만들어 사용하는 경우

1. app/Providers/ 하위에 GlobalFunctionServiceProvider를 생성

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class GlobalFunctionsServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        require_once base_path().'/app/Helper/Functions/global.php';
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

2. 위의 설정대로 app/Helper/Functions/global.php 폴더 및 디렉토리를 생성.

<?php
/**
*
* 프로젝트 전역에서 사용할 수 있는 함수들의 모음
*
*/

function globalFunction1(){
	return "This Is Global Function 1";
}

function globalFunction2(){
	return "This Is Global Function 2";
}

function globalFunction3(){
	return "This Is Global Function 3";
}

function globalFunction4(){
	return "This Is Global Function 4";
}

3. config/app.php 에서 위에 선언한 GlobalFunctionsServiceProvider 등록

/*
 * Custom Service Providers...
 */
App\Providers\GlobalFunctionsServiceProvider::class,

 

장점 : controller, model, blade template 등 어디서라도 전역 함수를 사용할 수 있다.

 

단점 : 위 globalFunction1~4를 사용하지 않은 페이지 혹은 Request에 맞는 Controller, Model, View 가 호출되더라도 라라 벨 라이프 사이클에 의해 무조건 생성해내기 때문에 자원을 낭비할 여력이 생긴다. 

 

결론 : 사용하기 권장하지는 않는다. 만약 프로젝트 내부에서 꼭 한 번씩 사용하는 (혹은, 거의 필수적으로 사용하는) 내용의 경우 사용해볼 만하다.


2. Traits를 이용하여 Global Function 전용 Trait으로 사용하는 경우

1. Traits 생성

<?php

namespace App\Traits;

trait GlobalFunctionTrait
{
    function globalFunction1(){
    	return "This Is global Function 1";
    }
    function globalFunction2(){
    	return "This Is global Function 2";
    }
    function globalFunction3(){
    	return "This Is global Function 3";
    }
    function globalFunction4(){
    	return "This Is global Function 4";
    }
}

2. 원하는 곳에서 Traits 사용

<?php

namespace App\Http\Controllers;

use App\Traits\GlobalFuntionTraits;
use Illuminate\Routing\Controller as BaseController;

class Controller extends BaseController
{
    use GlobalFunctionTraits;
}

장점 : use 키워드를 사용하여 언제든지 간편하게 접근할 수 있다.

 

단점 : 간편하기에 남용하다가 레거시 시절의 include_once, require_once 꼴이 날 수 있다. (같은 기능을 찾지 못하고 똑같은 기능을 또 만들 가능성이 있음)

 

결론 : 기능을 잘 관리할 수 있다면 사용하기 추천함. 특히 Controller에서 사용하기 보단 Model쪽에서 사용하는것을 권장.


3. app 디렉토리 밑에 별도의 services 디렉토리를 만들어 Function을 Class화 하여 사용하는 경우

1. Class를 생성

<?php

namespace App\Services\Classes;

class GlobalFuncion {
	function globalFunction1() {
    }
    function globalFunction2() {
    }
    function globalFunction3() {
    }
    function globalFunction4() {
    }
    
}

2. Class를 사용

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;
use App\Services\Classes\GlobalFunction;

class Controller extends BaseController
{

	public function index() {
    	$globalFunction = new GlobalFunction();
        $globalFunction->globalFunction1();
        $globalFunction->globalFunction2();
        $globalFunction->globalFunction3();
        $globalFunction->globalFunction4();
    }
    
}

 

장점 : 제일 깔끔하게 사용할 수 있으며 Class 네이밍 생성만 잘 한다면 유지보수 측면에서 수월하다. 

 

단점 : 사용할 때마다 매번 new연산자를 사용하여 객체를 생성해야 하기 때문에 번거롭고 잘못 사용하면 메모리 관리에 어려움이 있다.

 

결론 : 사용하기 권장. 다만 Global에서 사용하기 보다는 각 기능별, 각 상황별, 각 Controller별로 나누어 특정 구간에서 사용하면 좋을 듯 하다. (도메인 주도 설계[Domain Driven Design] 등)


4. Global용도의 Controller를 만들어 extends하여 사용하는 경우

1. GlobalFunctionController 생성

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;

class GlobalFunctionController extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    public function globalFunction1()
    {

    }
}

2. 상속받은 다른 클래스스에서 사용

<?php

namespace App\Http\Controllers\Test;

use App\Http\Controllers\GlobalFunctionController;

class TestController extends GlobalFunctionController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    public function index()
    {
		$this->globalFunction1();
    }
}
<?php

namespace App\Http\Controllers\Test;

use App\Http\Controllers\GlobalFunctionController;

class TestController2 extends GlobalFunctionController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    public function index()
    {
		$this->globalFunction1();
    }
}

장점 : 특정 컨트롤러만 상속받으면 그 기능을 온전히 다 사용할 수 있기 때문에 편리하다.

 

단점 : 특정 컨트롤러를 상속받지 못하면 기능을 사용할 수 없다.

 

결론 : Controller에서 사용하기에 적합.


5. Helpers 디렉토리 밑에 php파일을 만들어 관리하며 composer.json autoload를 이용하여 사용하는 경우

1. app/Helper/Functions/global.php 폴더 및 디렉토리를 생성.

<?php
/**
*
* 프로젝트 전역에서 사용할 수 있는 함수들의 모음
*
*/

function globalFunction1(){
	return "This Is Global Function 1";
}

function globalFunction2(){
	return "This Is Global Function 2";
}

function globalFunction3(){
	return "This Is Global Function 3";
}

function globalFunction4(){
	return "This Is Global Function 4";
}

2. composer.json 설정

"autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        },
        "files" : [
            "app\\Helper\\constant.php",
            "app\\Helper\\database.php",
            "app\\Helper\\helper.php",
            // 추가
            "app\\Helper\\Functions\\global.php"
        ]
    },

3. composer 명령어로 autoload dump하기

# In Terminal
$ composer dump-autoload

 

장점 : controller, model, blade template 등 어디서라도 전역 함수를 사용할 수 있다.

 

단점 : 위 globalFunction1~4를 사용하지 않은 페이지 혹은 Request에 맞는 Controller, Model, View 가 호출되더라도 라라 벨 라이프 사이클에 의해 무조건 생성해내기 때문에 자원을 낭비할 여력이 생긴다. 

 

결론 : 사용하기 권장하지는 않는다. 만약 프로젝트 내부에서 꼭 한 번씩 사용하는 (혹은, 거의 필수적으로 사용하는) 내용의 경우 사용해볼 만하다.


💁🏻‍♂️ 그 밖에 좋은 의견이나 방법을 알고계신다면 댓글이나 우측 하단의 채팅봇을 통하여 알려주시면 감사하겠습니다.