[Flutter] 프로젝트 구조 - Web FE 프레임워크와 비교하여

저우웅·2025년 10월 11일

Flutter

목록 보기
3/8
post-thumbnail

최근 동아리에서 flutter를 공부하고 있습니다.
저는 최근까지 웹 프로젝트만을 진행했던 만큼, Flutter의 프로젝트 구조가 낯설게 느껴졌습니다.
따라서 오늘은 프론트엔트 프레임워크와 Flutter의 프로젝트 구조를 간단히 비교해 보고자 합니다.

해당 글은 개인 공부를 위해 작성된 글로, 틀린 내용이 포함될 수 있습니다.



진입점 entry point

위 사진은 제가 최근 진행한 프로젝트(Vue)의 프로젝트 구조입니다.
웹 프론트엔드의 주요 코드는 src폴더 안에 들어있습니다.
웹 프로젝트의 entry point는 main.js죠!

main.js에는

// Vue
import App from './App.vue'
const app = createApp(App)
app.mount('#app')

또는

// React
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

요런 코드가 있을테고, 이는 App을 루트 컴포넌트로 하여 앱을 실행하겠다는 의미입니다.


한편 Flutter의 프로젝트 기본 구조는 이렇습니다.

Flutter의 주요 코드는 lib폴더 안에 위치하게 됩니다.
Flutter에서는 main.dart가 존재합니다.

import 'app.dart';

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

여기서 runApp은 App을 루트 위젯으로 하여 위젯 트리를 구성하라는 신호를 보냅니다.

그러면 웹에서의 컴포넌트가 플러터의 루트 개념과 동일할까요?
그렇진 않습니다.



Component vs Widget


Component

웹 프론트엔드에서 컴포넌트는 화면의 한 조각을 구성하는 단위입니다.
React나 Vue에서는 버튼, 카드, 네비게이션 바 등을 각각의 컴포넌트로 분리해 재사용합니다.

예를 들면 BottomNavbar.vue 파일로 네비게이션 컴포넌트를 만들어놓고,

// Vue
<template>
// 기타 코드들...
<BottomNavbar />
</template>

<script setup>
import BottomNavbar from '@/components/common/BottomNavbar.vue'
</script>

이런 식으로 네비게이션 바 컴포넌트를 가져와서 페이지 내부에서 사용하죠.


Widget

반면 Flutter의 위젯(Widget) 은 조금 더 포괄적인 개념이라고 생각하면 됩니다.
버튼이나 텍스트 같은 UI 요소뿐만 아니라 스타일, 앱 전체 구조 자체도 위젯이기 때문입니다. (모든 게 위젯인 세계관)


// Flutter
class MyButton extends StatelessWidget {
  final String text;
  const MyButton({required this.text});

  @override
  Widget build(BuildContext context) {
    return Padding( // padding도 위젯!
      padding: const EdgeInsets.all(8.0),
      child: ElevatedButton(onPressed: () {}, child: Text(text)),
    );
  }
}

따라서 Flutter에서는 UI를 그리는 것과 레이아웃을 배치하는 것이 동일한 개념으로 취급됩니다.

정리하자면, component가 화면 조각의 단위라면 widget은 앱 전체를 표현할 수 있는 단위입니다.


Flutter 프로젝트 또한 사진처럼 기능별로 (작은 앱의 경우 화면별로 나누어 관리하기도 한답니다.) 나누어 파일을 관리할 수 있겠네요.

pages, components 라는 폴더 대신 presentation, widgets라는 이름으로 폴더를 만들어 보었습니다.



플랫폼별 폴더

사실 Flutter 프로젝트를 생성했을 때 제일 먼저 눈에 띄었던 폴더는 android, ios, linux, macos, windows, web입니다.

위 파일들은 플러터 앱이 여러 플랫폼에서 잘 돌아갈 수 있도록 각 플랫폼별 빌드 설정과 실행 코드를 관리하는 역할을 합니다.

lib파일 내부의 dart코드가 설계도 역할을 하고, 해당 플랫폼별 폴더들이 OS별 공장을 세팅한다는 느낌으로 이해하면 쉽습니다.

웹 프론트는 당연히 웹 환경에 한정되어 있기 때문에 해당 폴더들이 존재하지 않습니다.



기타 차이점

test 폴더

Flutter 프로젝트 생성시 test 폴더가 기본으로 생기는 것을 볼 수 있습니다.

웹 FE 프로젝트에서는 test폴더가 자동으로 생성되지 않습니다. 프로젝트에서의 테스트 도입 여부에 따라 직접 폴더를 추가해서 사용하며, 테스트를 도입하는 경우 컴포넌트 렌더링 테스트를 위주로 합니다.

Flutter는 모바일/웹/데스크탑을 동시에 지원하기 때문에 테스트의 역할이 강조되기도 합니다.

  1. Flutter는 하나의 코드로 Android, iOS, Web, Desktop을 모두 빌드하기 때문에, 테스트 없이 배포하면 앱이 깨질 수 있고,

  2. 위젯 트리가 커지면 화면 일부를 수정할 때 의도치 않은 부작용이 발생할 수 있습니다.

(Flutter의 테스트에 대해서는 다른 포스트에서 자세히 알아보겠습니다.)




이렇게 Flutter 프로젝트의 구조에 대해서 web FE와 비교하며 알아보았습니다.

사실 이 포스트를 작성하면서 구조보다 렌더링 파이프라인이나 레이아웃 모델에 대해서 비교해보며 썼다면 더 유익하고 재밌는 글이 나오지 않을까 하는 아쉬움이 있었습니다.

따라서 다음은 해당 주제 혹은 관련 주제로 찾아오도록 하겠습니다...😇

부족한 글 읽어주셔서 감사합니다. <<>>

profile
ㅠㅠ

4개의 댓글

comment-user-thumbnail
2025년 10월 12일

웹 FE와 앱은 왜 이렇게 다르게 발전한걸까요....
하나 공부하면 나머지 하나는 공부 안해도 알정도로 비슷하게 만들면 안됐던 걸까요...
왜 손수 진입장벽을 높이는걸까요...

1개의 답글
comment-user-thumbnail
2025년 10월 13일

개인적으로 플러터의 가장 매력적인 포인트가 위젯 개념이라고 생각합니다. 웹 FE에서 매번 id나 class와 같이 연결해주고 설정해주고 하는 고통에서 해방될 수 있는... 이번 글도 잘 읽었습니다!

1개의 답글