etc

[Flutter/Dart] dart의 기본적인 구조, UI가 그려지는 과정 정리

냐옹멍멍 2024. 11. 26. 21:12
반응형

모든 것이 위젯(Widget)입니다

  • HTML 요소처럼 모든 UI 요소가 위젯으로 구성됩니다
  • 위젯은 React의 컴포넌트와 유사한 개념입니다

레이아웃 구조

  • Column: 세로 방향 배치 (CSS의 flex-direction: column)
  • Row: 가로 방향 배치 (CSS의 flex-direction: row)
  • Container: div와 유사한 범용 컨테이너
  • Stack: 요소들을 겹쳐서 배치 (CSS의 position: absolute와 유사)

스타일링 특징

  • CSS처럼 별도의 스타일시트 없이 위젯의 속성으로 스타일 정의
  • 모든 크기는 논리적 픽셀(logical pixels)을 사용
  • Theme을 통해 앱 전체의 스타일을 관리 (CSS 변수와 유사)

상태 관리

// StatelessWidget: Props만 받는 순수 컴포넌트 (React의 함수형 컴포넌트와 유사)
class MyStatelessWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('Hello');
  }
}

// StatefulWidget: 내부 상태를 가진 컴포넌트 (React의 state를 사용하는 컴포넌트와 유사)
class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _counter = 0;  // state와 유사

  void _incrementCounter() {
    setState(() {     // setState와 유사
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Count: $_counter'),
        ElevatedButton(
          onPressed: _incrementCounter,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

핵심 차이점

  • HTML/CSS는 선언적으로 구조와 스타일을 분리하지만, Flutter는 모든 것을 Dart 코드로 작성
  • Flutter의 위젯은 불변(immutable)이며, 상태 변경 시 전체 위젯 트리를 다시 빌드
  • CSS의 flexbox나 grid 대신 Row, Column, GridView 등의 위젯으로 레이아웃 구성
  • 반응형 디자인은 MediaQuery를 통해 구현 (CSS 미디어 쿼리와 유사)

 

Flutter/Dart의 주요 클래스 구조와 특징

기본 클래스 구조

  • StatelessWidget: 상태가 없는 정적 위젯
class MyStatelessWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Widget(...);
  }
}
  • StatefulWidget: 상태를 가진 동적 위젯
// 위젯 정의
class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

// 상태 정의
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  // 상태 변수들
  @override
  Widget build(BuildContext context) {
    return Widget(...);
  }
}

주요 레이아웃 위젯

  • Container
Container(
  width: 100,
  height: 100,
  color: Colors.blue,
  child: Widget(...),
)
  • Row
Row(
  mainAxisAlignment: MainAxisAlignment.center,  // justify-content: center
  children: [Widget1(), Widget2()],
)
  • Column
Column(
  crossAxisAlignment: CrossAxisAlignment.start,  // align-items: flex-start
  children: [Widget1(), Widget2()],
)

 

위젯 생명주기

class _MyWidgetState extends State<MyWidget> {
  @override
  void initState() {
    super.initState();
    // 위젯이 처음 생성될 때 호출
  }

  @override
  void didUpdateWidget(MyWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 위젯이 업데이트될 때 호출
  }

  @override
  void dispose() {
    // 위젯이 제거될 때 호출
    super.dispose();
  }
}

 

상태 관리 패턴

// 1. setState 사용
setState(() {
  _counter++;
});

// 2. Provider 패턴 사용
class CounterProvider extends ChangeNotifier {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }
}

 

기본적인 스타일링

Container(
  margin: EdgeInsets.all(8.0),  // margin: 8px
  padding: EdgeInsets.symmetric(
    horizontal: 16.0,  // padding-left: 16px, padding-right: 16px
    vertical: 8.0,     // padding-top: 8px, padding-bottom: 8px
  ),
  decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(8.0),  // border-radius: 8px
    boxShadow: [
      BoxShadow(
        color: Colors.black.withOpacity(0.1),
        blurRadius: 4,
        offset: Offset(0, 2),
      ),
    ],
  ),
)
반응형