본문 바로가기
비전공자를 위한 Flutter/앱 개발 강의보기

Flutter (영업비밀) 앱개발 자주 쓰이는 금주의 위젯 살펴보기 frequently used widgets

by 밍잔 2022. 6. 14.

3년간 플러터로 인터페이스 화면을 그리다 보니 자주 쓰이는 위젯이 몇 가지 있었습니다. 오늘은 플러터로 앱을 개발할 때 알아두면 좋은 위젯들을 살펴보겠습니다.

 

1. Listview, ListviewBuilder

2. Row, Column

3. SizedBox

4. Container

5. GestureDetector

6. SafeArea

7. ElevatedButton, OutlinedButton, TextButton, IconButton

8. Text, RichText, TextSpan

9. Flex, Flexible

10. Spacer

11. ClipRRect

12. Image

13. WillPopScope

14. Stack, Positioned

15. Semantic

 

Scaffold 위젯은 앱 디자인을 구현하는 데에 있어 가장 기본이 되는 위젯으로 이 위젯으로 감싸지 않으면 아무런 디자인 속성이 없는 검은 화면과 빨간 글씨를 보시게 될 겁니다. 페이지에 해당하는 위젯의 build 메소드에는 Scaffold 위젯을 리턴하는 걸로 시작하시길 바랍니다.


1. Listview, Listview.builder

 

여러개의 목록이 있어 아래로 스크롤을 해야할 때 사용하는 위젯입니다. 이제는 무한 스크롤이 없는 앱을 찾기가 더 힘들죠. 페이스북이 대단한 사용자 경험을 만들어내긴 했습니다. ListView와 Listview.builder의 생김새와 기능은 동일하고, 차이점은 자식 위젯의 렌더링 시점에 있습니다. Listview는 마운트와 함께 모든 자식 위젯을 렌더링하고, Listview.builder는 화면에 곧 보여질 위젯을 예측해서 렌더링을 하게 됩니다. Listview는 자식 위젯의 숫자가 적을 때 적합하고, Listview.builder는 무한 스크롤 리스트를 구현해야할 때 적합합니다.

 


2. Row, Column

 

Row는 가로로 Column은 세로로 위젯들을 정렬시키고 싶을 때 사용합니다. Row위젯은 가로로 100% 늘어나는 성질을 갖고 있습니다. Row위젯의 부모 위젯이 SizedBox이며, SizedBox의 가로 크기가 100이라면 Row위젯의 가로 크기도 100이 됩니다. 만약 이 가로 크기 100을 넘어가도록 자식 위젯을 렌더링하려하면 자식이 넘쳐흐른다는 overflow 오류를 볼 수 있습니다. Column위젯도 Row위젯의 개념과 동일하게 세로로 100% 늘어나는 성질을 갖고 있습니다. 

 

이 둘은 mainAxisAlignment, crossAxisAlignment라는 속성을 지정해줄 수 있는데요. mainAxis는 주축, crossAxis는 주축과 수직을 이루는 축입니다. Row의 mainAxisAlignment는 가로로 나열할 건데 어디부터 나열할 건지 정하는 거구요. crossAxisAlignment는 가로축으로 나열된 위젯들을 어떻게 세로 정렬시킬지 정하는 겁니다. Column위젯은 그 반대가 되겠죠. Row위젯 기준 자주 사용하는 정렬은 아래와 같습니다.

 

가로 정렬

- 왼쪽 : MainAxisAlignment.start

- 가운데 : MainAxisAlignment.center

- 오른쪽 : MainAxisAlignment.end

- 위젯 간 동일한 간격 : MainAxisAlignment.spaceBetween

- 위젯 사이사이에만 여백 : MainAxisAlignment.spaceEvenly

 

세로 정렬

- 왼쪽 : CrossAxisAlignment.start

- 가운데 : CrossAxisAlignment.center

 


3. SizedBox

 

주로 위젯과 위젯 사이에 여백을 줄 때 사용합니다. 가로와 세로 사이즈를 설정할 수 있으며, SizedBox가 지정한 가로, 세로 길이를 상속받는 자식 위젯을 추가할 수 있습니다. Container로도 같은 일을 할 수 있는데요. 사이즈만 지정할 때 Container를 사용하지 말아야 하는 이유는 관련 없는 노드가 너무 많이 생기기 때문입니다. 스프린터를 사용한다면 자동으로 경고 메시지가 나올겁니다.

 

스프린터 자세히 보기 [비전공자를 위한 Flutter/Flutter 심화과정] - 구글에서 사용하는 Flutter 코딩 컨벤션 flutter_lints 알아보기

 

구글에서 사용하는 Flutter 코딩 컨벤션 flutter_lints 알아보기

코딩 컨벤션이란 무엇인가요? 사람들과 함께 협업을 할 때 코딩의 규칙이 없으면 각자가 편한대로 코딩하게 됩니다. 그렇게 방치한 상태로 시간이 많이 흐르게 되면, 나중에 그 코드를 짠 당사

mingzan.dev


4. Container

 

배경색, 그림자, 둥근 모서리 등의 영역을 그릴 때 자주 쓰이는 위젯입니다. 저는 플러터로 카드 디자인을 구현할 때 Card위젯 대신에 Container를 사용하는데요, 그 이유는 Card위젯의 자식 위젯으로 Container위젯을 가지고 있기 때문에 필요한 프로퍼티만 사용하고자 Container위젯을 씁니다. 배경색을 지정할 때 유의해야할 점은 흰색 위젯 위에 흰색 위젯을 위치시키는 등 위젯마다 동일하게 보이는 배경색을 지정하면 안 된다는 겁니다.

 

위젯 위에 동일한 배경색을 지정하지 말아야 하는 이유 - [비전공자를 위한 Flutter/Flutter 심화과정] - Flutter How to optimize? 속도 10배 상승시킨 앱 최적화 하는 법 공유

 

Flutter How to optimize? 속도 10배 상승시킨 앱 최적화 하는 법 공유

플러터로 앱을 개발하다보면 처음에는 모르지만 점점 앱이 느려지는 jank를 맞이하게 됩니다.(앱이 버벅이는 현상을 jank라고 합니다.) '최적화가 시급하다!!'라고 선언하고 복잡도를 줄이는 작업

mingzan.dev

 

그리고 Container 위젯은 align프로퍼티가 있어서 자식 위젯을 어떻게 정렬할지 지정해줄 수 있는데요. 코딩 컨벤션에 따르면 단순한 가운데 정렬의 경우 Center위젯을 사용하라고 합니다. 마찬가지로 단순히 바깥 영역의 여백만 필요할 때 Padding 위젯을 사용하는 것이 좋습니다.


5. GestureDetector

 

이 위젯은 여러가지 사용자 액션마다 이벤트를 지정해줄 수 있는데요. 가장 많이 쓰이는 부분은 바로 폼 양식에 글자를 입력하기 위해 노출된 키보드를 입력을 다 하고 나서, 키보드를 다시 숨기기 위해 onTap 이벤트에 unfocus 메소드를 사용하는 겁니다. 주로 SafeArea 위젯과 함께 가장 상위 부모 위젯으로 위치시키는 편입니다.


6. SafeArea

 

이 위젯은 디자이너가 디자인한 대로 화면을 보여주기 위해 사용하는데요. 앱을 개발할 때 기본적으로는 휴대폰 화면에 시간이 나오는 상단 영역과 UI버튼이 있는 하단영역까지 사용하게 되어 있습니다. SafeArea 위젯으로 감싸주지 않으면 시간과 배터리가 나오는 영역에 위젯이 겹쳐나오는 일이 발생하게 됩니다. 여러분의 서비스에 대해 불편한 사용자 경험을 선사하고 싶지 않다면 잊지 말고 SafeArea 위젯을 상위 부모 위젯으로 사용하세요!


7. ElevatedButton, OutlinedButton, TextButton, IconButton

 

플러터에서 제공하는 버튼 위젯들입니다. 저는 처음에는 onTap 이벤트가 있는 GestureDetector와 InkWell 위젯을 이용해 버튼을 만들었었는데요. <클린 코드>라는 책을 읽고 이 버튼을 애용하기 시작했습니다. 주석 없이 이름만 봐도 명확하게 이해가 되는 코드. 코드 스타일을 다 읽지 않아도 위젯 이름만으로 어떤 모습을 하고 있을지 예상이 되지 않나요? 다만 스타일을 지정하는 방법이 다른 위젯들과 조금 달라서 적응하는 데에 시간이 조금 걸립니다.

 

버튼들이 궁금하다면? - [비전공자를 위한 Flutter/Flutter 심화과정] - Flutter How to use each button 플러터 상황별 버튼 사용법

 

Flutter How to use each button 플러터 상황별 버튼 사용법

버튼을 사용할 때 주의해야할 점은 바로 버튼의 내용이 1줄을 넘어서는 안 된다는 점입니다. 버튼은 사용자로 하여금 행동을 유도하기 위해 사용하는데요. 말은 길게 할 수록 전달력이 떨어지게

mingzan.dev


8. Text, RichText, TextSpan

 

앱에 텍스트가 빠질 수 없죠. 앱에 글자를 표현해주는 텍스트 위젯입니다. RichText위젯은 글자 사이사이에 이렇게 굵은 글자가 껴있거나 색이 다른 글자가 있을 때 사용합니다.

 

여기까지 오신 김에 디자인 얘기를 잠깐 해드리면 TextStyle에 letterSpacing, height라는 속성이 있는데요. 자간과 행간을 의미합니다. 편집디자인에서는 용도에 따라 자간과 행간을 조절하는데요. 자간을 줄여 글자 사이 간격을 좁게 만들면 가독성이 좋아집니다. 그런데, 앱을 사용할 때 자간을 좁히면 답답한 감이 들어서 자간을 수정하는 일은 지금까지 거의 없었습니다. 

 

주로 행간을 100%, 130%, 160%로 이용하는데요. 100%는 딱 한 줄짜리 텍스트에 사용합니다. 예를 들면 텍스트 버튼은 내용이 절대 한 줄을 넘어선 안 됩니다. 그리고 리스트의 제목에 130%의 행간을 사용합니다. 제목은 상대적으로 큰 글자크기로 뭉쳐있어야 인지하기 좋습니다. 마지막으로 본문의 행간을 160%로 지정합니다. height 속성을 주자면 1, 1.3, 1.6 이렇게 주면 됩니다. (1=100%)


9. Flex, Flexible

 

Flex 위젯은 부모 위젯으로서, 지정하는 축으로 화면 끝까지 길이가 늘어나는 위젯인 Flexible 위젯들을 감싸는 역할을 합니다. direction속성으로 어느 축으로 위젯들을 지정할 수 있습니다. 저는 이 위젯을 주로 화면 하단에 고정된 구매하기 버튼을 구현할 때 사용합니다. 특별히 예제 코드를 드리죠.

 

Flex(
  direction: Axis.vertical,
  children: [
    Flexible(
      child: ListView(
        children: [],
      ),
    ),
    ElevatedButton(
      onPressed: () {},
      child: Text("구매하기")
    )
  ],
),

10. Spacer

 

Row 위젯 안에 가끔 버튼 1개는 왼쪽에 있고, 버튼 2개는 오른쪽 끝에 붙어있는 디자인을 구현해야할 때가 있습니다. spaceBetween 속성을 주니 동일한 간격을 버튼 3개가 공유해버리는 일이 생기죠. 이럴 때 사용하는 위젯이 Spacer입니다. Spacer위젯은 지정된 축으로 다른 위젯들을 밀어버리는 역할을 합니다.

 

Row(
  children: [
    IconButton(
      onPressed: () {},
      icon: const Icon(Icons.add),
    ),
    const Spacer(),
    IconButton(
      onPressed: () {},
      icon: const Icon(Icons.add),
    ),
    IconButton(
      onPressed: () {},
      icon: const Icon(Icons.add),
    ),
  ]
)

 


11. ClipRRect

 

프로필 사진 또는 이미지의 모서리를 둥글게 만들고 싶을 때 사용하는 위젯입니다. 이 위젯은 비용이 비싸서 많이 쓰면 버벅거림을 유발할 수 있습니다. 더이상의 설명은 위에 있는 앱 최적화 글을 참고바랍니다.


12. Image, NetworkImage

 

직접 저장한 이미지를 불러오거나, 외부에 있는 이미지를 불러올 때 사용하는 위젯입니다. 이미지 크기가 너무 커서 그동안 보여줄 대체 위젯 또는 불러오려는 이미지가 없어서 404 에러가 나는 경우를 대비해 보여줄 위젯 등을 설정할 수 있는 패키지를 소개합니다.

 

https://pub.dev/packages/cached_network_image

 

cached_network_image | Flutter Package

Flutter library to load and cache network images. Can also be used with placeholder and error widgets.

pub.dev


13. WillPopScope

 

페이지 뒤로가기 이벤트가 발생할 때를 onWillPop 이벤트로 캐치할 수 있는 위젯입니다. 보통 양식 폼에서 여러 정보들을 다 입력한 상황에서 사용자가 잘못해서 뒤로가기 할 수도 있으니, 하려는 행동에 대해 확실히 하고자 확인용 모달을 띄우는 처리를 넣습니다.


14. Stack, Positioned

 

위젯은 보통 가로로 나열하거나, 세로로 나열하는데요. 이 위젯은 위치를 강제로 지정할 수 있으면서 z축으로 쌓을 수도 있습니다. Stack은 Positioned 위젯들을 감싸는 부모 위젯이구요. Positioned는 Stack위젯이 허용하는 공간 안에서 어디든 위젯을 노출할 위치를 지정할 수 있습니다. Positioned 위젯을 사용할 때 주의해야할 점이 있습니다. Stack위젯으로 감싸지 않으면 잘못된 부모 위젯과 매칭됐다며 렌더링 에러가 납니다. 그리고 우리가 사는 지구에는 사이즈가 다른 모바일 기기가 너무나도 많기 때문에 Positioned 절대값으로 위치를 지정하면 어떤 기기에서는 우리가 의도하지 않았던 디자인을 보여줄 가능성이 있습니다. 

 

코딩 없이 만들 수 있는 앱개발 툴이 대부분 이런 위젯들을 이용해 화면에 디자인을 그리는데요. 많은 모바일 디바이스들을 커버하기엔 한계가 있습니다. 상황에 따라 위젯이 변하도록 코딩을 해야만 여러 상황과 변수에 대처할 수 있습니다.


15. Semantic

 

마지막으로 Semantic 위젯은 위젯에 레이블링을 할 때 사용합니다. 위젯을 코딩하다보면 앱디자인을 구현해야 하다보니 필연적으로 코드가 길어집니다. 코딩 규칙에 따라 위젯 뒤에 아무리 콤마를 넣어 위젯 트리 코드를 보기 좋게 만들어도 한 눈에 알아보기 힘든 일이 빈번합니다. 이 때 Semantic 위젯으로 특정 단위의 자식 위젯을 감싸서 레이블 설명을 덧붙여 주면 유지보수하기에도 좋습니다. 더 좋은 방법은 또다른 StatefulWidget, StatelessWidget으로 명확하게 이해되는 위젯을 만드는 겁니다.

 


자주 쓰이는 위젯에 대해 알아봤습니다. 이어서 예제 앱을 계속 만들어보겠습니다. 아래 링크를 눌러주세요!

 

 

 

 

 

댓글