관리 메뉴

IT Story

Dart 레코드(Records) 완벽 가이드: 개념, 사용법, 예제 총정리 본문

Programming/Dart

Dart 레코드(Records) 완벽 가이드: 개념, 사용법, 예제 총정리

#root 2025. 6. 9. 16:11

     

 

Dart 3부터 도입된 레코드(Records)는 Dart 개발자들에게 더 깔끔하고 간결한 방식으로 여러 값을 반환하거나 구조화된 데이터를 표현할 수 있는 방법으로 이 포스트에서는 Dart 레코드의 개념부터 실전 예제, 성능, 사용 사례까지 모든 내용을 정리합니다.


✅ Dart 레코드(Records)란?

**Dart 레코드(Records)**는 클래스나 구조체를 정의하지 않고도 여러 개의 값을 하나의 단위로 묶어서 사용할 수 있는 데이터 구조입니다. 간단히 말해, 레코드는 다양한 타입의 값들을 그룹화할 수 있는 튜플(tuple) 유사한 기능을 제공합니다.

Dart 3 이상에서 사용할 수 있으며, 복잡한 데이터 구조 없이 함수에서 다중 반환값을 리턴하거나, 임시 데이터 구조를 다루는 데 유용합니다.


📦 Dart 레코드 문법

레코드는 () 안에 여러 값을 나열하여 생성합니다.

// 위치 기반 레코드
var record1 = ('홍길동', 30, true);

// 명명된 필드 포함
var record2 = (name: '홍길동', age: 30, isActive: true);

// 혼합된 형태
var record3 = ('홍길동', age: 30, true);

레코드 타입 지정

(String, int, bool) person = ('홍길동', 30, true);

명명된 필드의 경우:

({String name, int age, bool isActive}) person = (name: '홍길동', age: 30, isActive: true);

🎯 Dart 레코드의 주요 특징

  • 불변성(Immutability): 기본적으로 불변이지만 var 또는 final에 따라 다릅니다.
  • 위치 기반/명명 기반 모두 지원
  • 함수 반환값으로 이상적
  • 구조 분해(Destructuring) 지원

🧪 Dart 레코드 예제

1. 기본 사용 예제

void main() {
  var person = ('홍길동', 30, true);
  print(person); // (홍길동, 30, true)
}

2. 명명된 필드 사용 예제

void main() {
  var user = (name: '김영희', age: 25);
  print(user.name); // 김영희
  print(user.age);  // 25
}

3. 레코드를 함수의 반환값으로 사용하기

(String, int) getUserInfo() {
  return ('이철수', 40);
}

void main() {
  var (name, age) = getUserInfo();
  print('이름: $name, 나이: $age');
}

4. 명명된 레코드 반환

({String name, int age}) getUser() {
  return (name: '박지성', age: 42);
}

void main() {
  var user = getUser();
  print(user.name); // 박지성
}

🔍 Dart 레코드 vs 클래스: 언제 사용할까?

항목 레코드 클래스

선언 간결성 매우 간단함 복잡한 구조 가능
불변성 기본적으로 불변 선택적
사용 용도 임시 데이터, 다중 반환 명확한 구조 필요 시
코드 재사용 제한적 상속/믹스인 가능

TIP: 레코드는 Value Object를 대신하기보다는 간단한 데이터 전달이나 함수 다중 반환에 적합합니다.


🔧 Dart 레코드 구조 분해(Destructuring)

Dart에서는 레코드 값을 간편하게 변수로 분해할 수 있습니다.

var person = ('홍길동', 30);
var (name, age) = person;

print(name); // 홍길동
print(age);  // 30

명명된 레코드는 직접 프로퍼티로 접근:

var person = (name: '김하늘', age: 27);
print(person.name); // 김하늘

📈 실전 예제: 레코드를 이용한 API 응답 처리

({bool success, String message}) submitForm(String name) {
  if (name.isEmpty) {
    return (success: false, message: '이름을 입력하세요.');
  }
  return (success: true, message: '제출 완료');
}

void main() {
  var response = submitForm('홍길동');
  print(response.message); // 제출 완료
}

🔐 Dart 레코드의 타입 안전성과 null 처리

레코드는 일반적인 타입 시스템과 잘 통합됩니다. 예를 들어:

(String?, int?) person = (null, null);

또는 null-safe 레코드 선언:

({String? name, int? age}) user = (name: null, age: null);

 

📚 레코드 관련 자주 묻는 질문(FAQ)

Q1. Dart 레코드는 리스트나 맵보다 나은가요?

  • 레코드는 명확한 필드 구조가 있을 때 리스트보다 훨씬 타입 안정성이 높습니다. 하지만 컬렉션에는 적합하지 않습니다.

Q2. 레코드는 클래스를 대체하나요?

  • 아닙니다. 간단한 데이터 표현이나 임시 사용에 적합합니다. 복잡한 로직이나 메서드가 필요한 경우 클래스가 더 적합합니다.

Q3. 레코드 안에 레코드를 중첩할 수 있나요?

  • 네, 가능합니다. 예:
var nested = ((1, 2), (x: 3, y: 4));
print(nested.$1); // (1, 2)
print(nested.$2.x); // 3

🏁 마무리 및 결론

**Dart의 레코드(Records)**는 간결하고 효율적인 데이터 표현을 가능하게 하는 강력한 기능입니다. 특히 Flutter 개발자나 Dart 기반 백엔드 프로젝트에서 불필요한 클래스 선언을 줄이고, 함수에서 여러 값을 반환할 때 매우 유용합니다.

Dart 3 레코드 사용법을 제대로 이해하고 나면, 코드의 가독성, 생산성, 성능까지 향상됩니다. 이 글을 통해 Dart 레코드에 대한 기본 개념부터 실전 활용까지 마스터하셨기를 바랍니다.


🔗 관련 링크


📌 Dart 레코드에 대해 궁금한 점이 있다면 댓글로 남겨주세요. 다음 포스트에서는 Flutter UI와 레코드를 함께 사용하는 방법을 다뤄보겠습니다.