Repository Pattern(2)

Jimin·2023년 6월 5일
0

RepositoryPattern

목록 보기
2/3
post-thumbnail

본격적으로 Laravel을 이용하여 각 계층을 어떤 식으로 사용하는지 실습해보려 한다.
기본적인 예제만 다룰 예정이므로 회원 정보를 조회하는 로직을 예제로 사용한다.

필자는 아래와 같은 방법으로 사용했다.
(파일명과 파일경로는 자유이므로 꼭 필자의 경로와 같이 사용하지 않아도 무방하다.)

app
 ㄴ Http
 	 ㄴ Controllers
 ㄴ Models
 ㄴ Services
 ㄴ Repositoies
 ㄴ Interfaces

작업은 가장 먼저 제일 많이 사용되는 매서드 들을 추상화 시킬 예정이다.

Interface

app/Interfaces/BaseInterface.php

<?php

namespace App\Interfaces\Interfaces;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;

interface BaseInterface
{
    /**
     * @return Collection
     */
    public function all(): Collection;

    /**
     * @param int $id
     * @return Model
     */
    public function findId(int $id): Model;

    /**
     * @param array $data
     * @return Model
     */
    public function create(array $data = []): Model;

    /**
     * @param array $data
     * @return bool
     */
    public function update(array $data = []): bool;
    
    /**
     * @param array $data
     * @return bool
     */
    public function delete(array $data = []): bool;

}

해당 내용은 가장 기본적으로 사용되는 ORM의 매서드를 추상화 시키는 과정이다.
해당 패턴에 관련해서는 디자인 패턴(Factory Method Pattern)을 공부하는 걸 추천한다.

다음은 구현 클래스를 작성할 차례다.

Repositoty

app/Repositories/BaseRepository.php

<?php

namespace App\Repositories;

use App\Interfaces\BaseInterface;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;

class BaseRepository implements BaseInterface
{
    private Model $model;
    public function __construct(Model $model)
    {
        $this->model = $model;
    }

    /**
	 * @param array $columns
     * @param array $relations
     * @return : Collection
     */
    public function all(array $columns = ['*'], array $relations = []): Collection
    {
        return $this->model->get($columns);
    }

    /**
     * @param int $id
     * @param array $columns
     * @return Model
     */
    public function findId(int $id, array $columns = ['*'], array $relations = []): Model
    {
        return $this->model->find($id, $columns);
    }

    /**
     * @param array $data
     * @return Model
     */
    public function create(array $data = []): Model
    {
        return $this->model->create($data);
    }

    /**
     * @param array $data
     * @return bool
     */
    public function update(array $data = []): bool
    {
        return $this->model->update($data);
    }

    /**
     * @param array $data
     * @return bool
     */
    public function delete(array $data = []): bool
    {
        return $this->model->delete($data);
    }

}

해당 BaseRepository는 BaseInterface를 다중 상속(implements) 하고 있다.
이러한 경우 추상화되어있는 부모의 메소드를 반드시 재정의(Override) 해야 한다.

의존성 주입(Dependency Injection)

구현체에 매서드를 사용하기 위해서는 인터페이스를 바인딩 해야 한다. Laravel의 컨테이너를 이용하면 인터페이스와 구현체를 쉽게 인스턴스화 할 수 있다.
필자는 관리 중인 Repository를 한 파일에서 관리하기 위해 따로 파일을 생성할 예정이다.

php artisan make:provider RepositoryServiceProvider

Config/app.php

'providers' => [
	App\Providers\RepositoryServiceProvider::class,
]

까지 등록을 해준다. 그리고 생성된 파일에 인터페이스를 바인딩 한다.
app/Providers/RepositoryServiceProvider.php

<?php

namespace App\Providers;

use App\Repositories\Eloquent\BaseRepository;
use App\Repositories\Interfaces\BaseInterface;
use Illuminate\Support\ServiceProvider;

class RepositoryServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind(BaseInterface::class, BaseRepository::class);
    }

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

기본적인 추상화 과정은 끝났다. 다음 포스팅에서는 해당 매서드들과 추가적인 매서드를 통해서 회원 조회를 하는 로직을 완성해보자.

참고 자료
https://vuxy.tistory.com/entry/Laravel-8-%EC%97%90%EC%84%9C-Repository-%ED%8C%A8%ED%84%B4-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0
https://blog.decorus.io/php/2018/07/04/laravel-dependency-injection-container.html

profile
도전을 좋아하는 개발자

0개의 댓글