Dart에서 어노테이션은 코드에 메타데이터를 추가하는 강력한 도구입니다.
마치 책에 책갈피를 달거나 하이라이트를 칠하는 것처럼, 어노테이션은 코드에 추가적인 정보를 제공하여 코드를 더욱 이해하기 쉽고 유지 관리하기 용이하게 만들어줍니다.
이 블로그 게시글에서는 Dart에서 어노테이션의 기본 개념부터 다양한 사용법까지, 초보자도 쉽게 이해할 수 있도록 심층적으로 살펴보겠습니다.
1. 어노테이션이란 무엇일까요?
어노테이션은 클래스, 함수, 변수, 매개변수 등 다양한 코드 요소에 추가할 수 있는 특별한 문자 시퀀스입니다.
어노테이션은 다음과 같은 다양한 목적으로 사용됩니다.
- 코드 문서화: 어노테이션을 사용하여 코드의 기능, 사용 방법, 제약 조건 등을 명확하게 설명할 수 있습니다. 이는 코드를 이해하고 사용하는 다른 개발자들에게 큰 도움이 됩니다.
- 코드 구성 및 조직화: 어노테이션을 사용하여 코드를 논리적으로 그룹화하고 분류할 수 있습니다. 이는 코드를 더욱 읽기 쉽고 유지 관리하기 용이하게 만듭니다.
- 코드 제어 및 자동화: 어노테이션을 사용하여 컴파일러나 다른 도구가 코드를 처리하는 방식을 제어할 수 있습니다. 예를 들어, 테스트 코드를 식별하거나 특정 코드를 최적화하도록 지시하는 데 사용할 수 있습니다.
2. 어노테이션 사용 방법
어노테이션을 사용하려면 다음과 같은 단계를 따릅니다.
- 어노테이션 클래스 정의: 어노테이션을 나타내는 클래스를 정의합니다. 이 클래스는 어노테이션의 이름, 매개변수, 기타 속성을 정의합니다.
- 코드 요소에 어노테이션 추가: 어노테이션 클래스를 사용하여 코드 요소에 어노테이션을 추가합니다. 어노테이션은 @ 기호로 시작하며, 어노테이션 이름과 괄호 안에 매개변수 값 (있는 경우)을 지정합니다.
예시
// 어노테이션 클래스 정의
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CLASS, ElementType.FUNCTION})
class MyAnnotation {
final String message;
const MyAnnotation(this.message);
}
// 코드 요소에 어노테이션 추가
@MyAnnotation(message: "This is an example annotation.")
class MyClass {
// ...
}
설명
- @Retention(RetentionPolicy.RUNTIME) 어노테이션은 컴파일 후에도 어노테이션 정보가 유지되도록 합니다.
- @Target({ElementType.CLASS, ElementType.FUNCTION}) 어노테이션은 이 어노테이션이 클래스와 함수에 사용될 수 있음을 나타냅니다.
- MyAnnotation 클래스는 message이라는 문자열 매개변수를 가진 어노테이션을 정의합니다.
- @MyAnnotation(message: "This is an example annotation.") 은 MyClass 클래스에 MyAnnotation 어노테이션을 추가하고, message 매개변수에 "This is an example annotation." 값을 지정합니다.
3. 어노테이션 종류
Dart에서 제공하는 기본 어노테이션 종류는 다음과 같습니다.
- @Retention: 어노테이션 정보가 유지되는 기간을 지정합니다.
- @Target: 어노테이션을 사용할 수 있는 코드 요소를 지정합니다.
- @Deprecated: 코드가 더 이상 사용되지 않음을 나타냅니다.
- @Optional: 어노테이션 매개변수가 선택적임을 나타냅니다.
- @Default: 어노테이션 매개변수의 기본값을 지정합니다.
이 외에도 다양한 사용자 정의 어노테이션을 만들 수 있습니다.
4. 어노테이션 활용 사례
- 코드 문서화
/// This class represents a person.
@deprecated('Use `User` class instead.')
class Person {
/// The person's name.
final String name;
/// The person's age.
final int age;
Person(this.name, this.age);
}
위 코드에서 @deprecated 어노테이션은 Person 클래스가 더 이상 사용되지 않고 User 클래스를 대신 사용해야 한다는 것을 나타냅니다.
또한, 각 속성에 대한 주석은 코드의 기능을 명확하게 설명합니다.
- 코드 구성 및 조직화
@Todo('Implement this function')
void doSomething() {
// ...
}
위 코드에서 @Todo 어노테이션은 doSomething 함수가 아직 구현되지 않았음을 나타냅니다.
이는 코드를 논리적으로 그룹화하고, 해야 할 작업을 명확하게 파악하는 데 도움이 됩니다.
- 코드 제어 및 자동화
@Test()
void testMyFunction() {
// ...
}
위 코드에서 @Test 어노테이션은 testMyFunction 함수가 테스트 코드임을 나타냅니다.
이는 테스트 코드를 자동으로 실행하고 코드 품질을 유지 관리하는 데 도움이 됩니다.
5. 실습 문제
다음 문제를 해결해 봅시다.
문제
다음 상황을 모델링하기 위해 어노테이션을 사용하여 클래스를 설계하세요.
- 도서관을 나타내는 클래스를 만듭니다.
- 각 도서관에는 이름, 위치, 소장 도서 수 속성이 있어야 합니다.
- 도서관의 이름, 위치, 소장 도서 수를 출력하는 메서드를 작성합니다.
- 서로 다른 도서관 유형을 나타내는 클래스를 상속하여 만들고, 각 유형별 특징을 나타내는 속성과 메서드를 추가합니다.
- 예를 들어, 대중 도서관은 정부에서 운영되고, 대출 가능한 도서 수가 제한될 수 있습니다.
- 학술 도서관은 대학에서 운영되고, 연구 관련 자료가 풍부할 수 있습니다.
해결 팁
- Library 클래스를 만들어 도서관의 공통 속성과 메서드를 정의합니다.
- @Retention(RetentionPolicy.RUNTIME) 어노테이션을 사용하여 어노테이션 정보가 런타임까지 유지되도록 합니다.
- @Target({ElementType.CLASS}) 어노테이션을 사용하여 어노테이션이 클래스에만 사용될 수 있음을 나타냅니다.
- PublicLibrary 클래스와 AcademicLibrary 클래스를 만들어 Library 클래스를 상속받고, 각 유형별 특징을 나타내는 속성과 메서드를 추가합니다.
- @override 어노테이션을 사용하여 상속받은 메서드를 재정의합니다.
이 문제를 통해 어노테이션을 사용하여 코드를 설계하고 구성하는 방법을 연습할 수 있습니다.
정답
다음은 주어진 상황을 모델링하기 위해 어노테이션을 사용하여 설계한 클래스입니다.
import 'package:meta/meta.dart'; // 어노테이션을 사용하기 위해 meta 패키지를 가져옵니다.
@immutable // 클래스가 변경 불가능함을 나타냅니다.
abstract class Library {
final String name;
final String location;
final int bookCount;
Library({@required this.name, @required this.location, @required this.bookCount});
void printInfo() {
print("Name: $name");
print("Location: $location");
print("Book Count: $bookCount");
}
}
// 대중 도서관 클래스
class PublicLibrary extends Library {
final String 운영단체;
final int 대출가능도서수;
PublicLibrary({
@required String name,
@required String location,
@required int bookCount,
@required this.운영단체,
@required this.대출가능도서수,
}) : super(name: name, location: location, bookCount: bookCount);
@override
void printInfo() {
super.printInfo();
print("운영단체: $운영단체");
print("대출가능도서수: $대출가능도서수");
}
}
// 학술 도서관 클래스
class AcademicLibrary extends Library {
final String 연구자료수;
AcademicLibrary({
@required String name,
@required String location,
@required int bookCount,
@required this.연구자료수,
}) : super(name: name, location: location, bookCount: bookCount);
@override
void printInfo() {
super.printInfo();
print("연구자료수: $연구자료수");
}
}
설명
- Library 클래스:
- @immutable 어노테이션으로 클래스가 변경 불가능함을 명시합니다.
- name, location, bookCount 속성을 가지고 일반적인 도서관의 정보를 나타냅니다.
- printInfo 메서드는 도서관 정보를 출력합니다.
- PublicLibrary 클래스:
- Library 클래스를 상속받고, 대중 도서관의 특징인 운영다체와 대출가능도서수 속성을 추가합니다.
- printInfo 메서드를 재정의하여 운영단체와 대출가능도서수 정보도 출력합니다.
- AcademicLibrary 클래스:
- Library 클래스를 상속받고, 학술 도서관의 특징인 연구자료수 속성을 추가합니다.
- printInfo 메서드를 재정의하여 연구자료수 정보도 출력합니다.
사용 예시
void main() {
PublicLibrary publicLibrary = PublicLibrary(
name: "Seoul Public Library",
location: "Seoul, South Korea",
bookCount: 100000,
운영단체: "Seoul Metropolitan Government",
대출가능도서수: 50000,
);
AcademicLibrary academicLibrary = AcademicLibrary(
name: "KAIST Library",
location: "Daejeon, South Korea",
bookCount: 500000,
연구자료수: 1000000,
);
publicLibrary.printInfo();
academicLibrary.printInfo();
}
출력
Name: Seoul Public Library
Location: Seoul, South Korea
Book Count: 100000
운영단체: Seoul Metropolitan Government
대출가능도서수: 50000
Name: KAIST Library
Location: Daejeon, South Korea
Book Count: 500000
연구자료수: 1000000
6. 마무리
이 블로그 게시글에서는 Dart에서 어노테이션의 기본 개념부터 다양한 사용법까지, 초보자도 쉽게 이해할 수 있도록 심층적으로 살펴보았습니다.
어노테이션을 활용하여 코드를 더욱 효과적으로 작성하고 유지 관리할 수 있기를 바랍니다.
더 궁금한 점이나 개선할 부분이 있다면 언제든지 코멘트를 남겨주세요.
'Dart > Study' 카테고리의 다른 글
Dart로 간단한 웹 서버 만들기: Shelf 패키지 사용법과 옵션 (0) | 2024.07.13 |
---|---|
Dart에서 어노테이션 심화 학습: 초보자를 위한 가이드 (0) | 2024.07.12 |
Dart에서 클래스 상속 심화 학습: 상속의 모든 것을 다루는 가이드 (0) | 2024.07.12 |
Dart에서 상속 배우기: 초보자를 위한 가이드 (0) | 2024.07.12 |
Dart에서의 상속과 믹싱: extends, with, implements (0) | 2024.07.12 |