특성의 개념
특성(Attribute)은 System.Attribute를 상속하는 클래스로, 클래스나 메서드 같은 대상에 적용됩니다. 컴파일 시 특성 인스턴스 정보가 어셈블리 메타데이터에 포함되며, 실행 로직을 직접 변경하지는 않지만 런타임에 다른 코드에서 읽어 동작을 제어하거나 추가 정보를 제공합니다.
기본 제공 특성 예시
Obsolete
[Obsolete("NewMethod를 사용하세요")]
public void LegacyMethod() { }
Serialization 제어
[Serializable]
public class UserData
{
public string UserName;
[NonSerialized] private int sessionId;
}
Conditional
[Conditional("DEBUG")]
public void TraceLog() { }
사용자 정의 특성 생성
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
Inherited = false, AllowMultiple = true)]
public class CodeMetadataAttribute : Attribute
{
public string Note { get; }
public int Revision { get; set; }
public CodeMetadataAttribute(string note) => Note = note;
}
AttributeUsage 파라미터:
- AttributeTargets: 적용 대상(클래스, 메서드 등)
- AllowMultiple: 중복 적용 허용
- Inherited: 상속 여부
특성 적용 방법
[CodeMetadata("샘플 클래스", Revision = 2)]
public class Sample
{
[CodeMetadata("테스트 메서드")]
public void Test() { }
}
리플렉션을 통한 특성 읽기
Type type = typeof(Sample);
var attr = type.GetCustomAttribute<CodeMetadataAttribute>();
Console.WriteLine($"설명: {attr.Note}, 버전: {attr.Revision}");
주요 활용 사례
- 직렬화 제어:
[XmlIgnore],[JsonPropertyName] - 데이터 검증:
[Required],[Range] - ORM 매핑:
[Table],[Column] - 권한 관리:
[Authorize] - 단위 테스트:
[TestMethod],[Fact]
검증 프레임워크 예제
public class MemberProfile
{
[RequiredValidation("ID 필수 입력")]
public string UserId { get; set; }
[RangeValidation(18, 99, "나이 범위 오류")]
public int Age { get; set; }
}
public static class ValidationEngine
{
public static bool Check(object target, out string error)
{
foreach (var prop in target.GetType().GetProperties())
{
var reqAttr = prop.GetCustomAttribute<RequiredValidationAttribute>();
if (reqAttr != null && string.IsNullOrEmpty(prop.GetValue(target)?.ToString()))
{
error = reqAttr.ErrorMessage;
return false;
}
}
error = null;
return true;
}
}
중요 고려사항
- 특성 매개변수는 컴파일 타임 상수여야 함
- 리플렉션 성능 오버헤드 주의(캐싱 권장)
- 특성 자체는 동작하지 않음 - 해석 로직 필요