클래스(Class)와 생성자(Constructor): 플러터 앱의 설계도와 주문서
최근 바이브코딩을 통해 실제 앱의 로직을 만져보면서, 단순히 위젯을 배치하는 것보다 그 위젯이 어떻게 데이터를 받아오고 움직이는지 이해하는 것이 더 중요하다는 것을 느꼈습니다. 플러터의 모든 위젯은 사실 클래스(Class)로 이루어져 있고, 이를 실제로 살아 움직이게 만드는 장치가 바로 생성자(Constructor)입니다. 오늘은 이 핵심 개념들을 아주 쉽게 파헤쳐 보겠습니다.
1. 클래스(Class)의 구성 요소 재정의
클래스는 크게 세 가지 핵심 요소로 구성됩니다. 우리가 만드는 모든 위젯도 이 틀을 따릅니다.
- 속성 (Field/Property): 데이터 (무엇을 가지고 있는가? - 이름, 색상, 가격 등)
- 생성자 (Constructor): 초기화 (어떻게 태어나는가? - 주문서 작성)
- 메소드 (Method/Function): 행동 (무엇을 하는가? - 걷기, 소리 내기, 화면 그리기)
2. 생성자(Constructor)란 무엇인가?
🧱 개념 비유: 주문서와 조립 라인
붕어빵 틀(클래스)이 있다고 해도, '팥'을 넣을지 '슈크림'을 넣을지 결정해야 진짜 붕어빵이 나옵니다. 생성자는 객체가 생성되는 순간 "어떤 재료(데이터)를 넣어서 만들 것인지" 정의하는 주문서와 같습니다.
생성자는 객체가 만들어질 때 초기값을 설정해주고, 필수 데이터가 없으면 아예 만들어지지 않도록 하는 안전장치 역할도 수행합니다.
3. 생성자의 구조: 이름 있는 매개변수(Named Parameter)
플러터에서는 가독성을 위해 { }(중괄호)를 사용하는 '이름 있는 매개변수'를 주로 사용합니다. 이 구조를 이해해야 위젯 속성을 자유자재로 다룰 수 있습니다.
class Snack { String name; int price; // 중괄호 {}를 사용해 매개변수의 이름을 지정합니다. Snack({required this.name, required this.price}); void showInfo() { print("$name의 가격은 $price원입니다."); } } void main() { // 호출할 때 'name:', 'price:'를 써주니 코드가 명확해집니다. var mySnack = Snack(name: "포테이토칩", price: 1500); mySnack.showInfo(); }
4. 생성자와 위젯의 긴밀한 관계
플러터에서 위젯을 만든다는 것은 사실 "클래스의 생성자를 호출하는 것"과 같습니다. 코드 곳곳에 숨겨진 비밀을 알아봅시다.
- const 생성자와 성능:
const가 붙은 위젯은 메모리에 딱 한 번만 생성되어 재사용됩니다. 앱이 다시 그려질 때(Build) 불필요한 리소스를 낭비하지 않게 해주어 앱 속도를 획기적으로 높여줍니다. - super 키워드의 비밀:
const MyWidget({super.key});코드에서 super는 설정값(key 등)을 부모 클래스(StatelessWidget)에게 전달하여 기본 기능을 그대로 물려받겠다는 뜻입니다.
5. BuildContext: 위젯의 "주소" 혹은 "신분증"
모든 위젯의 build 함수에는 BuildContext context 매개변수가 들어옵니다. 이게 왜 그렇게 중요할까요?
🗺️ 개념 비유: 구글 지도 위의 내 위치
위젯 트리가 하나의 거대한 도시라면, 각 위젯은 건물입니다. BuildContext는 현재 이 위젯이 도시의 어디에 위치(주소)하고 있는지 알려주는 GPS 정보와 같습니다.
위젯은 독립적으로 존재하지 않고 주변 정보를 확인해야 할 때 context를 사용합니다.
- 테마 정보 가져오기: "지금 우리 앱 전체 테마 컬러가 블루인가?" (
Theme.of(context)) - 화면 크기 파악: "지금 이 위젯이 그려지는 화면의 가로 길이는?" (
MediaQuery.of(context))
💡 퀴즈 (Quiz)
Q. 플러터에서 위젯을 생성할 때 const를 붙이는 가장 큰 이유는 무엇일까요?
(정답: 메모리를 아끼고 앱의 실행 성능을 높이기 위해서입니다! 한 번 생성된 객체를 메모리에 고정하여 재사용하기 때문이죠.)