10분만에 플러터 앱 개발 찍먹하기

GY·2024년 1월 7일
0

플러터

목록 보기
1/1

오늘은 가볍고 빠르게 플러터로 앱을 개발하기 위한 기본적인 내용을 정리해 공유해볼게요.

플러터의 기본적인 내용을 학습하는 과정에서 정리하는 만큼 내용의 정확도는 떨어질 수 있습니다.
가볍게 훑어보는 용도로 참고해주세요!

✅ 리액트와 플러터의 코드는 어떻게 다른지 알아보고 싶다
✅ 어떤 개발자는 플러터는 어느정도 만들어진 UI를 사용하면 되어서 css에 고통받지 않아도 된다고 하던데.. 그게 무슨 말인지? 알고싶다
✅ 앱 개발에도 관심이 있는데.. 각잡고 공부하기 전에 훑어보고 찍먹하고 싶다

기본적인 플러터 설치 등의 세팅은 공식문서나 다른 글을 쉽게 찾아볼 수 있으므로, 해당 부분은 건너뛰고 시작하겠습니다.


플러터 프로젝트 시작

flutter create {app-name}


시작해봅시다

프로젝트를 실행합니다.
flutter run

이런 화면이 뜰 거에요.

+버튼을 누르면 count 수가 하나씩 증가하는 아주 간단한 애플리케이션 데모가 나옵니다.

main.dart 파일을 열면 해당 애플리케이션 데모에 대한 소스코드를 확인할 수 있습니다.
가장 시작 부분을 볼게요.

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

main에서 runApp메서드를 통해 MyApp 클래스를 호출합니다.

MyApp 클래스는, 아직 무엇인지는 모르겠지만 Stateless Widget을 상속받는 클래스네요.

글고 MaterialApp으로 UI 정보를 넘겨주어 생성하고 있습니다.

무슨 말일까요? 플러터에 대해 조금 더 알아볼게요.

아주, 아주, 기본적인 것들부터 알아봐요

flutter는 dart라는 언어를 사용합니다.

dart는 구글이 자바스크립트를 대체하기 위해 2011년 개발한 웹 프로그래밍 언어입니다. java와 문법이 유사해 몇 가지 특징을 숙지하면 쉽게 개발할 수 있습니다.


Widget에 대해 알아야 합니다.

위젯은 리액트의 컴포넌트 개념과 유사하다고 보면 될 것 같아요.
이 위젯으로 재사용 가능한 UI를 만들고 각 코드의 관심사를 분리합니다.

위젯의 종류는 크게 StatelessWidget과 StatefulWidget으로 나뉘어요.

위젯은 기본적으로 이런 형태로 이루어져있습니다.

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class로 정의하되, 필요에 따라 StatelessWidget또는 StatefulWidget 클래스를 상속받아 사용합니다.
그리고 build메서드를 사용해 위젯의 속성을 정의합니다.

여기에서 key는 플러터에서 각 위젯을 식별해 각 위젯들을 빠르게 찾을 수 있도록 하는 역할입니다.


StatelessWidget, StatefulWidget

상태를 갖지 않는 단순 UI는 StatelessWidget, 상태를 갖는 경우 StatefulWidget을 상속받아 사용합니다.

StatelessWidget은 위에서 간단한 예시를 확인했으니, StatefulWidget을 어떤 식으로 사용하는지 보여드리겠습니다.

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  
  Widget build(BuildContext context) {
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
//...
    );
  }
}

위 예시 코드에서 아래 내용에 대해서만 알고 넘어가요!

변수 선언

dart로 변수를 선언할 때는 final과 const를 사용할 수 있습니다.

const는 컴파일 타임에서 상수를 정의하므로, 이 키워드로 정의한 상수는 런타임에서 정의되는 값을 설정할 수 없습니다. 하지만 final은 런타임에서 결정되는 값도 설정할 수 있다는 차이가 있죠.
다만 둘 다 한 번 설정한 값을 변경할 수 없고, 변경하려고 시도할 경우 컴파일 오류가 발생한다는 차이가 있습니다.


setState

리액트처럼 변경된 데이터에 따라 UI를 업데이트하기 위해서는 setState함수를 호출해야 합니다.

MaterialApp

Widget에는 여러 종류가 있는데, 가장 처음에 알아두기 좋은 것이 MaterialApp과 Scaffold입니다.
MaterialApp은 기본적인 기능 요소들을 담당합니다. 맨 처음 데모 소스 코드를 보면 MaterialApp을 볼 수 있어요.

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

home, theme, title등 앱을 구성하는 레이아웃 및 기능적인 요소들을 쉽게 정의할 수 있도록 뼈대를 제공하는 위젯입니다

UI 만들기

Scaffold widget

Scaffold는 디자인 뼈대를 담당합니다. 즉 빠르고 쉽게 미리 만들어진 요소들을 사용해 UI를 만들 수 있도록 도와주는 위젯입니다.
Scaffold를 입력하면 자동완성되는 키워드들을 볼 수 있는데, Scaffold가 제공하는 것들을 통해 쉽게 UI를 구성할 수 있음을 알 수 있죠.

이렇게 작성해볼게요.

Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        home: const Scaffold(
            body: Center(
          child: Text('Main page UI here'),
        )));
  }

그러면 이렇게 UI가 표시됩니다.

이 외에도 리액트에서 css를 통해 요소들을 스타일링했다면, 플러터에서는 어떻게 각 위젯으로 이를 해내는지 보여줄게요.

텍스트는 이런 방식으로 스타일링합니다.

Text('text color',
      style:
          TextStyle(color: Colors.white.withOpacity((0.8))))

css에서 flexbox를 만들듯이 요소를 정렬하고 배치하는 건 Row, Column위젯을 사용해 이렇게 할 수 있습니다.
Row는 요소를 수평 정렬하고, Column은 수직 정렬해요. children의 인자값으로 각 하위요소들을 정의해주면 됩니다.

Row(
  children: <Widget>[
    Column(
      children: <Widget>[
        Text('요소 1'),
        Text('요소 2')
      ]
    ),
    Icon(Icons.star),
    Text('텍스트')
  ]
)

상위 위젯의 정보 내려받기

context, buildContext

리액트에서는 보통 하위컴포넌트로 props를 내려받아 필요한 데이터나 상탯값을 사용하죠. 위젯에서는 context의 개념이 유사한 역할을 합니다.

Widget을 선언할 때 buildContext context가 작성되어 있는 경우를 볼 수 있어요.

Widget build(BuildContext context) {
  return MaterialApp(

buildcontext는 현재 위젯의 위젯트리 상에서의 위치에 관한 정보를 담고 있습니다.
플러터의 모든 위젯은 내부에 build 메서드를 갖는데, 이 메서드의 타입은 widget이고 인자 값으로 buildContext를 갖습니다. 모든 위젯은 자신만의 BuildContext를 갖고 있고, 그것은 StatelessWidget.build혹은 State.build에 의해 반환되는 위젯의 부모가 되죠. 무슨 말이냐면, 상위 위젯의 정보에 접근하는 데 사용할 수 있다는 겁니다.

정리하면,
각 context를 통해 연결된 위젯간의 계층적 구조를 위젯트리라고 하는데요,
위젯트리를 통해

  • context는 모든 상위요소들의 정보 즉 위젯트리에 대한 정보를 담고 있습니다.
  • buildContext는 애플리케이션에서 현재 위젯의 위치, 부모요소 접근 등... 위젯트리 안에서 위젯의 위치를 다룹니다.

아래 예시에서, 상위 위젯에서 theme을 정의했을 때, 하위 위젯에서 Theme.of(context)로 이에 접근하는 것을 볼 수 있습니다.

Widget build(BuildContext context) {
  return MaterialApp(
    theme: ThemeData(
      textTheme: const TextTheme(
        titleLarge: TextStyle(
          color: Colors.red,
        )
      )
    )
  )
}

//...
Widget build(BuildContext context) {
  return const Text(
    style: TextStyle(
      color: Theme.of(context).textTheme.titleLarge.color
    )
  )
}

이번 글은 플러터의 코드가 어떤식으로 이루어져 있는지를 아주 가볍게 훑는 목적으로 작성했습니다. 깊이 있게 공부하기 전에 전체적인 그림을 훑고 직접 만들어봐야 지루하지 않으니까요!
다음 글에서는 좀 더 복잡한 기능을 만드는 방법에 대해 다루고, 관련 개념들도 정리해보겠습니다.

profile
Why?에서 시작해 How를 찾는 과정을 좋아합니다. 그 고민과 성장의 과정을 꾸준히 기록하고자 합니다.

0개의 댓글