[Flutter]BuildContext에 대해서

한상욱·2024년 8월 26일
0

Flutter

목록 보기
18/26
post-thumbnail

들어가며

Flutter의 모든 위젯은 Stateless Widget 또는 Stateful Widget으로 구분되며 위젯 내부의 build()메소드를 이용해서 UI의 렌더링 될 위젯을 선언합니다. 그리고 build()메소드는 항상 아래와 같은 형식으로 이루어집니다.


Widget build(BuildContext context) {
	...
}

Flutter에서 build()메소드는 항상 BuildContext타입의 context를 항상 전달받도록 설계가 되어있습니다. 그리고 종종 아래와 같이 context를 이용해야 되는 경우가 있습니다.

Navaigator.of(context) ...
Theme.of(context) ...

도대체 BuildContext는 무엇일까요?

BuildContext의 정의

"A handle to the location of a widget in the widget tree."

공식문서에서는 BuildContext를 위와 같이 설명하고 있습니다. 번역을 해보면 "위젯트리 내부에서 위젯의 위치를 정보를 의미한다." 라고 해석할 수 있겠네요.

그렇습니다. 공식문서에서는 BuildContext가 현재 위젯 트리에서의 위젯의 위치를 의미하는 정보라고 소개하고 있는 것입니다.

BuildContext 이해하기

Flutter는 모든 위젯이 위젯 트리 형식의 계층형 구조로 선언됩니다. 그리고 선언된 위젯을 UI에 렌더링 하기 위해서 각각 위젯 트리, 요소 트리, 렌더 객체 트리가 생성됩니다. 그렇다면 이 위젯 트리에서 특정 위젯 인스턴스가 트리에 어떤 위치에 존재하는지에 대한 정보를 갖고 있을까요? 아뇨. 이 위젯의 위치는 경우에 따라서 트리의 어떤 위치로 지정될지 알 수 없습니다. 그렇기에 위젯 인스턴스는 현재 위젯의 위치 정보를 갖고 있지 않습니다.

Stateless Widget, Stateful Widget은 Widget을 상속받은 추상 클래스입니다. framework.dart파일에 내부 정의를 확인하면 이를 알 수 있습니다.

자세히 보니, createElement()라는 메소드를 갖고 있네요. 이 메소드를 통해서 요소를 생성하고 그 요소로 요소 트리를 생성할 수 있습니다. 요소는 현재 위젯의 위치를 지속적으로 추적하는 객체입니다.

요소에 대해서 더 파고 들어가보죠.

요소, Element는 BuildContext로 정의가 되어있네요! 즉, BuildContext는 실제로 Element를 의미한다고 할 수 있습니다.

build() 메소드 이해하기

build()메소드로 선언된 모든 위젯들은 BuildContext가 부모로 지정됩니다. build()메소드 하위에도 Builder 위젯을 통해 context를 전달할 수 있는데요. build()메소드의 context와 메소드 하위 위젯에서 생성하는 context는 서로 다른 context를 갖게 된다는 것을 알 수 있습니다.

이로 인해서 아래와 같은 에러가 종종 발생할 수 있습니다.

Scaffold.of() called with a context that does not contain a Scaffold.

예를 들어, 아래와 같은 코드가 있다고 하겠습니다.


  Widget build(BuildContext context) {
  	// Scaffold.of(context)는 null을 반환함.
    return Scaffold(
        appBar: AppBar(title: const Text('Demo')),
        body: TextButton(
          child: const Text('BUTTON'),
          onPressed: () {
            Scaffold.of(context).showBottomSheet(
              (BuildContext context) {
                return Container(
				...
  }

여기서 build()메소드 내부에서 Scaffold 내부의 Scaffold.of(context)를 통해 바텀 시트를 보여줍니다. 여기서, context는 build 메소드의 context가 전달되어 사용되었기에 Scaffold를 찾지 못하고 Scaffold.of(context)는 null을 반환하여 에러가 발생하게 되는 것입니다.

이 코드가 정상적으로 동작하기 위해서는 Builder 위젯을 통해 context를 전달해주어야 합니다. 그래야 자체적인 context가 아닌 새로운 context를 사용하게 되고 Scaffold의 위치를 파악할 수 있으니까요.

profile
자기주도적, 지속 성장하는 모바일앱 개발자가 되기 위해

0개의 댓글