더 빠르고 깔끔하게 Import 하기 : Single Import

Ximya·2023년 7월 8일
4

Plotz 개발일지

목록 보기
10/12
post-thumbnail

해당 포스팅은 유튜브 영화&드라마 리뷰 영상 큐레이션 플랫폼 Plotz를 개발하면서 도입된 기술 및 방법론에 대한 내용을 다루고 있습니다.
다운로드 링크 : 앱스토어 / 플레이스토어

여러분이 개발하고 있는 Flutter 프로젝트의 규모가 커질수록 Import 구문 라인들이 많아질 수밖에 없습니다.
예를 들어 한 화면을 구현한다고 했을 때 기본적으로 Material을Material를 패키지를 import 해야 하고 상태관리 라이브러리를 이용한다면 Provider나 GetX 같은 패키지를 import 하겠죠. 그것뿐만 아니라 앱에서 정의된 컬러나 폰트 등을 관리하는 유틸리티 클래스도 필요하고, 커스텀 위젯이 있다면 구현한 커스텀 위젯도 따로 불러와야 합니다.

import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:soon_sak/app/config/app_insets.dart';
import 'package:soon_sak/app/config/app_space_config.dart';
import 'package:soon_sak/app/config/color_config.dart';
import 'package:soon_sak/app/config/font_config.dart';
import 'package:soon_sak/app/config/size_config.dart';
import 'package:soon_sak/app/di/locator/locator.dart';
import 'package:soon_sak/presentation/base/base_screen.dart';
import 'package:soon_sak/presentation/base/base_view.dart';
import 'package:soon_sak/presentation/common/image/content_poster_item_view.dart';
import 'package:soon_sak/presentation/common/image/round_profile_img.dart';
import 'package:soon_sak/presentation/common/slider/content_post_slider.dart';
import 'package:soon_sak/presentation/common/skeleton_box.dart';
import 'package:soon_sak/presentation/screens/home/home_view_model.dart';
import 'package:soon_sak/presentation/screens/home/localWidget/category_content_section_view.dart';
import 'package:soon_sak/presentation/screens/home/localWidget/home_scaffold.dart';
import 'package:soon_sak/presentation/screens/home/localWidget/paged_category_list_view.dart';
import 'package:soon_sak/domain/model/channel/channel_model.dart';
import 'package:soon_sak/domain/model/content/content_argument_format.dart';
import 'package:soon_sak/domain/model/content/home/banner_model.dart';
import 'package:soon_sak/domain/model/content/home/content_poster_shell.dart';
import 'package:soon_sak/utilities/extensions/tmdb_img_path_extension.dart';


class HomeScreen extends BaseScreen<HomeViewModel> {
  const HomeScreen({Key? key}) : super(key: key);
  ...

그러다 보면 위에 제 홈스크린 코드처럼 어느 순간 이처럼 수많은import 구문이 쌓이게 됩니다.

불편한 점

사실 저렇게 여러 import 구문들이 쌓인다는 건 어떻게 보면 당연한 거고 기능적으로는 문제가 있는 건 아니지만 몇 가지 불편한 점이 생깁니다.

1. 반복적으로 import 문을 적어야 하는 번거로움

새로운 위젯을 만들 때 기본적으로 사용되는 base 모듈(config, extestion 등등)들에 대한 import 구문을 일일이 적는다는 건, 반복적인 작업을 싫어하는 개발자들에게는 꽤 귀찮은 작업일 수 있습니다.

2.불필요한 Merge Conflict 발생

프로덕션 수준의 제품을 개발할 때 여러 개발자가 을 이용해 서로의 작업물을 공유하고 합치는 작업을 합니다. 이때 여러 파일에서 import 구문들이 변경되었다면 merge 하는 과정에서 conflict가 발생할 수 있고 일일이 conflict를 해결해야 하는 번거로움이 생깁니다.

3. 가독성이 떨어짐


또한 불러오는 import구문 많을수록 작업 중에 더 이상 필요 없거나 중복된 import 구문이 쉽게 쌓이게 될 수 있습니다. 이런 코드들을 일일이 삭제하는 것도 또 번거로운 일이겠죠.

[Tip]
Flutter 팀에서 제공하는 dart fix --apply 명령어를 입력하면 불필요한 import 구문을 자동으로 제거해 줍니다.


Single Import 방식으로 Import를 관리

이런 불편한 점들을 해결할 방법은 기존의 Multi Import 대신 Single Import 방법으로 파일을 만들어 호출하는 것입니다.

Single Import방식의 원리는 간단한데요.

export 'package:cupertino_will_pop_scope/cupertino_will_pop_scope.dart';
export 'package:connectivity_plus/connectivity_plus.dart';
export 'package:cached_network_image/cached_network_image.dart';
export 'package:plotz/presentation/screens/search/localWidget/search_scaffold.dart';
export 'package:plotz/presentation/screens/search/localWidget/searched_list_item.dart';
export 'package:plotz/presentation/screens/search/search_view_model.dart';

index.dart라는 임의의 파일을 하나 만들고 해당 파일에 자주 사용되는 모듈에 대한 export 구문을 적는 것입니다.

import 'package:soon_sak/utilities//index.dart';

class HomeScreen extends BaseScreen<HomeViewModel> {
  const HomeScreen({Key? key}) : super(key: key);

그리고 이 index. dart파일을 호출하면 기존처럼 매번 여러 라인의 import 구문들을 적는 번거로운 작업을 피할 수 있게 됩니다.

구조화된 Single Import 파일 (barrel export)


그리고 여러분의 프로젝트가 여러 레이어로 구분되어 있다면 레이어마다 index.dart파일을 구성하는 것도 좋은 방법입니다. 어떤 심볼의 Single Import 파일을 가져왔는지 식별할 수 있기 때문이죠. 이는 보통 barrel export라고 불리기도 합니다.

참고로 여러 파일에 대한 export들을 한 파일에서 관리하는 barrel export 방식은
React, Angular와 같은 웹 프론트엔드 환경에서 자주 사용되곤 합니다.

근데 섹션마다각 섹션마다 index.dart 파일을 만드는 것 자체가 너무 귀찮은 작업이죠. 그래서 Single Import 파일을 쉽게 만들어 주는single_import_generator 패키지를 만들었습니다.

single_import_generator 패키지는 간단한 명령어로 Single Import 파일을 생성하여 프로젝트의 여러 파일의 export 구문들을 조직화하여 생산성가독성을 향상해 주는 데 도움을 줍니다. 예시를 통해 자세히 설명해 드려 보겠습니다.

lib > presentation 경로에 있는 모든 하위의 dart 파일에 대한 export 구문을 담은 index.dart을 만든다고 해봅시다.

$ dart run single_import_generator -target=lib/presentation all

그럼, 위 명령어를 통해 간단하게 index.dart 파일을 만들 수 있습니다.



혹시 하위 경로에 있는 모든 파일을 대상으로 Single Import 파일을 만들기보다는 직속 경로에 있는 파일들만 타겟하고 싶다면, 아래 명령어를 사용하시면 됩니다.

$ dart run single_import_generator -target=lib/presentation/common dir

그럼, 직속 경로에 있는 파일들에 대한 export 구문들을 관리하는 index.dart 파일이 생성됩니다.


또는 반대로, 레이어마다 Single Import 파일을 만들기보다는 자주 사용되는 특정 모듈만 타겟하여 export 구문들을 관리하고 싶다면 패키지의 @SingleImport 어노테이션 기능을 이용해 보실 수 있습니다.

()
class FrequentlyUsedClass {
   ...
}
()
extension SomeStringExtension on String {
  ...
}

위에 코드처럼 자주 사용되는 모듈에 @SingleImport 어노테이션을 표시해 주시면 준비는 끝났습니다.

dart run single_import_generator -path=lib/utilities

그다음 위 명령어를 실행시키면 path argument에 넘겨진 경로에 @SingleImport() 어노테이션으로 마크된 파일들에 대한 export 구문이 담긴 index.dart 파일이 생성되게 됩니다.

export 'package:projectName/domain/frequently_used_class.dart
export 'package:projectName/utilities/some_strig_extension.dart

// Package imports:
export 'package:intl/intl.dart';
export 'package:provider/provider.dart';

또한 어노테이션을 생성되는 index.dart 파일에 자주 사용하는 외부 패키지에 대한 export 구문을 추가하여 관리하는 것도 좋은 방법입니다.

마무리

이번 포스팅에서는 Flutter 프로젝트에서 Single Import 방식을 사용하여 import 구문을 관리하는 방법에 대해 알아보았습니다. 프로젝트의 규모가 커질수록 import 구문이 증가하여 발생하는 불편한 문제들을 Single Import를 활용하여 해결할 수 있습니다. 이때 앞서 말씀드린 single_import_generator 패키지를 이용하면 더 쉽게 Single Import 파일을 손쉽게 만들 수 있으니, 사용을 적극 권장드립니다!
감사합니다.

profile
https://medium.com/@ximya

0개의 댓글