메타데이터

메타데이터 (Metadata)

Dart에서 메타데이터(annotation)를 활용하면 코드에 추가적인 정적 정보를 담을 수 있어요. 무엇을 어떻게 붙이는지, 어떤 게 내장되어 있는지 함께 살펴볼게요.

출처: Dart 공식 문서

본문

메타데이터를 쓰면 코드에 추가적인 정적 정보를 제공할 수 있어요. 메타데이터 annotation은 @ 문자로 시작하며, 그 뒤에 컴파일 타임 상수(deprecated 같은 것)에 대한 참조나 상수 생성자에 대한 호출이 따라와요.

메타데이터는 선언이나 지시문 앞에 annotation을 붙이는 방식으로 대부분의 Dart 프로그램 구조에 연결할 수 있어요.

내장 annotation (Built-in annotations)

다음 annotation들은 모든 Dart 코드에서 사용할 수 있어요.

@Deprecated

선언을 더 이상 쓰지 말아야 한다고 표시해요. 대체할 것이 무엇인지, 그리고 언제 제거될지 설명하는 메시지를 함께 지정하고, 해당 선언에서 멀리 옮겨가도록 유도해요.

일반적인 @Deprecated annotation 외에도, 특정 용법만 폐기하는 구체적인 annotation을 쓸 수 있어요.

  • @Deprecated.extend(): 클래스를 확장(extend)하는 것이 폐기됐어요.
  • @Deprecated.implement(): 클래스나 믹스인을 구현(implement)하는 것이 폐기됐어요.
  • @Deprecated.subclass(): 클래스나 믹스인을 상속(서브클래싱)하는 것이 폐기됐어요.
  • @Deprecated.mixin(): 클래스를 믹스인(mixin)으로 섞는 것이 폐기됐어요.
  • @Deprecated.instantiate(): 클래스를 인스턴스화하는 것이 폐기됐어요.
  • @Deprecated.optional(): 해당 파라미터에 인자를 생략하는 것이 폐기됐어요.

@Deprecated annotation을 쓰는 예시를 볼게요.

class Television {
  /// Use [turnOn] to turn the power on instead.
  @Deprecated('Use turnOn instead')
  void activate() {
    turnOn();
  }

  /// Turns the TV's power on.
  void turnOn() {
    // ···
  }
  // ···
}

@deprecated

선언이 언제까지인지 특정하지 않은 미래 릴리스까지 폐기됨을 표시해요. 되도록 @Deprecated를 쓰고 폐기 메시지를 제공하는 쪽을 권장해요.

@override

인스턴스 멤버가 부모 클래스나 인터페이스의 같은 이름을 가진 멤버를 오버라이드하거나 구현한 것임을 표시해요. @override 사용 예시는 클래스 확장(Extend a class)에서 볼 수 있어요.

@pragma

컴파일러나 analyzer 같은 Dart 도구에 선언에 대한 특정 지시나 힌트를 제공해요.

Dart analyzer@override annotation이 필요한지, 그리고 @deprecated@Deprecated로 표시된 멤버를 사용할 때 진단(diagnostic) 형태로 피드백을 제공해요.

Analyzer가 지원하는 annotation (Analyzer-supported annotations)

내장 annotation에 대한 지원과 분석을 넘어, Dart analyzerpackage:meta의 다양한 annotation에 대한 추가 지원과 진단도 제공해요. 이 패키지가 제공하는 자주 쓰이는 annotation 몇 가지를 볼게요.

@visibleForTesting

패키지의 멤버를 테스트에서만 접근할 수 있도록 public으로 표시해요. analyzer는 이 멤버를 자동완성 제안에서 숨기고, 다른 패키지에서 사용하면 경고해요.

@awaitNotRequired

Future 타입을 가진 변수나 Future를 반환하는 함수가 호출자에게 Future를 await하도록 요구하지 않아도 됨을 표시해요. 이러면 discarded_futuresunawaited_futures 린트 때문에 await하지 않은 호출자에게 analyzer가 경고하지 않아요.

이 패키지가 제공하는 다른 annotation들과 그것들이 무엇을 뜻하는지, 어떤 기능을 켜는지, 어떻게 쓰는지 더 배우려면 package:meta/meta.dart API 문서를 확인해 보세요.

커스텀 annotation (Custom annotations)

자신만의 메타데이터 annotation을 정의할 수도 있어요. 두 개의 인자를 받는 @Todo annotation을 정의하는 예시를 볼게요.

class Todo {
  final String who;
  final String what;

  const Todo(this.who, this.what);
}

그리고 그 @Todo annotation을 사용하는 예시예요.

@Todo('Dash', 'Implement this function')
void doSomething() {
  print('Do something');
}

자신의 annotation으로 표시할 언어 구조의 종류를 나타내려면 package:meta@Target annotation을 사용해요.

예를 들어 앞선 @Todo annotation을 함수와 메서드에만 허용하고 싶다면, 다음과 같이 추가하면 돼요.

import 'package:meta/meta_meta.dart';

@Target({TargetKind.function, TargetKind.method})
class Todo {
  // ···
}

이렇게 설정하면 analyzer는 최상위 함수나 메서드가 아닌 다른 선언에 Todo를 annotation으로 사용할 때 경고해요.

더 알아보기