Framework/Laravel

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

MingyuKim 2023. 11. 8.

Laravel 프임워크의 MVC 패턴

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

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

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

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

Laravel 프레임웍에서 Controller를 Controller, Service, Repository 패턴으로 확장하기 - Laravel 프레임워크의 Controller를 세분화 시켰을 때 장단점

장점:

  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]);
    }
}

댓글