Flutter 프로젝트 내부 구조

ssook·2023년 8월 28일
2

Flutter-Study

목록 보기
2/3
post-thumbnail

플러터 프로젝트 주요 폴더 & 파일

android안드로이드 프로젝트 관련 파일안드로이드 스튜디오로 실행 가능
iosiOS 프로젝트 관련 파일맥 전용 엑스코드로 실행 가능
lib플러터 앱 개발을 위한 다트 파일플러터 SDK 설치 필요
test플러터 앱 개발 중 테스트 파일테스트 편의성 제공
  • 루트에도 여러 파일이 있지만 가장 봐야 할 파일은 pubspec.yaml. pubspec.yml 파일은 플러터에서 다양한 패키지와 이미지, 폰트 등을 사용하게 해 줌.
  • 플러터의 메인 소스 파일은 main.dart로 lib 폴더 안에 있음.
    • import 구문 자바의 import처럼 해당 소스에서 사용하려는 패키지를 불러올 때 사용하는 구문임. 다른 다트 클래스나 pubspec.uaml 파일에서 내려받은 패키지를 불러올 때도 사용함.
      import 'package:flutter/material.dart';
      이 패키지에는 플러터의 UI와 관련된 모든 클래스가 있어 자주 사용함
    • main함수 여타 타 언어로 작성된 프로그램처럼 main함수에서 부터 시작.
    • 위젯 플러터 앱에서 위젯은 클래스로 구현하며 이를 상속받는 다양한 위젯이 있음. 이를테면, Text 클래슨느 글자를 전문적으로 표시하는 위젯이고 Image 클래스는 이미지를 전문적으로 표시하는 위젯, 그리고 Button 클래스는 버튼을 표시하는 위젯임.
    • 그 외
      • extends(상속을 나타내는 키워드)를 써서 클래스로부터 상속 가능
      • @override 에너테이션을 사용해 함수 재정의도 가능함.
      • build 함수에서는 어떤 위젯을 만들 것인지 재정의 가능함.
      • theme함수에서는 지금 만들 앱의 테마를 어떤 색상으로 할 지 정의 가능
      • visualDensity 속성은 앱이 모바일이나, 웹, 데스크톱, 맥 등 어떤 플랫폼에서도 자연스럽게 보이도록 지원함.

상태에 따른 위젯 구분

플러터 앱을 구성하는 위젯은 스테이트리스스테이트 풀 두 가지로 구분 가능함.

이 구분은 상태 연결과 관련이 있음

  • 스테이트리스 위젯 내용을 갱신할 필요가 없는 위젯은 화면에 보이기 전에 모든 로딩을 마침. 따라서 앱이 위젯의 상태를 감시할 필요가 없음. 이처럼 상태를 연결할 필요가 없는 위젯을 스테이트리스 위젯이라고 하며 StatelessWidget 클래스를 상속받아 만듦.
  • 스테이트 풀 위젯 위의 스테이트리스 위젯과 다르게 내용을 갱신해야 할 때 사용. 앱이 위젯의 상태를 감시하다가 위젯이 특정 상태가 되면 알맞은 처리를 수행해야 함. 상태가 연결된 동적인 위젯을 스테이트풀 위젯이라고 하며 Stateful Widget 클래스를 상속받아 만듦. 스테이트 풀 위젯은 언제든 상태가 변경되면 특정한 처리를 수행해야 하므로 항상 지켜봐야 함. 메모리나 CPU 등 자원을 그 만큼 많이 사용함. (+) 스테이트 풀 위젯은 혼자서 화면을 출력할 수 없고 State 클래스가 필요함. 그러므로 State 클래스를 상속 받는 내부 클래스를 만들고 그 안에 앞에서 만들어 놓은 위젯을 담아야 함. 그 상속 받은 클래스는 createState() 함수를 재정의한 후 함수를 호출함. 그렇게 하면 해당 클래스가 현재 화면을 보다가 상태가 변경되면 이를 감지하고 내부 클래스가 화면을 갱신함. ⇒ createState로 상태를 만들고, setState로 변경한 스테이트를 적용하는 형식.
    .
    .
    .
    onPressed: (){
    	if (_color == Colors.blue){
    		setState(() {
    			test = 'flutter';
    			_color = colors.amber; 
    		}}
    }

추가

  • 기본적인 화면 구조에서 벗어나면 기본 테마가 적용되지 않고 텍스트에 노란 밑줄이 생김.
    • 플러터의 기본 배경색은 검은색이며 위젯은 왼쪽에서 오른족으로, 위에서 아래쪽으로 그려짐. 왼쪽 위가 위젯이 그려지는 시작점이라고 보면 됨.
  • 핫 리로드 기능은 Ctrl + \ 키로 동작
    • Ctrl + S를 눌러 저장하는 것만으로도 핫 리로드 기능이 자동으로 실행되어 바뀐 코드가 적용됨.
  • child 옵션은 자신 아래 어떤 위젯을 넣겠다는 의미인데 하나만 넣을 때는 child, 여러 위젯을 넣고 싶을 때는 children 옵션을 사용함.
    .
    .
    .
    home: Center(
    	child : Text('Hello', textAlignL TextAlign.center)
    ));
    .
    .
    .
  • 배경을 바꾸려면 Container가 필요함. Container는 플러터에서 가장 많이 사용하는 위젯 중 하나로 특정 공간을 책임지는 역할을 수행함. 그 공간에서 정렬, 여백 등 다양한 역할을 감당하는 만능 위젯임.
    home: Container(
    	child : Center(
    		child : Text('Hi')
    	)
    )
  • 앱의 머터리얼 디자인을 적용하려면 Scaffold 클래스를 이용함.

위젯의 생명주기 이해하기

스테이트리스 위젯은 한 번 만들어지면 갱신할 수 없으므로 생명주기가 없음.

즉, 다른 위젯으로 넘어가면 모든 로직이 종료됨.

그러나 스테이트풀 위젯은 10단계로 구분하는 생명주기가 있음.

[추가] 왜 State와 StatefulWidget 클래스를 나눠 놓아 고통받게 만들었을까?

  • 성능 때문. State 클래스가 StatefulWidget 클래스보다 상대적으로 더 무겁기 때문에 StatefulWidget에서 감시하고 있다가 상태 변경 신호가 오면 State 클래스가 화면을 갱신하도록 구현함. StatefulWidget에서 바로 갱신하면 나중에 화면이 종료되어도 할당받은 메모리를 없앨 때까지 오랜 시간이 걸릴 수 있음. 따라서 상태 변경 감시는 StatefulWidget 클래스가 담당하고 실제 갱신은 State가 담당하도록 분리함.

  1. 상태를 생성하는 createState() 함수

    먼저 statefulWidget을 상속받는 클래스는 반드시 createState() 함수를 호출해야 함.

    이 함수는 다른 생명주기 함수들이 포함된 State 클래스를 반환함. 즉, 위젯의 상태를 생성하는 함수임.

  2. 위젯을 화면에 장착하면 mounted == true

    createState() 함수가 호출되어 상태가 생성되면 곧바로 mounted 속성이 true로 변경됨.

    mounted 속성이 true라는 것은 위젯을 제어할 수 있는 buildContext 클래스에 접근할 수 있다는 의미와 동일함.

    buildContext가 활성화되어야 비로소 setState() 함수를 이용할 수 있음. 아니면 오류가 발생함.

    화면 구성도 안 되었는데 setState() 함수로 위젯을 건드릴 수는 없음.

    다음처럼 setState() 함수를 호출하기 전에 mounted 속성을 점검 코드로 사용하면 좀 더 안전하게 코드를 작성할 수 있음.

    if (mounted){
    	setState()
    }
  3. 위젯을 초기화하는 initState() 함수

    initState() 함수는 위젯을 초기화할 때 한 번만 호출함.

    데이터 목록을 만들거나 처음 필요한 데이터를 주고 받을 때 사용함.

    initState() 함수를 호출할 때 내부에서 _getJsonData() 함수를 호출해 서버에서 받아온 데이터를 화면에 출력하게 만들 수 있음.

    만약 네트워크 통신이 안 되거나 데이터가 이상하다면 화면에 표시하기 전에 미리 알아서 적절하게 대응해야 하므로 위젯을 초기화하는

    initState() 함수에서 데이터를 준비해놓는 것이 좋음.

  4. 의존성이 변경되면 호출되는 didChangeDependencies() 함수

    initState() 함수가 호출된 후에 이어서 바로 호출되는 함수가 didChangeDependencies()

    이 함수는 데이터에 의존하는 위젯이라면 화면에 표시되기 전에 꼭 호출해야 함.

    주로 상속받은 위젯을 사용할 떄 피상속자가 변경되면 호출함.

  5. 화면에 표시하는 build() 함수

    해당 함수는 위젯을 반환함. ( = 화면에 위젯을 렌더링함)

    build 함수에서 위젯을 만들고 반환하면 비로소 화면에 표시됨.

  6. 위젯을 갱신하는 didUpdateWidget() 함수

    부모 위젯이나 데이터가 변경되어 위젯을 갱신해야 할 때 호출함. 만약 initState()에서 특정 이벤트에 의해 위젯이 변경되면

    didUpdateWidget() 함수를 호출해 위젯을 갱신할 수 있음.

    initState() 함수는 위젯을 초기화할 때 한 번만 호출되므로 위젯이 변경되었을 때 호출하는 didUpdateWidget() 같은 함수가 필요함.

  7. 위젯의 상태를 갱신하는 setState() 함수

    setState() 함수를 이용하면 데이터가 변경되었다는 것을 알려주고 변경된 데이터를 이용해 화면의 UI를 변경할 수 있도록 함.

    플러터 앱을 만든다는 것은 곧 앱의 화면을 구성하는 일이므로 제일 많이 호출하는 함수.

  8. 위젯의 상태 관리를 중지하는 deactiviate() 함수

    deactiviate() 함수는 State 객체가 플러터의 구성 트리로부터 제거될 때 호출됨.

    다만, State 객체가 제거되었다고 해서 해당 메모리까지 지워지지는 않음.

    dispose() 함수를 호출하기 전까지는 State 객체를 재 사용 가능함.

  9. 위젯의 상태 관리를 완전히 끝내는 dispose() 함수

    state 객체를 영구적으로 소멸할 때 호출.

    네트워크 통신이나 스트림 통신을 하다가 dispose() 함수를 호출하면 데이터 전송을 중지함.

    그리고 위젯을 소멸할 때 꼭 호출해야 하는 함수라면 dispose() 함수 내에서 호출해야 함.

    앞에서 살펴 본 dispose() 함수 호출로 State 객체를 트리에서 제거한 후에 같은

    State를 다시 다른 트리에 재사용할 경우 dispose() 함수가 호출되지 않을 수 있음. (물론 흔한 경우는 아님!)

  10. 위젯을 화면에서 제거하면 mounted == False

    State 객체가 소멸하면 마지막으로 mounted 속성이 false로 되면서 생명주기가 끝남.

    mounted 속성이 false라는 의미는 이 state는 재사용할 수 없다는 의미와 동일함.

    그러므로 setState() 함수를 호출하면 오류가 발생함.


profile
개발자에서, IT Business 담당자로. BrSE 업무를 수행하고 있습니다.

0개의 댓글

관련 채용 정보