본문 바로가기

Personal Posting/Flutter

Dart 프로그래밍에서의 애노테이션(Annotations)

 

Annotation.. 최근까지는 어노테이션이라고 많이 읽었는데 영문으로 된 유튜브를 볼 때 거의 애노테이션으로 발음하는 것 같아 애노테이션으로 명기하기로 했다.

 

Annotation이란?

애노테이션은 클래스, 함수, 변수 등 다양한 코드 요소에 추가적인 정보를 제공하는 메타데이터이다. Dart에서는 @ 기호를 사용하여 애노테이션을 표시하며, 이는 컴파일타임 상수(const)로 정의된 값이어야 한다.

class Parent {
  void doSomething() {
    print('Doing something in Parent');
  }
}

class Child extends Parent {
  @override
  void doSomething() {
    print('Doing something in Child');
  }
}

void main() {
  var child = Child();
  child.doSomething(); // Output: Doing something in Child
}

 

주요 사용 사례

1. 문서화: 자동으로 문서를 생성하는데 활용

2. 코드 생성: 'build_runner'와 같은 도구가 애노테이션을 사용해 보일러플레이트 코드를 생성한다.

✓ 보일러플레이트 코드 (boilerplate code): 여러 곳에서 반복적으로 사용되며, 거의 변경되지 않는 코드를 의미하며, 주로 기본적인 구조나 설정을 제공하는 데 사용된다.

3. 검증: 데이터 검증 또는 코딩 표준 준수를 돕는다.

 

@override: 메서드가 슈퍼클래스의 메서드를 재정의하도록 의도되었음을 나타낸다.
@deprecated: 기능을 더 이상 사용하지 않음으로 표시하여 사용하면 안된다는 것을 알린다.

 

커스텀 애노테이션 만들기

Dart에서 커스텀 애노테이션을 만드는 것은 간단하다. 애노테이션을 클래스로 정의한 다음 인스턴스화한다.

 

클래스 정의

class RequiresPermission {
  final String permission;
  const RequiresPermission(this.permission);
}

 

사용 예제

class NetworkService {
  @RequiresPermission("Internet")
  void fetchData() {
    print("Fetching data from the internet...");
  }
}

 

위 예시에서:

  • 커스텀 애노테이션인 RequiresPermission이 정의되어 있으며, 문자열 permission을 가지고 있다.
  • NetworkService 클래스에는 인터넷 권한이 필요하다는 것을 나타내는 @RequiresPermission 애노테이션이 달린 fetchData 메서드가 있다.

 

 

실행 시점에서의 애노테이션 활용

애노테이션 자체는 실행 로직을 변경하지 않는다. 런타임에서 이를 해석하려면 리플렉션이나 코드 생성을 활용해야 한다.

 리플렉션은 프로그램이 실행 중에 자신의 구조(클래스, 메서드, 변수 등)를 검사하고 조작할 수 있는 프로그래밍 기술이다. 이를 통해 컴파일 시점에 알 수 없는 객체의 정보를 런타임에 동적으로 확인하거나 수정할 수 있다.

 

source_genbuild_runner를 활용한 코드 생성

Flutter 환경에서는 리플렉션 대신 source_gen과 같은 도구를 활용해 애노테이션 기반 코드를 자동으로 생성하는 것이 일반적이다.

# pubspec.yaml에 의존성 추가
dependencies:
  json_annotation: ^4.9.0

dev_dependencies:
  build_runner: ^2.4.14
  json_serializable: ^6.9.3

 

예제

import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable()
class User {
  final String name;
  final int age;

  User({required this.name, required this.age});

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

 

위와 같이 @JsonSerializable() 애노테이션을 사용하면 JSON 직렬화/역직렬화 코드를 자동으로 생성할 수 있다.

 

결론

Dart의 애노테이션은 메타데이터를 제공하여 코드의 가독성과 유지보수성을 높이고, 런타임 또는 컴파일 타임 작업을 효율적으로 처리하는 데 매우 유용하다. 특히 Flutter 환경에서는 리플렉션 대신 source_gen과 같은 도구를 사용하는 것이 권장되는 편이다.

 

 

 

 

아래 링크의 포스팅을 참고하여 정리한 내용입니다. 원문을 확인하고 싶으시면 아래 링크를 확인해주세요.

출처 - https://blog.nonstopio.com/exploring-annotations-in-dart-programming-ae6a8e4b8624