Laravel 프레임웍에서 Controller를 Controller, Service, Repository 패턴으로 확장하기

Laravel 프임워크의 MVC 패턴

Laravel은 웹 애플리케이션의 개발을 위한 PHP 프레임워크로, MVC (Model-View-Controller) 패턴을 기반으로 설계되어있다. MVC는 소프트웨어 디자인 패턴 중 하나로, 애플리케이션 로직을 세 가지 주요 구성 요소로 분리하여 유지 보수성을 높이고, 확장성을 갖추며, 코드 재사용을 용이하게 한다.

때문에 Laravel의 MVC 패턴을 사용하면 애플리케이션의 로직과 사용자 인터페이스를 분리하여 관리할 수 있다. 이로 인해 코드의 가독성과 유지 보수성이 향상되며, 여러 개발자가 함께 작업할 때도 각 부분의 역할과 책임이 명확하게 구분되어 효율적인 협업이 가능해진다.

Laravel 프레임워크의 Controller를 세분화 시켰을 때 장단점

사실 Controller, Service, Repository로의 세분화는 Spring 및 Spring Boot 프레임워크의 사용자들이 Component를 더 효율적으로 사용하기위해 만들어낸 거라고 해도 무방하다. 그렇기 때문에 Laravel 프로젝트에서 컨트롤러, 서비스, 레포지토리로 로직을 분리하면 코드의 유지 보수와 확장성이 향상된다. Controller, Service, Repository로 로직을 분리할 경우의 장단점은 다음과 같다.

장점:

  1. 단일 책임 원칙 (Single Responsibility Principle):
    • 각 구성 요소는 각각 하나의 책임만을 가지게 되어 코드의 깔끔함과 명확성이 증가한다. Controller는 요청의 처리와 응답 반환에, Service는 비즈니스 로직에, Repository는 데이터 액세스 로직에 집중할 수 있다.
  2. 재사용성:
    • Service나 Repository의 메서드들은 다양한 컨트롤러나 서비스에서 재사용될 수 있다. 특히, 일반적인 CRUD 작업이나 비즈니스 로직을 한 곳에서 관리하므로 중복 코드를 줄일 수 있다.
  3. 테스트 용이성:
    • 코드가 모듈화되면, 각 구성 요소를 독립적으로 테스트하기가 쉬워진다. 특히 Mock 객체를 사용하여 데이터베이스나 외부 서비스와의 의존성 없이 테스트를 수행할 수 있게 된다.
  4. 유지 보수성:
    • 로직이 명확하게 분리되어 있으면, 변경이나 확장이 필요할 때 해당 부분만을 수정하면 된다. 이로 인해 유지 보수 비용이 줄어든다.
  5. 코드의 명확성:
    • 코드 구조가 명확해져서 새로 프로젝트에 참여하는 개발자가 시스템을 빠르게 이해할 수 있게 된다.

단점:

  1. 초기 구축 복잡성:
    • 각 구성 요소를 분리하는 것은 초기에 시간과 노력이 더 필요하게 된다. 간단한 애플리케이션의 경우 오버헤드로 느껴질 수 있다.
  2. 파일 및 클래스 증가:
    • 로직이 세분화되면서 프로젝트의 파일과 클래스 수가 늘어날 수 있는데, 이로 인해 디렉토리 구조와 네이밍에 더 많은 주의를 기울여야 할 수도 있다.

결론적으로, Controller, Service, Repository 패턴의 분리는 대규모 프로젝트나 팀에서 작업할 때 특히 유용하다고 생각한다. 그러나 소규모 프로젝트나 단독으로 작업할 때는 해당 패턴의 모든 장점이 필요하지 않을 수도 있으므로 프로젝트의 상황과 필요에 따라 적절한 구조를 선택하는 것이 중요하다.

Controller -> Controller, Service, Respository 분리하기

Controller, Service, Repository 패턴을 사용하여 간단한 사용자 조회 로직을 구현하는 예제를 작성해보자.

Repository: 데이터베이스 액세스 로직을 캡슐화한다.

// UserRepository.php

namespace App\Repositories;

use App\Models\User;

class UserRepository
{
    public function findById($id)
    {
        return User::find($id);
    }
}

Service: 비즈니스 로직을 정의한다.

// UserService.php

namespace App\Services;

use App\Repositories\UserRepository;

class UserService
{
    protected $userRepository;

    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function getUser($id)
    {
        return $this->userRepository->findById($id);
    }
}

Controller: 요청을 처리하고 응답을 반환한다.

// UserController.php

namespace App\Http\Controllers;

use App\Services\UserService;
use Illuminate\Http\Request;

class UserController extends Controller
{
    protected $userService;

    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    public function show($id)
    {
        $user = $this->userService->getUser($id);
        return view('user.show', ['user' => $user]);
    }
}