INTRO
라라벨 생명주기 따라가보기 두번째 포스트이다.
저번 포스트에서 bootstrap/app.php 를 실행하기 직전까지 확인해보았는데, 이번부터는 그 이후이다.
FLOW
A.4.a. bootstrap/app.php
해당 파일은 php 파일로, 특정 클래스에 대한 정의없이 $app 이라는 인스턴스를 생성한 후, 가공하여, return 하는 코드이다. 하나 하나 따라가 보자.
A.4.a.1 인스턴스 $app 생성하기 - Application 인스턴스 생성하기
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
첫번째로는 $app 에, Application instance를 할당하는 일이다.
주석을 해석해보자면,
첫 번째로 우리가 할 일은 Laravel 애플리케이션 인스턴스를 생성하는 것입니다.
이 애플리케이션 인스턴스는 Laravel의 모든 구성 요소를 "접합"해주며 시스템의 IoC(의존성 주입) 컨테이너로 작동하여 다양한 부분을 모두 연결시킵니다.
이다. 사이클 동안, 다양한 컴포넌트에서 사용하거나, 사용되는 어플리케이션 인스턴스를 생성하는 코드이다.
여기서, IoC(의존성 주입) 컨테이너라는게 뭔지 좀더 찾아보자.
https://laravel.kr/docs/9.x/container
라라벨 9.x - 서비스 컨테이너
라라벨 한글 메뉴얼 9.x - 서비스 컨테이너
laravel.kr
라라벨 공식문서 한글 번역본에서의 서비스 컨테이너에 대한 설명이다.
아마도, 위에서 말하는 서비스 컨테이너 해당 어플리케이션 클래스가 아닐까 싶다. (확실하진 않으니 진행하면서 아닐 경우 수정하겠다.)
라이프 사이클에 걸쳐 의존성 주입 을 쉽게 사용할 수 있게 해준다는 것만 이해하고 넘어가자. ( 서비스 컨테이너에 대해서는 다른 포스트에서 더 자세하게 다뤄 보자.)
한편, 해당 어플리케이션 인스턴스를 생성하기 위해 생성자에 넣는 인자는 프로젝트의 루트 디렉토리 경로인것으로 보여진다.
어디에 사용하는 것일지는 Application 인스턴스 안에서 확인해보자.
A.4.b. Illuminate\Foundation\Application
https://github.com/laravel/framework/blob/10.x/src/Illuminate/Foundation/Application.php
라이프 사이클 따라가기를 하며 처음으로 만나는 클래스이다.
라라벨의 시스템의 전반적인 환경 정보나 부가적인 설정 정보를 property로 가지는 것으로 보인다.
또한, 서비스 컨테이너의 기능이었던 바인딩 기능 등에 대한 메서드들도 보인다.
그밖에도 상당히 많은 인터페이스와 프로퍼티, 메서드를 지녔지만, 일단은 생성자부터 확인해보자.
/**
* Create a new Illuminate application instance.
*
* @param string|null $basePath
* @return void
*/
public function __construct($basePath = null)
{
if ($basePath) {
$this->setBasePath($basePath);
}
$this->registerBaseBindings();
$this->registerBaseServiceProviders();
$this->registerCoreContainerAliases();
}
가장 먼저, setBasePath 메서드부터 따라가 보자.
/**
* Set the base path for the application.
*
* @param string $basePath
* @return $this
*/
public function setBasePath($basePath)
{
$this->basePath = rtrim($basePath, '\/');
$this->bindPathsInContainer();
return $this;
}
주석을 읽어 보면, "application의 기본 경로를 지정한다." 라고 작성되어있다.
그대로 따라가보면 Applicaiton 클래스의 property 중 하나인 basePath에 인자로 받은 path(프로젝트 루트 디렉토리)를 할당해준다.
그 다음, bindPathsInContainer 메서드를 실행한 후 $this(Application 인스턴스)를 return 한다.
/**
* Bind all of the application paths in the container.
*
* @return void
*/
protected function bindPathsInContainer()
{
$this->instance('path', $this->path());
$this->instance('path.base', $this->basePath());
$this->instance('path.config', $this->configPath());
$this->instance('path.database', $this->databasePath());
$this->instance('path.public', $this->publicPath());
$this->instance('path.resources', $this->resourcePath());
$this->instance('path.storage', $this->storagePath());
$this->useBootstrapPath(value(function () {
return is_dir($directory = $this->basePath('.laravel'))
? $directory
: $this->basePath('bootstrap');
}));
$this->useLangPath(value(function () {
return is_dir($directory = $this->resourcePath('lang'))
? $directory
: $this->basePath('lang');
}));
}
해당 메서드의 주석을 읽어 보면, "application의 모든 path 들을 컨테이너에 bind 해준다." 라고 적혀 있다.
주석과 코드를 대강 읽어보았을 때는 주석의 의미대로, 기본 경로, config 의 경로, storage의 경로 등등을 컨테이너에 바인딩 해주는 메서드 인것으로 추측된다.
다양한 메서드가 등장하는데, instance 메서드부터 확인해보자.
/**
* Register an existing instance as shared in the container.
*
* @param string $abstract
* @param mixed $instance
* @return mixed
*/
public function instance($abstract, $instance)
{
$this->removeAbstractAlias($abstract);
$isBound = $this->bound($abstract);
unset($this->aliases[$abstract]);
// We'll check to determine if this type has been bound before, and if it has
// we will fire the rebound callbacks registered with the container and it
// can be updated with consuming classes that have gotten resolved here.
$this->instances[$abstract] = $instance;
if ($isBound) {
$this->rebound($abstract);
}
return $instance;
}
주석: "존재하는 instance를 컨테이너에 공유되도록 등록한다."
즉, 인스턴스를 컨테이너에 등록하는 코드로 보인다.
removeAbstractAlias 메서드
/**
* Remove an alias from the contextual binding alias cache.
*
* @param string $searched
* @return void
*/
protected function removeAbstractAlias($searched)
{
if (! isset($this->aliases[$searched])) {
return;
}
foreach ($this->abstractAliases as $abstract => $aliases) {
foreach ($aliases as $index => $alias) {
if ($alias == $searched) {
unset($this->abstractAliases[$abstract][$index]);
}
}
}
}
removeAbstractAlias 메서드는 기존에 선언된 alias를 삭제하는 코드로 보인다.
그러나, 현재 condition에서는 따로 unset하는 로직이 작동하지 않기때문에, 넘어간다.
bound 메서드
/**
* Determine if the given abstract type has been bound.
*
* @param string $abstract
* @return bool
*/
public function bound($abstract)
{
return isset($this->bindings[$abstract]) ||
isset($this->instances[$abstract]) ||
$this->isAlias($abstract);
}
해당 메서드는 특정 abstract type (추상 자료형)이 구현체에 bind 된적 있는지 확인하는 메서드이다.
이것 역시 현재 condition에서 request에서 결과값은 false이다.
unset($this->aliases($abstract);
unset($this->aliases[$abstract]);
그 다음, 기존에 alias에 등록되어 있던, 추상 클래스를 unset 해준다.
alias가 어디서 쓰이는지는 아직 정확히 알 수 없다.
$this->instances~ return $instances;
// We'll check to determine if this type has been bound before, and if it has
// we will fire the rebound callbacks registered with the container and it
// can be updated with consuming classes that have gotten resolved here.
$this->instances[$abstract] = $instance;
if ($isBound) {
$this->rebound($abstract);
}
return $instance;
instances라는 배열 property 안에 key 값으로 추상자료형을, value값으로 instance (구현체)를 넣는 것으로 보아, 컨테이너에서 구현체를 바인딩해주는 로직으로 보인다.
그 밑에는 $isBound 가 true이면, rebound 메서드를 실행시키는데,
주석을 읽어보면
추상자료형이 bind 된 적 있는지 확인하고, 된적 있다면 컨테이너에 등록된 rebound 콜백을 실행시킨다.
라는 의미로 보인다.
아마도, rebound 될때에 이벤트를 다른 곳에서 사용하는 것을 보이나 현재는 $isBound 가 false이기에 알 수 없다.
정리해보자면, instance 메서드는 추상체에 구현체를 넣는 로직으로 보인다.
원래 살펴 보던 bindPathsInContainer 에서는 instance 메서드를 'path', 'path.base' 등 라라벨내에서 사용하는 추상 path에 실제 사용자의 개발환경의 path를 bind 해주는 용도로 사용하는것으로 보인다.
그 다음은 useBootstrapPath 메서드와 useLangPath 메서드이다.
이름만 봐도, bootstrap, lang 의 경로를 지정하는 메서드인 것으로 보이나. 한번 알아보겠다.
'개발 > 라라벨' 카테고리의 다른 글
eloquent 모델에 keyType 지정하지 않을 시, relation에 접근할 수 없는 이슈 (1) | 2023.10.17 |
---|---|
tap, tap, tap (0) | 2023.09.27 |
laravel Request life-cycle (생명주기) dd로 따라가보기 (1) (0) | 2023.09.05 |
Eloquent Collection과 Support Collection 은 뭐가 다를까? (0) | 2023.09.01 |
laravel Notification queue 적용시에 모델에 따라서 memory size exhausted 되는 이슈 해결기 (0) | 2023.08.29 |