Flutter 개발

Flutter 상태란? 초보자를 위한 State 개념 쉽게 이해하기

withmilk 2025. 7. 13. 19:33

앱을 만들다 보면 가장 자주 듣게 되는 단어 중 하나가 바로 “상태(State)”예요.

Flutter를 처음 시작하는 분들이라면 이 개념이 조금 헷갈릴 수 있는데요, 걱정 마세요!

 

오늘은 초보자 눈높이에 맞춰 상태란 무엇인지, 그리고 왜 중요한지를 하나씩 차근차근 알아볼게요.


1. 상태(State)란 무엇인가요?

  • 상태(State)는 앱이 현재 어떤 상황인지 알려주는 데이터의 값이에요.
  • 예를 들어, 지금 로그인 중인지 아닌지, 버튼을 몇 번 눌렀는지, 텍스트 입력창에 뭐가 써있는지가 전부 상태예요.
  • Flutter에서는 상태에 따라 UI(화면)가 자동으로 바뀌게 되어 있어요.

앱을 만들다 보면 ‘상태’라는 말을 정말 자주 듣게 돼요. 근데 처음엔 이게 뭔지 참 감이 안 오죠. 😅
그래서 일상 속 예시로 먼저 설명해볼게요!

 

커피숍에서의 상태

여러분이 카페에 가서 아메리카노를 주문했다고 해볼게요.

  1. 주문을 하고 나면 상태는 ‘대기 중’
  2. 바리스타가 만들기 시작하면 ‘제조 중’
  3. 커피가 완성되면 ‘완료’

이렇게 주문한 커피는 시간이 지나면서 상태가 계속 바뀌어요.
그리고 이 상태에 따라 매장 안 디스플레이에 표시되는 문구도 달라지죠?

대기 중 디스플레이 화면 예시

  • “아메리카노 – 제조 중”
  • “아메리카노 – 완료되었습니다”

이처럼 ‘현재 어떤 상태냐’에 따라 화면에 보여주는 내용이 달라지는 것,
이게 바로 Flutter에서 말하는 상태(State)의 핵심이에요!

 

Flutter에서는 어떤 게 상태일까?

Flutter 앱에서 상태는 어떤 걸 의미할까요? 아래 예시를 볼게요.

  • 숫자 증가 버튼을 눌렀을 때 현재 숫자 → 상태
  • 사용자가 입력창에 쓴 내용 → 상태
  • 로그인 되어 있는지 아닌지 → 상태
  • 탭 메뉴에서 어떤 페이지가 선택됐는지 → 상태

즉, 앱이 기억해야 할 현재의 데이터가 바로 상태예요.
그리고 이 상태가 바뀌면 Flutter는 자동으로 “오! 뭔가 바뀌었네?” 하고
화면(UI)을 새로 그려서 그걸 반영해주는 거예요. 이걸 reactive(반응형)이라고도 해요.

상태란 앱의 "기억력"이에요.
지금 어떤 내용이 화면에 보여야 하는지를 결정해주는 정보죠.
그리고 이 상태가 바뀌면, 앱은 그걸 눈치채고 화면을 자동으로 새롭게 보여줘요!


2. 왜 상태관리가 중요할까요?

  • 상태가 바뀌면 UI도 함께 바뀌어야 해요.
  • Flutter는 데이터(상태)와 UI가 연결된 구조예요.
  • 상태가 잘못 관리되면, 화면이 실제 데이터와 엇갈려 보이게 되는 문제가 생겨요.

앱을 사용하다 보면, "버튼을 눌렀는데 화면이 안 바뀌는" 경험을 한 번쯤 하게 돼요.
이럴 때 대부분의 원인은 상태를 제대로 관리하지 않았기 때문이에요.

 

사용자의 행동 = 상태 변화

Flutter 앱은 기본적으로 사용자의 행동에 따라 화면이 달라져요.
예를 들어 아래처럼요.

  • 사용자가 버튼을 누르면 숫자가 올라가야 하고,
  • 로그인에 성공하면 다음 화면으로 이동해야 하고,
  • 체크박스를 누르면 체크 표시가 나타나야 하죠.

이 모든 상황은 사실 상태가 바뀌는 순간이에요.
그리고 이 상태 변화를 감지해서, 그에 맞는 UI를 보여주는 것이 바로 상태관리예요.

 

🤔 상태관리가 안 되면 생기는 문제

간단한 예시를 들어볼게요.

int counter = 0;

ElevatedButton(
  onPressed: () {
    counter++;
  },
  child: Text('숫자 증가'),
);

 

이 코드는 counter 값을 증가시키긴 하지만, 화면은 바뀌지 않아요.
왜냐하면 Flutter는 상태가 바뀐 사실을 몰라요!

카운터 앱 잘못된 예시. 숫자 증가를 눌러도 Counter: 0에서 변하지 않는다.

 

 

즉, 데이터는 바뀌었지만 UI는 그대로인 이상한 상황이 생겨요.
이게 바로 상태관리가 필요한 이유예요. 데이터를 바꾸는 것만으론 부족하고,
Flutter에게 “상태가 바뀌었어!”라고 알려줘야 해요.

 

그래서 우리는 setState() 같은 방법을 써서 상태 변화를 Flutter에 알려주는 거죠.
아래처럼 이렇게 해야만 화면도 함께 업데이트돼요.

 

버튼을 누르면 숫자가 올라가는 앱을 생각해볼게요.
이때 숫자 데이터는 상태예요.
사용자가 버튼을 누르면 상태가 바뀌고, Flutter는 그걸 감지해서 숫자를 다시 그려줘요.

setState(() {
  counter++;
});

이 한 줄이 바로 Flutter에게 “지금 상태가 바뀌었으니까 화면도 다시 그려줘!”라고 알려주는 신호예요.

setState를 통해 count를 변경했을 때 정상적으로 UI가 그려지는 모습.

Flutter 앱은 살아있는 생물처럼, 상태가 바뀔 때마다 화면이 변해야 해요.
그런데 그걸 제대로 알려주지 않으면 앱은 여전히 이전 모습만 보여줘요.
그래서 상태관리가 정말 정말 중요해요!


3. Flutter에서 상태가 바뀌면 어떤 일이 벌어질까?

  • 상태가 바뀌면 Flutter는 관련된 위젯을 다시 그려요.
  • 이 과정을 **리렌더링(re-rendering)**이라고 해요.
  • 우리가 직접 화면을 새로 그리지 않아도, Flutter가 자동으로 해줘요!

 

그림을 다시 그리는 앱, Flutter

Flutter는 UI를 직접 그려주는 프레임워크예요.
즉, 앱의 모든 화면 요소(버튼, 텍스트, 이미지 등)를 내가 원하는 대로 조립해서 그리는 구조예요.
그런데 중요한 점은, 이 UI들이 상태(State)에 따라 달라진다는 거예요.

Flutter는 상태가 바뀌는 걸 감지하면,


"오! 뭔가 바뀌었네? 다시 그려야겠군!" 하고, 화면의 일부분 혹은 전체를 새로 그려줘요.
이걸 전문 용어로는 위젯 트리의 재빌드라고 부르지만, 쉽게 말하면
다시 그림 그리는 거예요.

 

칠판에 그림 그리기

Flutter를 칠판에 그림 그리는 선생님으로 생각해볼게요.

  • 처음에 숫자 0을 그렸어요.
  • 버튼을 누르면 숫자가 1이 돼요.

이때 Flutter(선생님)는 숫자 0을 지우고 1을 다시 그려주는 거예요.
중요한 건, Flutter가 "어디가 바뀌었는지" 알고 있어서,
전체 칠판을 다시 그리는 게 아니라 필요한 부분만 쏙쏙 바꿔주는 거예요.

 

Flutter는 굉장히 효율적이에요.

  • 상태가 바뀔 때마다 전체 앱을 다 그리는 게 아니라,
  • 필요한 부분만 골라서 똑똑하게 다시 그려줘요.

그래서 Flutter는 빠르고, 부드러운 UI를 만들 수 있어요.

 

숫자 증가 앱에서 일어나는 일

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Flutter 상태 예제')),
      body: Center(
        child: Text(
          '현재 숫자: $counter',
          style: TextStyle(fontSize: 24),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _increaseCounter,
        child: Icon(Icons.add),
      ),
    );
  }

이 코드를 실행하면 다음과 같은 일이 벌어져요:

  1. counter 값이 바뀜 → 상태 변경 발생
  2. setState()가 호출되면서 Flutter는 “이 Widget을 다시 그려야겠군” 하고 판단
  3. 숫자가 출력되는 텍스트만 다시 그려짐 → 나머지 UI는 그대로 유지

즉, Flutter는 최소한의 부분만 다시 그려서 화면을 바꿔주는 똑똑한 엔진이에요.

상태가 바뀌면 Flutter는 화면을 다시 그려요.
근데 전부 다 다시 그리는 게 아니라, 바뀐 부분만 골라서 그려줘요!
그래서 상태만 잘 관리하면, 우리는 화면 업데이트 걱정 없이 개발할 수 있어요 🙌


4. 간단한 예제로 알아보는 상태 변경

  • setState()는 Flutter에게 “상태가 바뀌었어!”라고 알려주는 함수예요.
  • 상태가 바뀌고 나면, Flutter는 그에 맞게 화면(UI)을 자동으로 다시 그려줘요.
  • 우리가 하는 일은 단지 상태를 바꾸고, setState() 안에 넣는 것뿐!

Flutter를 설치하면 처음 실행해보는 앱이 바로 숫자 증가 앱(Counter App)이에요.
화면에 숫자가 있고, 버튼을 누르면 숫자가 하나씩 올라가죠?

이걸 직접 코딩해보면 아래처럼 간단하게 만들 수 있어요:

//main.dart
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'State Example',
      home: CounterPage(),
    );
  }
}

class CounterPage extends StatefulWidget {
  @override
  _CounterPageState createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  int counter = 0;

  void _increaseCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Flutter 상태 예제')),
      body: Center(
        child: Text(
          '현재 숫자: $counter',
          style: TextStyle(fontSize: 24),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _increaseCounter,
        child: Icon(Icons.add),
      ),
    );
  }
}

 

 

  • counter: 현재 숫자를 저장하는 상태 변수
  • setState(() { counter++; }): 숫자를 1 증가시키고, Flutter에게 "다시 그려줘!" 라고 알림
  • Text('현재 숫자: $counter'): 상태 값에 따라 달라지는 화면 UI

이 예제에서는 버튼을 누를 때마다 counter라는 상태가 바뀌고,
그 상태가 바뀌었으니 Flutter는 “앗! 숫자 바뀌었구나” 하고 화면을 다시 그려줘요.
우리는 숫자만 바꿨을 뿐인데, Flutter가 자동으로 UI까지 반영해주는 거죠 🙌

상태 변경의 흐름 요약

  1. 사용자가 버튼을 누름
  2. 상태 변수(counter)가 바뀜
  3. setState()로 Flutter에게 알림
  4. Flutter가 바뀐 부분만 새로 그림
  5. 화면에 숫자가 업데이트됨

이렇게 상태를 바꾸는 흐름만 이해하면, Flutter의 핵심을 절반 이상은 이해한 거예요!


5. StatelessWidget vs StatefulWidget 차이

  • StatelessWidget: 상태가 없는 위젯 → 화면이 고정됨
  • StatefulWidget: 상태가 있는 위젯 → 화면이 바뀜
  • 사용자의 상호작용이 필요 없다면 Stateless, 무언가 바뀌는 UI가 있다면 Stateful을 써야 해요

Flutter에서는 화면을 구성할 때 모든 요소들을 Widget(위젯)이라는 단위로 만들어요.
그리고 이 위젯은 크게 두 종류로 나뉘어요:

  1. 상태가 없는 StatelessWidget
  2. 상태가 있는 StatefulWidget

 

StatelessWidget = 인쇄된 메뉴판

  • 고정된 내용이 프린트된 종이
  • 바뀔 일이 없기 때문에 다시 인쇄할 필요가 없음
  • 예: "이름표", "로고", "앱 제목"

StatefulWidget = 전광판 메뉴판

  • 상태에 따라 표시 내용이 바뀜 (예: “품절” 표시)
  • 언제든지 업데이트 가능
  • 예: 버튼 눌렀을 때 바뀌는 숫자, 로그인 여부에 따라 다른 화면
구분 StatelessWidget StatefulWidget
상태(State) ❌ 없음 ✅ 있음
화면 변경 가능 여부 ❌ 항상 동일함 ✅ 상태에 따라 변경됨
사용 시점 고정된 UI 사용자 상호작용 필요 UI
예시 앱 로고, 타이틀 버튼, 입력창, 체크박스 등

StatelessWidget 예시

class HelloWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('안녕하세요!');
  }
}

화면에 "안녕하세요!" 라는 텍스트를 항상 보여주는 고정된 위젯이에요.
버튼을 눌러도, 어떤 입력을 해도 절대 바뀌지 않아요.

 

StatefulWidget 예시

class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int counter = 0;

  void _increase() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('숫자: $counter'),
        ElevatedButton(
          onPressed: _increase,
          child: Text('증가'),
        ),
      ],
    );
  }
}

버튼을 누를 때마다 상태(counter)가 바뀌고,
Flutter가 그걸 감지해서 숫자를 다시 그려줘요.
이처럼 동적인 UI에는 StatefulWidget이 필수예요.


6. setState()는 뭔가요?

  • setState()는 상태(State)가 바뀌었음을 Flutter에게 알려주는 함수예요.
  • 이걸 써야만 UI가 새로 그려지고, 사용자에게 변화가 보이게 돼요.
  • 상태만 바꾸고 setState()를 안 쓰면 화면은 그대로예요.

Flutter는 말하지 않으면 모른다!

Flutter는 UI를 직접 다시 그리는 똑똑한 프레임워크지만,
**“상태가 바뀌었다는 사실”**은 개발자인 우리가 알려줘야 해요.

즉, 데이터만 바꾼다고 해서 자동으로 화면이 바뀌지는 않아요.
바뀐 걸 알려주는 게 바로 setState()의 역할이에요.

setState() 없이 상태만 바꾸면?

int counter = 0;

void onPressed() {
  counter++; // 상태는 바뀌었지만...
}​

이렇게 하면 실제로 counter는 1이 되지만,
화면에는 여전히 0이 보여요. 왜?
→ Flutter는 “counter가 바뀌었다”는 걸 모르기 때문이에요.

Counter 텍스트가 바뀌지 않는 모습

이제 setState()를 써볼게요

int counter = 0;

void onPressed() {
  setState(() {
    counter++; // 상태도 바꾸고
  });          // Flutter에게 알려줌!
}

이렇게 하면 Flutter는
“아하! 상태가 바뀌었구나? 그럼 내가 화면을 다시 그려줄게!”
하고 build() 메서드를 다시 실행해서 UI를 업데이트해줘요.

내부에서 어떤 일이 일어나냐면...

  1. setState() 호출됨
  2. build() 함수가 다시 실행됨
  3. 새로운 상태값을 바탕으로 위젯이 다시 그려짐
  4. 사용자 눈에는 최신 상태가 반영된 화면이 보여짐

setState()는 “얘 좀 바꼈어요~!” 하고 Flutter에게 말해주는 신호등이에요.
이걸 써야만 앱이 새로 그림을 그리고, 사용자에게 변화가 보이죠.
Flutter는 말을 하지 않으면 절대 모르는 친구예요 😅

언제 setState()를 써야 할까?

  • 버튼 눌렀을 때 값이 변해야 한다면? → ✅ setState() 사용
  • 체크박스, 스위치가 바뀔 때? → ✅ setState() 사용
  • 입력값이 바뀌었을 때 화면에 반영하고 싶다면? → ✅ setState() 사용

간단하죠?


7. 상태관리는 어떻게 더 잘 할 수 있을까?

  • 앱이 커질수록 setState()만으로는 상태 관리가 복잡해져요.
  • 여러 위젯에서 하나의 데이터를 공유해야 할 때 문제가 생겨요.
  • 그래서 Flutter에서는 Provider, Riverpod, Bloc 같은 상태관리 도구를 사용해요.

setState()만으로는 부족한 순간이 온다…

지금까지는 setState() 하나만으로 상태를 잘 바꿔왔어요.
그런데 앱이 점점 커지고 복잡해지면, 상황이 달라져요.

예를 들어 이런 앱을 상상해보세요:

  • 로그인 화면 → 로그인 성공 시 메인 화면으로 이동
  • 메인 화면에 유저의 이름과 프로필 사진이 표시됨
  • 하단의 다른 페이지들에도 유저 정보를 공유해서 보여줘야 함

이때 setState()를 각 화면마다 쓰게 되면…

😵‍💫 “누가 상태를 가지고 있지?”
😵‍💫 “이 화면에서도 저 데이터를 써야 하는데, 어떻게 전달하지?”
😵‍💫 “상태를 바꾸면 모든 화면에서 자동으로 반영될까?”

이런 혼란스러운 상황이 생겨요.

 

그래서 등장한 상태관리 도구들

이 문제를 해결하기 위해 Flutter에서는 다양한 상태관리 도구를 사용할 수 있어요.

그 중 대표적인 도구가 바로 Provider예요.
Provider는 상태를 중앙에서 관리하고, 필요한 위젯들이 공유해서 사용할 수 있게 도와줘요.

즉, 데이터를 한 군데에 보관해두고,
필요한 곳에서 꺼내다 쓰는 공용 냉장고 같은 역할이에요!

  • setState()는 작은 도시락: 한 위젯 안에서만 데이터를 관리해요.
  • Provider는 공유 냉장고: 여러 위젯들이 하나의 상태를 나눠서 써요.

도시락은 간편하지만 여러 명이 먹기엔 불편하죠.
공용 냉장고가 있다면, 각자 필요한 걸 꺼내먹을 수 있어요.
앱이 커질수록 공용 냉장고 방식, 즉 Provider 같은 도구가 필요해져요.

상태관리 도구들 예시

도구 특징 난이도
setState() 기본 내장 기능. 위젯 내부에서만 사용 가능 ⭐ (쉬움)
Provider 전역 상태 공유, 공식 권장 방식 ⭐⭐
Riverpod Provider의 발전형, 더 안전하고 깔끔함 ⭐⭐⭐
Bloc 복잡한 앱에 적합한 구조화된 상태관리 ⭐⭐⭐⭐
 

앱이 작을 땐 setState()로 충분하지만,
앱이 커지고 여러 화면에서 데이터를 공유해야 할 땐
더 강력한 상태관리 도구가 필요해요.
그 중 입문자에게 가장 추천되는 건 바로 Provider예요!


8. 마무리: 오늘의 개념 요약 & 다음 글 예고

Flutter에서 상태(State)란 앱의 “지금 상황”을 나타내는 데이터예요.
숫자, 로그인 여부, 입력된 글자, 체크 상태처럼 UI에 영향을 주는 모든 것이 상태라고 할 수 있어요.

 

그리고 이 상태가 바뀔 때, Flutter는 화면(UI)을 자동으로 다시 그려줘요.
하지만! Flutter는 그 상태가 바뀐 걸 우리가 직접 알려줘야 해요.
바로 그 역할을 하는 게 setState()라는 함수였죠.

 

우리가 배운 흐름

  1. 상태란 무엇인가?
    → 앱이 기억하는 “지금 상황”, 데이터 값
  2. 왜 상태관리가 중요한가?
    → 상태가 바뀌어야 화면도 바뀌기 때문
  3. 상태가 바뀌면 무슨 일이 벌어지나?
    → Flutter가 화면을 다시 그림 (재렌더링)
  4. setState()로 상태를 바꿔보기
    → 버튼 누를 때 숫자가 올라가는 예제
  5. Stateless vs Stateful 위젯 구분
    → 바뀌는 UI면 Stateful, 아니면 Stateless
  6. setState()의 역할
    → Flutter에게 “상태가 바뀌었다”고 알려주는 신호
  7. 더 나은 상태관리 방법
    → 앱이 커질수록 Provider 같은 도구가 필요

마무리하며..

Flutter에서 상태는 정말 중요한 개념이에요.
이번 글을 통해 상태가 무엇이고, 어떻게 바꾸고, 왜 중요하며, 어떤 방식으로 관리하는지까지 감을 잡으셨을 거예요.

모든 앱의 동작은 상태의 변화와 그에 따른 UI의 반응에서 시작돼요.
오늘 개념을 잘 익혀두면, 앞으로 Flutter 개발이 훨씬 쉬워질 거예요!

 

다음 글에서는 Provider를 직접 사용해볼 거예요.

  • 숫자 상태를 여러 화면에서 공유하는 예제
  • setState() 없이도 똑똑하게 상태를 관리하는 방법
  • 입문자가 쉽게 따라할 수 있는 Provider 실습

를 단계별로 알려줄게요.
지금까지 배운 내용을 바탕으로, 한 단계 업그레이드된 상태관리 방법을 배워볼 준비 되셨죠? 😎