개발 지식

개발 지식

PHP 실무에서 PHP Trait 남용을 피하는 방법

페이지 정보

profile_image
영삼이
0건 200회 25-03-28 23:17

본문

✅ 실무에서 PHP Trait 남용을 피하는 방법

Trait는 PHP에서 다중 상속을 흉내낼 수 있게 해주는 기능으로, 여러 클래스 간 코드 재사용을 위해 도입되었습니다. 하지만 잘못 사용하면 코드 구조가 불명확해지고, 유지보수성이 급격히 낮아질 수 있습니다. 이 글에서는 Trait의 올바른 사용법과 남용을 피해야 하는 상황을 구체적으로 설명합니다.


🧩 Trait 기본 예시

[code=php]
trait LoggerTrait {
    public function log(string $message): void {
        file_put_contents('app.log', $message . PHP_EOL, FILE_APPEND);
    }
}

class UserService {
    use LoggerTrait;

    public function register() {
        $this->log("회원 가입 시도");
    }
}
[/code]
  • 공통 로직을 여러 클래스에서 공유 가능

  • 중복 코드 제거에 유리


❌ 잘못된 사용 사례: 책임 혼란

[code=php]
trait AuthTrait {
    public function checkPermission($user) {
        // 권한 체크
    }

    public function logLogin($user) {
        // 로그인 로그 남기기
    }

    public function sendLoginEmail($user) {
        // 이메일 발송
    }
}
[/code]
  • 하나의 Trait에 역할이 다른 메서드들이 섞여 있음

  • 재사용은 되지만 응집도 낮고 책임이 불명확


⚠️ Trait 남용 시 문제점

문제 설명
책임 분리 실패 단일 책임 원칙 위반 (SRP)
충돌 위험 여러 Trait이 동일한 메서드 포함 시 충돌 발생 가능
테스트 어려움 Trait 단위 테스트 불가능 (클래스에 의존해야 함)
IDE 탐색 불편 정의 위치가 분산되어 가독성 저하

✅ 올바른 사용 기준

1. 역할이 명확한 경우만 사용

[code=php]
trait TimestampTrait {
    protected DateTime $createdAt;

    public function setCreatedAt(DateTime $date): void {
        $this->createdAt = $date;
    }
}
[/code]
  • 도메인 상 "모든 엔티티가 생성일시를 가져야 한다"는 일관된 목적일 경우 OK


2. 작고 독립적인 기능만 포함

  • 하나의 Trait은 하나의 책임만 가지도록 구성

  • 이름도 LoggerTrait, SoftDeleteTrait 등 기능 중심으로 명확히


3. 가능하면 인터페이스 + 서비스 클래스로 분리 고려

[code=php]
interface LoggerInterface {
    public function log(string $message): void;
}

class FileLogger implements LoggerInterface {
    public function log(string $message): void {
        file_put_contents('app.log', $message, FILE_APPEND);
    }
}
[/code]

→ DI 컨테이너를 통해 주입하면 재사용성과 확장성이 훨씬 높아짐

---

### 💡 추천 사용 예

- 공통적인 상태 또는 유틸 함수 (예: `SoftDeletes`, `HasUuid`)
- 도메인 속성의 재사용 (`Timestamps`, `Blameable`)
- 의존성이 없고, 기능이 작고, 책임이 명확할 때

---

### 🧠 요약

- Trait은 **강력한 도구지만 양날의 검**
- 코드를 공유하려고 무작정 Trait에 때려 넣는 순간 유지보수 지옥
- 책임이 명확하고 작고 독립적인 기능만 포함할 것
- 클래스 구조가 복잡해지면 인터페이스와 서비스 클래스로 전환 고려

---

댓글목록

등록된 댓글이 없습니다.