예제 소스코드 같은 걸 구해서 보면 클래스 또는 메서드 위에 [TestMethod] 이런 식으로 [ ]로 무언가가 명시되어 있습니다.
어트리뷰트(Attribute)라고 하는데 개발하는데 반드시 필요한 것은 아니라서 사용하지 않더라도 개발을 못하는 것은 아닙니다. 저도 이번 기회에 좀 알아봤는데 재미있습니다.
✅ 어트리뷰트 (Attribute)
C#의 어트리뷰트(Attribute)는 코드의 메타데이터를 나타내는 데 사용되는 선언적 태그입니다. 이는 클래스, 메서드, 속성, 이벤트, 필드 등과 같은 다양한 프로그래밍 요소에 추가 정보를 제공할 때 사용됩니다.
어트리뷰트의 장점
어트리뷰트는 추가정보를 제공할 수 있다는 점에서 유용한데 이는 컴파일타임, 런타임 모두 해당됩니다.
- 컴파일러에게 추가적인 정보를 제공하여 컴파일 과정에서 처리하도록 할 수 있습니다. 예를 들어, [Obsolete] 어트리뷰트는 해당 프로그래밍 요소가 더 이상 사용되지 않음을 나타내고, 컴파일러는 경고 메시지를 표시합니다.
- 프레임워크 또는 라이브러리가 코드를 처리할 때 런타임에 추가 정보를 제공할 수 있습니다. 예를 들어, ASP.NET에서는 [Authorize] 어트리뷰트를 사용하여 특정 컨트롤러 액션에 대한 인증을 요구할 수 있습니다.
- 코드의 가독성과 유지 관리를 향상하기 위해 주석처럼 사용할 수 있습니다. 이를 통해 코드의 특정 부분에 대한 의도나 동작을 명확하게 나타낼 수 있습니다.
어트리뷰트를 사용할 수 있는 대상
|
쉽게 말해서 클래스, 메서드 등에 추가적인 속성을 부여하는 것입니다. 어트리뷰트가 붙어있으면 이 함수가 어떤 용도로 사용되는지 소스코드 상에서 추측이 가능합니다.
위에 언급한 것과 같이 [TestMethod]라고 명시되어 있다면 TestMethod '이 함수는 Test에 사용하는 함수구나'라고 알 수 있습니다.
하지만 어트리뷰트의 진짜 재미있는 부분은 Reflection과 함께 사용할 때입니다.
Reflection - Attribute는 추후에 포스팅하고 이번 글은 어트리뷰트에 대한 내용만 언급하겠습니다.
기본 어트리뷰트
. NET에서 제공하는 기본 어트리뷰트는 다음과 같습니다.
Attribute | Description |
AttributeUsageAttribute | This attribute specifies the usage of a different attribute. |
CLSCompliantAttribute | This attribute shows if a particular code element complies with the Common Language Specification. |
ContextStaticAttribute | This attribute designates that a static field should not be shared between contexts. |
FlagsAttribute | The FlagsAttribute specifies that an enumeration can be used as a set of flags. This is most commonly used with bitwise operators. |
LoaderOptimizationAttribute | This attribute sets the optimization policy for the default loader in the main method. |
NonSerializedAttribute | This attribute signifies that the field of the serializable class should not be serialized. |
ObsoleteAttribute | This attribute marks the code elements that are obsolete i.e. not in use anymore. |
SerializableAttribute | This attribute signifies that the field of the serializable class can be serialized. |
ThreadStaticAttribute | This attribute indicates that there is a unique static field value for each thread. |
DllImportAttribute | This attribute indicates that the method is a static entry point as shown by the unmanaged DLL. |
출처 : https://www.geeksforgeeks.org/attributes-in-c-sharp/
이중에 Serializable, DllImport 정도는 자주 사용합니다.
어트리뷰트 만들기
어트리뷰트는 System.Attribute 클래스를 상속받아야 합니다. 어트리뷰트를 사용하려는 프로그래밍 요소에 대해 대괄호([ ]) 안에 어트리뷰트를 선언하고, 필요한 경우 매개변수를 전달합니다.
어트리뷰트 기본 구조
// Custom attribute definition
public class CustomAttribute : Attribute
{
public string Description { get; }
public CustomAttribute(string description)
{
Description = description;
}
}
// Using the custom attribute
[Custom("This is a custom attribute for a class.")]
public class MyClass
{
[Custom("This is a custom attribute for a method.")]
public void MyMethod()
{
// Method implementation
}
}
위와 같이 사용자가 원하는 어트리뷰트를 만들 수 있습니다.
실사용 예제
실제 사용은 어떤 식으로 하게 되는지 예제를 들어보겠습니다.
LogAttribute.cs
using System;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class LogAttribute : Attribute
{
public string Message { get; }
public LogAttribute(string message)
{
Message = message;
}
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] 으로
Method 에만 적용되는 Log라는 어트리뷰트를 만들었습니다.
program.cs
using System;
using System.Reflection;
public class Program
{
[Log("Starting the example method.")]
[Log("Finishing the example method.")]
public static void ExampleMethod()
{
Console.WriteLine("Inside the example method.");
}
public static void Main(string[] args)
{
ExecuteMethodWithLogging(typeof(Program), nameof(ExampleMethod));
}
private static void ExecuteMethodWithLogging(Type type, string methodName)
{
MethodInfo methodInfo = type.GetMethod(methodName);
var logAttributes = methodInfo.GetCustomAttributes(typeof(LogAttribute), false);
// 로그 시작 메시지 출력
if (logAttributes.Length > 0 && logAttributes[0] is LogAttribute startLog)
{
Console.WriteLine(startLog.Message);
}
// 메서드 실행
methodInfo.Invoke(null, null);
// 로그 종료 메시지 출력
if (logAttributes.Length > 1 && logAttributes[1] is LogAttribute endLog)
{
Console.WriteLine(endLog.Message);
}
}
}
Main 함수에서 ExecuteMethodWithLogging를 호출하고 함수 내부에서는 Reflection으로 어트리뷰트를 읽어서 어트리뷰트 출력 및 ExampleMethod 함수를 실행하도록 되어있습니다.
위 코드에서 알 수 있듯이 어트리뷰트는 리플렉션과 함께 사용했을 때 많은 것을 할 수 있습니다.
다음 포스팅에서는 어트리뷰트 + 리플렉션에 대해 알아보겠습니다.