개요

Attribute 는 메타 데이터(meta data)나 선언적 정보(declarative information)를 코드와 연결하는 강력한 방법입니다.

Java 에서는 annotation 이라고 부르며 C# 에서는 PHP 와 마찬가지로 Attribute 로 명명되어 있습니다.


Attribute 를 속성이라고 번역한 곳도 있던데 속성은 property 와 의미가 겹치므로 적당한 용어가 아니라고 생각합니다.

기술 번역의 레퍼런스인 Microsoft 의 언어 포털 사이트를 보면 attribute 를 '특성' 으로 번역하고 있으며 제가 생각하기에도 속성보다는 특성이 더 적당한 단어같으므로 이 글에서도 Attribute 를 특성이라고 지칭하겠습니다.


PHP 의 attribute 는 class, method, variable, parameter 등에 부여할 수 있으며 compiler time 과 runtime 에 attribute 를 이용해서 특별한 처리를 할 수 있습니다.

예로 PHPStorm 을 사용할 경우 불변 속성을 가진 변수에 대해 아래와 같이 attribute 를 지정하면 수정할 경우 IDE 에서 감지해서 에러를 표시하므로 코딩 실수를 줄일 수 있습니다.

<?php

use JetBrains\PhpStorm\Immutable;

class MyClass
{
    #[Immutable]
    private int $read_only_var;

    public function setValue(int $value): void
    {
        $this->read_only_var = $value;
    }
}
PHP

기존에 docblocks 에 @ 를 사용해서 annotation 을 달 경우 오타를 내거나 없는 annotation 을 사용해도 코드가 아니라 주석이므로 IDE 에서 에러를 감지하지 어려웠습니다.

Attribute 는 기존에 docblocks 사용한 주석에 비해 파싱 및 분석이 용이하므로 PHPStorm 같은 IDE 가 더 정확하게 동작하며 phpstan 이나 psalm 같은 정적 분석기가 더 정교하게 동작하는 장점이 있습니다.

또 docblocks 주석을 메모리까지 로딩해야 했던 기존 방식에 비해 JIT 으로 최적화가 용이하고 Run time 에 Reflection 을 더 빠르게 할 수 있으며 실행 시간도 더 짧아지지 않을까 추측합니다.


Symfony Doctrine 같은 유명한 PHP Framework 도 Attribute 를 지원하도록 수정되었고 psalm 이나 phpstan 도 Attribute 를 지원하는 버전을 발표했으므로 Attribute 을 잘 활용해서 좋은 품질의 코드를 작성하도록 연습이 필요한 시점입니다.


만약 attribute 의 필요성과 활용 방법이 잘 이해가 되지 않는다면 C# 이나 Java 에서 사용 방법을 찾아 보는 것도 많은 도움이 됩니다.

특히 Spring framework 를 잘 사용하려면 어지러울 정도로 수많은 annotation 을 활용한 meta programming 기법이 필요합니다.

문법

PHP 는 특성을 부여하는 문법으로 #[Attr] 을 사용하는데 이걸로 결정하기까지 여러 우여 곡절이 있었나 봅니다.(PHP Annotated – August 2020 (haah.kr) 참고)


use App\Attributes\ExampleAttribute;

#[ExampleAttribute]
class Foo
{
    #[ExampleAttribute]
    public const FOO = 'foo';
 
    #[ExampleAttribute]
    public $x;
 
    #[ExampleAttribute]
    public function foo(#[ExampleAttribute] $bar) { }
}
PHP


Laravel 8은 PHP 7.3 부터 지원하므로 Attribute 를 제대로 지원하고 있지는 않습니다. 대신 PHP 8 로 라라벨을 구동할 경우 Attribute 를 사용하는데 문제가 없습니다.

예로 PHP 8 을 사용한다면 라라벨 라우팅을 Attribute 로 관리하는 패키지인 spatie/laravel-route-attributes 를 이용해서 라우팅을 관리해 줘도 됩니다.

같이 보기

Ref