Flutter Mason 도입기

부리부리대마왕·2025년 4월 29일
0
post-thumbnail

🌤️ 개요

얼마 전 Intellij 에서 Cursor로 IDE를 옮겼다. Intellij도 나름 세팅을 잘 해놔서 꽤 효율적으로 사용하긴 했는데... Cursor를 체험해 보고 갈아탈지 엄청 고민했다. 회사에서 앱 개발을 혼자 맡다 보니, 최대한 낭비하는 시간이 없이 빠르게 개발 사이클을 돌려야 하는데, 그런 측면에서 Cursor는 효율이 잘 나올거라 생각하고, 과감하게 Cursor로 갈아탔다.

회사 특성상 기능들이 빠르게 추가, 제거가 되는 일이 빈번한데, 그럴때마다 유사한 Class, Page, View 등을 매번 만들었다 지우기를 반복했다. 물론 스니펫을 사용해서 어느 정도 코드 레벨에서의 템플릿을 구축하고 있긴 했는데, vscode에서 폴더 레벨까지 템플릿으로 만드는 방법을 찾을 수가 없었다. (내가 못 찾는 거일 수도 있음 ㅎㅎ;) 물론 템플릿 생성을 지원하는 extension 들은 본 것 같긴 한데, 왠지 사용하기 싫었다. 그리고 그건 나 개인의 IDE에 적용되기 때문에, 다른 사람들이랑 공유가 안 되는 단점도 있다.

그냥 반복되는 모든 구조를 다 템플릿으로 만들어버리는 방법이 없는지 찾아봤다. 그러다 구글링을 좀 해보니, Mason 이라는 Dart 기반 파일/폴더 템플릿 생성 툴을 사용하면 쉽게 템플릿을 만들 수 있을 것 같아서 재미삼아 도입해 보려 했다.



✅ Mason 이란?

Mason은 Dart 생태계에서 반복되는 파일/폴더 구조를 템플릿으로 만들어주는 CLI 도구라고 한다. Dart 패키지이며, 내가 현재 앱에서 사용 중인 Spider(Asset 관리에 특화된 코드 생성기)와 비슷한 역할을 하는 코드 제네레이터다. 그냥 내가 딱 찾던 역할을 하는 툴이다.



💡 이걸 왜 사용하는지?

반복되는 코드, 폴더 생성을 자동화해서 생산성을 높이기 위함이다.다수의 개발자가 있는 팀에서는 통일된 구조로 템플릿을 만들어서 사용하면 컨벤션 지키기도 괜찮을 것 같고, 온보딩 같은 곳에도 쓰이면 좋을 것 같다.



📚 Mason 시스템 구축

1. Mason CLI 설치

dart pub global activate mason_cli

Dart 패키지 설치 명령어를 사용한다. 다른 팀원이 Mason 을 사용하기 위해서도 해당 팀원의 환경에도 mason이 설치되어 있어야 한다.

설치 후 mason --version 으로 정상 설치되었는지 확인한다.


2. Mason 프로젝트 초기화

mason init

Init 명령어를 실행하면 mason.yaml 파일이 Init 명령어를 실행한 경로에 생성된다. 이 mason.yaml파일은 Flutter의 pubspec.yaml 이랑 동일한 역할을 한다고 생각해도 된다. 내부, 외부에 있는 Brick이라는 템플릿 패키지를 등록하고, 다운받는다. pubspec.yaml처럼 내부 Brick은 Path를 지정해서 등록한다.

Brick은 그냥 템플릿 그 자체라고 생각하면 된다.

source ~/.zshrc

Init이후엔 안내하는 대로 source명령어를 통해 Dart cli설정을 적용시켜주자.



🧵 Custom Brick 만들기

1. Brick 생성

mason new <template_name>
mason new <template_name> -o <path>

새로운 템플릿(Brick)을 만드는 과정이다. -o 옵션은 특정 Path에 Brick을 만들고, 옵션을 따로 넣지 않으면 명령어를 실행한 디렉토리에 새로운 Brick을 생성한다.

명령어가 정상적으로 실행되면 이렇게 <template_name>으로 지정한 폴더와 하위에 기본 템플릿 폴더 및 파일들이 생성된다.


2. Template 작성

// 예시
sealed class {{name.pascalCase()}}State {
  const {{name.pascalCase()}}State();
}

class InitialState extends {{name.pascalCase()}}State {
  const InitialState();
}

이제 진짜 사용할 템플릿 코드를 작성하면 된다. 템플릿은 __brick__ 폴더 하위에 작성한다. 대략 위와 같은 형식으로 작성한다. Brick을 만들 때도 문법이 있는데, 자세한 문법은 Brick Syntax를 참조하면 좋다.

템플릿을 다 작성했으면, 이제 brick 폴더 하위 구조가 위 사진과 같이 구성될 것이다.



🧤 Brick 추가, 제거

이제 템플릿을 다 작성했으니, yaml 파일 등에 어떤 템플릿을 사용할지 등록해야 한다. 등록 및 해제하는 방법은 간단하다.

Brick 등록

bricks:
  page:
    path: mason_templates/page

mason.yaml파일에 만들어둔 Brick 을 등록한다. 나의 경우엔, brick들을 mason_templates이라는 폴더 하위에 만들어서 path 가 위와 같다.

mason add <brick_name> --path <brick_path>

직접 작성하지 않고 CLI 로 등록할 수도 있다. pub_dev 에서 설치하는 패키지처럼, 직접 pubspec.yaml 에 등록할 수도 있지만, CLI 를 통해 설치하는 방법도 있듯이 mason도 동일하다.


Brick 제거

mason remove <brick_name>

remove 명령어는 템플릿 자체를 지우는 게 아니고, yaml 파일에서 <brick_name> 을 갖는 brick의 의존성만을 없애는 명령어다. 이것 또한 수기로 mason.yaml 파일에서 그냥 지워도 된다.



📌 템플릿 적용

mason make <brick_name>

make 명령어를 사용해 템플릿 코드를 생성한다. brick 을 생성하면 brick 폴더 내부에 brick.yaml 파일이 존재하는데, 이 brick.yaml 파일은 템플릿을 만들 때 사용 할 변수, 프롬프트 등을 설정하는 파일이다. 그래서 brick 하나당 한 개씩 맵핑되어 있다.

위의 brick 폴더 내부에 정의된 brick 이 make 명령어를 통해 위 이미지에 보이는 코드를 생성해준다.



🧱 구조

mason.yaml                  # mason init 을 한 디렉토리 기준

< ------------------>

<brick_name>/               # mason new 명령어로 생성된 템플릿 폴더
├── brick.yaml              # 템플릿 메타 정보 및 변수 정의 파일
└── __brick__/              # 템플릿 코드가 들어있는 실제 폴더
    ├── {{variable}}.dart   # 변수 치환 가능한 파일명과 내용
    └── ...    

mason init, mason new <brick_name> 을 통해 생성되는 폴더 및 파일들이다. 하나씩 간략하게 각 파일 및 폴더가 무슨 역할을 하는지만 보면 좋을 것 같다.

mason.yaml

bricks:
  page:
    path: mason_templates/page
  • 템플릿을 사용하는 쪽에서 필요함.
  • mason make 를 실행 할 계층과 관련됨
  • 어떤 brick 들을 사용할 지 (로컬, Git Path, BrickHub)
  • mason add 명령어를 쓰면 해당 파일이 자동으로 수정됨

Mason은 초기화 위치에 따라 템플릿이 적용되는 범위가 결정된다.
예를 들어, lib/ 디렉토리 하위에서 mason init을 수행하면, 해당 위치를 기준으로 생성된 mason.yaml은 lib/ 이하에서만 유효하며, 상위 디렉토리에서는 해당 브릭들을 인식할 수 없다. 따라서 프로젝트 규모가 크거나 패키지/모듈 단위로 관리되는 구조라면, 각 모듈별로 필요한 브릭만 별도로 구성해 모듈 단위로 Mason을 운영할 수 있다.


brick.yaml

name: page
description: A simple page template
vars:
  name:
    type: string
    description: Your name
    default: snake_case
    prompt: input file name
  • vars에 선언한 변수는 {{name}}처럼 템플릿에서 사용할 수 있음
  • type, description, default, prompt 등 다양한 설정 가능

mason make를 통해 직접 선언된 name을 받을 수 있다.

Argument로 var 값을 넣어서 명령어 실행 시, 따로 프롬프트 없이 입력된 변수 값으로 실행된다.



‼️ 주의사항

Syntax Error

Brick 템플릿에 사용되는 {{변수}} 문법은 Dart 문법이 아니기 때문에 Syntax Error가 발생한다. 물론 빌드하는데 영향은 없지만, Analyzer에 잡혀서 거슬린다.

analyzer:
  errors:
    constant_identifier_names: ignore
  exclude:
    - "**/__brick__/**"
include: package:flutter_lints/flutter.yaml

그럴 땐 analysis.yaml 에서 직접 Mason 템플릿 관련 디렉토리를 exclude 한다.



😮 후기

CLI 기반이다 보니 템플릿을 구성해야 할 디렉토리 위치를 찾아 들어가서 명령어를 입력해야 해서 약간 귀찮긴 하다. 그래도 직접 폴더 구성하고 파일 만드는 시간보다는 훨씬 적으니 그거로 만족...

컨벤션이 확실하게 정해져 있다면 더 편리할 것 같다. 예를 들어, "page 템플릿은 무조건 lib/app/module 밑에만 생성된다". 라는 컨벤션이 있으면 스크립트를 만들어서 의도에 맞게 Path를 미리 지정해주면 굳이 생성할 위치를 찾아가지 않아도 될 것 같다.



참조

0개의 댓글