Menu
Coddy logo textTech

레코드 (Dart 3)

Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 86번째.

Dart 3는 레코드(records)를 도입했습니다. 이는 전체 클래스를 생성하지 않고도 여러 값을 함께 묶을 수 있는 가벼운 방법입니다. 레코드는 불변이며, 내장된 동등성 비교 기능을 갖추고 있고, 함수에서 여러 값을 반환하거나 관련 데이터를 일시적으로 그룹화하는 데 적합합니다.

괄호로 값을 감싸서 레코드를 생성합니다:

void main() {
  // 두 개의 값을 가진 간단한 레코드
  var point = (10, 20);
  print(point.$1);  // 10 - 첫 번째 요소에 접근
  print(point.$2);  // 20 - 두 번째 요소에 접근
  
  // 이름이 있는 필드를 가진 레코드
  var person = (name: 'Alice', age: 30);
  print(person.name);  // Alice
  print(person.age);   // 30
}

위치 필드는 $1, $2 등으로 접근하며, 이름이 지정된 필드는 이름을 직접 사용합니다. 단일 레코드에서 두 스타일을 혼합하여 사용할 수 있습니다.

레코드는 함수에서 여러 값을 반환할 때 유용합니다. 단지 두 개의 데이터를 반환하기 위해 클래스를 생성할 필요가 없습니다:

(int, int) divideWithRemainder(int a, int b) {
  return (a ~/ b, a % b);
}

(String name, int age) getUser() {
  return ('Bob', 25);
}

void main() {
  var (quotient, remainder) = divideWithRemainder(17, 5);
  print('$quotient remainder $remainder');  // 3 remainder 2
  
  var (name, age) = getUser();
  print('$name is $age');  // Bob is 25
}

레코드는 값을 기반으로 동등성을 자동으로 지원하므로, ==를 직접 구현하지 않고도 편리하게 비교할 수 있습니다. 단순하고 불변인 데이터 그룹화가 필요한 경우에는 레코드를 사용하고, 메서드, 가변성 또는 더 복잡한 동작이 필요한 경우에는 클래스를 사용하세요.

challenge icon

챌린지

쉬움

레코드를 사용하여 좌표 시스템을 만들어 봅시다! 레코드로 표현된 2D 포인트를 다루는 함수를 작성하며, 전체 클래스를 생성하지 않고도 레코드를 통해 여러 관련 값을 쉽게 반환하고 작업하는 방법을 배우게 됩니다.

코드를 두 개의 파일로 구성합니다:

  • geometry.dart: 레코드를 사용하여 좌표 데이터를 다루는 함수를 만듭니다:
    • 이름이 지정된 필드 xy를 가진 레코드를 반환하는 createPoint(int x, int y) 함수. 반환 타입은 ({int x, int y})여야 합니다.
    • 두 포인트 사이의 중간 지점을 계산하여 이름이 지정된 필드를 가진 레코드로 반환하는 midpoint(({int x, int y}) p1, ({int x, int y}) p2) 함수. 계산에는 정수 나눗셈(~/)을 사용하세요.
    • 위치 기반 필드를 가진 레코드를 반환하는 distance(({int x, int y}) p1, ({int x, int y}) p2) 함수: 수평 거리(x의 차이)와 수직 거리(y의 차이). 반환 타입은 (int, int)여야 합니다. p2.x - p1.xp2.y - p1.y로 계산하세요.
  • main.dart: geometry 파일을 임포트하고 레코드가 작동하는 모습을 보여줍니다:
    • createPoint를 사용하여 두 개의 포인트를 생성합니다: (2, 4) 위치의 포인트 A와 (10, 8) 위치의 포인트 B.
    • 이름이 지정된 필드를 사용하여 'Point A: (${pointA.x}, ${pointA.y})'를 출력합니다.
    • 이름이 지정된 필드를 사용하여 'Point B: (${pointB.x}, ${pointB.y})'를 출력합니다.
    • 중간 지점을 계산하고 'Midpoint: (${mid.x}, ${mid.y})'를 출력합니다.
    • 거리를 계산하고 구조 분해(destructuring)를 사용하여 값을 변수 dxdy로 추출한 다음, 'Distance: dx=$dx, dy=$dy'를 출력합니다.

의미가 중요할 때는 명확성을 위해 이름이 지정된 필드를 사용하고, 문맥이 분명할 때는 위치 기반 필드를 사용하여 레코드가 어떻게 여러 값을 깔끔하게 반환하는지 확인해 보세요!

예상 출력:

Point A: (2, 4)
Point B: (10, 8)
Midpoint: (6, 6)
Distance: dx=8, dy=4

치트 시트

Dart 3에서 레코드(records)가 도입되었습니다. 이는 전체 클래스를 생성하지 않고도 여러 값을 함께 묶을 수 있는 가벼운 방법입니다. 레코드는 불변(immutable)이며 함수에서 여러 값을 반환할 때 완벽합니다.

괄호 안에 값을 감싸서 레코드를 생성합니다:

// 위치 기반 필드를 가진 간단한 레코드
var point = (10, 20);
print(point.$1);  // 10 - 첫 번째 요소에 접근
print(point.$2);  // 20 - 두 번째 요소에 접근

// 이름이 있는 필드를 가진 레코드
var person = (name: 'Alice', age: 30);
print(person.name);  // Alice
print(person.age);   // 30

위치 기반 필드는 $1, $2 등으로 접근하며, 이름이 있는 필드는 해당 이름을 직접 사용합니다.

레코드는 함수에서 여러 값을 반환하는 데 이상적입니다:

// 반환 타입이 레코드 구조를 지정함
(int, int) divideWithRemainder(int a, int b) {
  return (a ~/ b, a % b);
}

// 반환 타입에 이름이 있는 필드 사용
(String name, int age) getUser() {
  return ('Bob', 25);
}

// 레코드 구조 분해
var (quotient, remainder) = divideWithRemainder(17, 5);
print('$quotient remainder $remainder');  // 3 remainder 2

var (name, age) = getUser();
print('$name is $age');  // Bob is 25

이름이 있는 필드를 포함하는 레코드 반환 타입은 중괄호를 사용합니다:

({int x, int y}) createPoint(int x, int y) {
  return (x: x, y: y);
}

레코드는 값을 기반으로 한 동등성(equality)을 자동으로 지원합니다.

직접 해보기

import 'geometry.dart';

void main() {
  // TODO: createPoint를 사용하여 (2, 4) 위치에 point A 생성
  
  // TODO: createPoint를 사용하여 (10, 8) 위치에 point B 생성
  
  // TODO: 명명된 필드(named fields)를 사용하여 Point A 출력: Point A: ([x], [y])
  
  // TODO: 명명된 필드(named fields)를 사용하여 Point B 출력: Point B: ([x], [y])
  
  // TODO: 중점(midpoint)을 계산하고 출력: Midpoint: ([x], [y])
  
  // TODO: 거리를 계산하고 구조 분해(destructuring)를 사용하여 dx와 dy로 추출
  // 그 다음 출력: Distance: dx=[dx], dy=[dy]
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨