
AI와 인간 모두에게 친절한 Laravel 설계, Package By Feature
요약
AI 코딩 에이전트의 효율을 높이기 위해 기술 계층 중심의 Package By Layer 대신 기능 중심의 Package By Feature 설계를 제안합니다. 기능 단위로 디렉터리를 구성하면 AI의 컨텍스트 소비를 줄이고 설계 규칙을 강제할 수 있습니다.
핵심 포인트
- Package By Layer는 AI가 관련 파일을 찾기 위해 여러 디렉터리를 탐색해야 하는 비용이 발생함
- Package By Feature는 기능별로 코드를 응집시켜 AI의 컨텍스트 활용도를 극대화함
- 디렉터리 구조를 통해 AI가 지켜야 할 설계 규칙을 명시적으로 강제할 수 있음
- 새로운 기능 구현 시 기존 디렉터리를 템플릿으로 활용하여 AI 지시가 용이함
서론
최근 1년 정도 사이 AI 코딩 에이전트에게 코드를 작성해 달라고 요청하는 기회가 급격히 늘었다. 아니, 거의 대부분의 코드를 작성해 주고 있다. 사용하면서 느낀 점은, Controller·Service·Repository와 같이 기술적인 계층(Layer)으로 디렉터리를 나누는 이른바 Package By Layer(기술 단위로 디렉터리를 나누는 구성)는 AI와 그리 궁합이 좋지 않다는 것이다.
반면, Package By Feature(기능 단위로 디렉터리를 나누는 구성)로 하면 AI도 인간도 다루기 쉬워지는 경우가 많았다. 이 기사에서는 그 이유와 실제로 어떤 구성을 했는지 샘플 리포지터리를 곁들여 써 내려가고자 한다.
레이어드 아키텍처(Layered Architecture)에서 느끼고 있던 문제
Laravel에서 흔히 볼 수 있는 구성은 다음과 같다.
app/
├── Http/Controllers/TaskController.php
├── Services/TaskService.php
...
Task라는 하나의 기능만 수정하려 해도 파일은 4개의 디렉터리에 걸쳐 있다. 인간은 프로젝트에 대한 지형지물(Context)을 알고 있기에 그리 고통스럽지 않지만, AI에게 코드를 작성하게 할 때는 이 "여기저기 찾아다니는" 비용이 그대로 영향을 미친다.
구체적으로는,
- 관련 파일을 찾기 위해 여러 디렉터리를 grep하거나 읽으러 가는 횟수가 늘어난다. 컨텍스트(Context)를 불필요하게 소비한다.
- Service가 어디까지 책임을 가질지, Repository는 어디까지 얇게(Thin) 만들지 같은 암묵적인 규칙을 AI는 모른다. 매번 미묘하게 다른 설계로 작성된다.
- 영향 범위를 잘못 예측하여 관계없는 파일까지 건드려 버린다.
와 같은 일이 일어나기 쉬웠다.
Package By Feature란
기술적인 계층이 아니라, 기능(Feature)을 제1의 분할 단위로 삼는 사고방식이다. 1기능 = 1디렉터리로 하며, 해당 기능에 관한 코드는 원칙적으로 그 디렉터리 안에 가두어 둔다.
app/Features/Task/
├── TaskController.php
├── Requests/
...
Controller, UseCase(비즈니스 로직), Resource와 같은 역할 자체는 기존과 동일하게 나누어져 있지만, 그것들은 "Task"라는 디렉터리 안에 갇혀 있다. 무언가를 고칠 때는 이 1개의 디렉터리만 보면 된다.
왜 AI와 궁합이 좋은가
이유는 단순하다. 1기능의 변경에 필요한 정보가 1디렉터리에 수렴되어 있기 때문이다. AI에게 "Task에 ◯◯라는 항목을 추가해 줘"라고 부탁하면, app/Features/Task/ 아래만 보고도 완결할 수 있다. 다른 Feature의 Service나 Repository를 신경 쓸 필요가 없다.
새로운 Feature를 만들 때도 기존의 Feature 디렉터리를 통째로 복사해서 이름을 바꾸는 것만으로 템플릿이 된다. 이는 AI에게 지시할 때도 편리하여, "Task 디렉터리와 동일한 구성으로 Order라는 기능을 만들어 줘"라고 부탁하는 것만으로 기존 규칙에 따른 구현을 받아내기 쉽다.
레이어드(Layered) 구성에서는 "Service의 책임", "Repository의 입도(Granularity)"와 같이 코드만으로는 읽어내기 어려운 암묵적인 규칙이 AI와의 사이에서 어긋나기 쉽다. Package By Feature는 그러한 규칙을 디렉터리 구조 자체로 강제할 수 있으므로 AI에 대한 지시 비용이 낮아진다.
Feature 내부는 Controller/UseCase/Resource와 같이 기술 계층으로 나누어져 있지만, 이는 AI가 찾아가는 범위가 "1디렉터리 내부"에 수렴되어 있다면 문제가 되지 않는다. Feature "간"에 기술 계층을 가로지르게 하지 않는 것이 중요하다고 생각한다.
하지만, 인간도 읽지 못하면 의미가 없다
지금까지 AI와의 궁합에 대해 이야기해 왔지만, 코딩을 AI에게 전부 맡길 수 있다면 인간이 읽기 쉬운지는 상관없다는 뜻으로 말하는 것은 아니다.
AI는 무제한으로 쓸 수 있는 것이 아니다. 개인 계약 플랜에도 기업의 이용에도 예산 상한이 있으며, 예산이 매우 풍족한 조직이 아닌 한, 월 중간에 한도에 도달하거나 비용 의식 때문에 AI에 의존하지 않고 직접 작성하는 상황은 흔히 발생한다. 즉, 인간이 코드를 직접 읽거나 작성할 가능성은 AI 시대에도 (※현 시점에서는) 충분히 남아 있다.
따라서 "AI를 위해 최적화되어 있지만 인간에게는 읽기 어려운" 구성은 곤란하다. 다행히 Package By Feature는 기술 계층을 횡단하지 않아도 되는 만큼 인간에게도 인지 부하가 낮다. "Task의 동작을 고치고 싶다면 app/Features/Task/
를 보면 된다」는 점은 AI에게도, 리뷰하는 인간에게도 마찬가지로 적용된다. AI와 인간을 위해 각각 별도로 최적화할 필요 없이 양쪽 모두에게 효과적이라는 것이 이 구성을 추천하는 가장 큰 이유이다.
샘플 구현으로 보는 구성
실제로 직접 구현하여 테스트한 내용을 laravel-feature-template라는 이름으로 리포지토리에 올려두었다. 특정 프로젝트의 비즈니스 로직은 포함되어 있지 않으며, Task라는 범용적인 CRUD만을 샘플로 동봉하고 있다.
디렉토리 구성
src/app/
├── Features/
│ └── Task/ # 1기능 = 1디렉토리
...
요청(Request)은 Router → Middleware → Controller → FormRequest → Input DTO → UseCase → Model → Resource라는 일직선 경로로 흐른다. Task의 생성(store) 처리를 예로 들어 살펴보자.
Controller는 얇게 유지되며, 1메서드 1액션(Action) 구조로 되어 있다.
public function store(StoreTaskRequest $request, StoreTaskAction $action): JsonResponse
{
return (new TaskResource($action->execute($request->toInput())))
...
FormRequest는 유효성 검사(Validation)를 수행한 후, Input DTO로 변환하는 역할까지 담당한다.
public function rules(): array
{
return [
...
UseCase는 비즈니스 로직 본체이다. execute() 메서드를 단 하나만 가진다.
final class StoreTaskAction
{
public function execute(StoreTaskInput $input): Task
...
마치며
Package By Feature는 은탄환(Silver Bullet)이 아니다. 기능(Feature) 간에 걸쳐 있는 처리가 늘어나는 프로젝트에서는 Shared를 어디에 둘지 고민하는 상황이 생길 것이고, 작은 애플리케이션에서는 솔직히 Feature로 나눌 필요조차 없는 경우도 있다.
그럼에도 불구하고 AI와 함께 코드를 작성하는 기회가 늘어난 지금, 「하나의 변경이 하나의 디렉토리에서 완결된다」는 특성은 AI의 컨텍스트(Context) 소비를 줄이는 측면에서도, 인간이 읽는 측면에서도 효과적이라는 실감이 든다. 아직 시도하는 중이긴 하지만, 비슷한 고민을 하는 분들에게 참고가 되기를 바란다.
참고로 중~대규모 프로젝트에서는 Features/StoreTask/와 같이 액션(Action) 단위로 디렉토리를 나누는 방법(Vertical Slice Architecture?)도 좋을 수 있다고 생각하고 있다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기