mirror of
https://github.com/ChangJoo-Park/learn-flutter.git
synced 2025-06-08 21:53:09 +00:00
686 lines
17 KiB
Markdown
686 lines
17 KiB
Markdown
# 자주 묻는 질문 (FAQ)
|
|
|
|
이 페이지에서는 Flutter 개발 과정에서 가장 자주 묻는 질문들과 그에 대한 답변을 제공합니다.
|
|
|
|
## 환경 설정
|
|
|
|
### Q: Flutter SDK 업데이트는 어떻게 하나요?
|
|
|
|
다음 명령어를 사용하여 Flutter SDK를 최신 버전으로 업데이트할 수 있습니다:
|
|
|
|
```bash
|
|
flutter upgrade
|
|
```
|
|
|
|
특정 채널(stable, beta, dev)로 전환하려면:
|
|
|
|
```bash
|
|
flutter channel stable
|
|
flutter upgrade
|
|
```
|
|
|
|
### Q: Flutter와 Dart의 버전 호환성은 어떻게 확인하나요?
|
|
|
|
Flutter SDK 버전마다 지원하는 Dart 버전이 다릅니다. 현재 설치된 Flutter와 Dart 버전을 확인하려면:
|
|
|
|
```bash
|
|
flutter --version
|
|
```
|
|
|
|
공식 [Flutter 릴리스 페이지](https://docs.flutter.dev/release/archive)에서 각 Flutter 버전이 사용하는 Dart 버전을 확인할 수 있습니다.
|
|
|
|
### Q: MacOS에서 iOS 시뮬레이터를 실행하는 방법은?
|
|
|
|
```bash
|
|
# 사용 가능한 시뮬레이터 목록 확인
|
|
xcrun simctl list devices
|
|
|
|
# 시뮬레이터 실행
|
|
open -a Simulator
|
|
```
|
|
|
|
또는 VS Code의 상태바에서 디바이스 선택 옵션을 통해 iOS 시뮬레이터를 선택할 수 있습니다.
|
|
|
|
## 패키지 및 의존성
|
|
|
|
### Q: pub.dev에서 패키지를 설치하는 가장 좋은 방법은 무엇인가요?
|
|
|
|
패키지를 설치하는 방법은 두 가지가 있습니다:
|
|
|
|
1. 명령줄에서 설치:
|
|
|
|
```bash
|
|
flutter pub add package_name
|
|
```
|
|
|
|
2. `pubspec.yaml` 파일을 직접 수정한 후:
|
|
|
|
```bash
|
|
flutter pub get
|
|
```
|
|
|
|
### Q: 패키지 버전 충돌을 해결하려면 어떻게 해야 하나요?
|
|
|
|
패키지 버전 충돌은 일반적으로 다음과 같은 방법으로 해결할 수 있습니다:
|
|
|
|
1. 종속성 트리를 확인하여 충돌 원인 파악:
|
|
|
|
```bash
|
|
flutter pub deps
|
|
```
|
|
|
|
2. 충돌하는 패키지 버전 범위 조정:
|
|
|
|
```yaml
|
|
dependencies:
|
|
package_a: ^2.0.0 # 버전 범위 조정
|
|
```
|
|
|
|
3. 호환되는 버전으로 업데이트:
|
|
|
|
```bash
|
|
flutter pub upgrade --major-versions
|
|
```
|
|
|
|
### Q: 패키지 개발 시 로컬 패키지를 연결하는 방법은?
|
|
|
|
`pubspec.yaml`에 로컬 경로를 지정할 수 있습니다:
|
|
|
|
```yaml
|
|
dependencies:
|
|
my_package:
|
|
path: ../my_package
|
|
```
|
|
|
|
## 상태 관리
|
|
|
|
### Q: 어떤 상태 관리 솔루션을 선택해야 할까요?
|
|
|
|
상태 관리 솔루션은 프로젝트 규모와 요구사항에 따라 다릅니다:
|
|
|
|
- **작은 프로젝트**: `setState`, `ValueNotifier`, `InheritedWidget`
|
|
- **중간 규모 프로젝트**: `Provider`, `Riverpod`
|
|
- **대규모 프로젝트**: `Riverpod`, `Bloc`, `Redux`
|
|
|
|
Riverpod는 다양한 규모의 프로젝트에 모두 적합하며, 최근에는 보일러플레이트 코드를 크게 줄인 코드 생성 기능을 제공하여 많은 개발자들이 선호합니다.
|
|
|
|
### Q: Riverpod와 Provider의 차이점은 무엇인가요?
|
|
|
|
- **Provider**:
|
|
|
|
- Context에 의존적
|
|
- 위젯 트리 내에서만 동작
|
|
- 단순하고 학습 곡선이 낮음
|
|
|
|
- **Riverpod**:
|
|
- Context에 의존하지 않음
|
|
- 컴파일 타임 안전성
|
|
- 프로바이더 참조가 가능
|
|
- 자동 캐싱 및 종속성 추적
|
|
- 코드 생성을 통한 보일러플레이트 감소
|
|
|
|
### Q: StatefulWidget 대신 Hooks를 사용해야 하는 이유는 무엇인가요?
|
|
|
|
Flutter Hooks는 React의 Hooks에서 영감을 받은 패턴으로, 다음과 같은 장점이 있습니다:
|
|
|
|
1. 상태 로직 재사용 용이
|
|
2. 코드 중복 감소
|
|
3. `initState`, `dispose` 등의 라이프사이클 메서드를 명시적으로 처리할 필요 없음
|
|
4. 더 간결하고 가독성 있는 코드
|
|
|
|
예를 들어, StatefulWidget을 사용하면:
|
|
|
|
```dart
|
|
class CounterWidget extends StatefulWidget {
|
|
@override
|
|
_CounterWidgetState createState() => _CounterWidgetState();
|
|
}
|
|
|
|
class _CounterWidgetState extends State<CounterWidget> {
|
|
int count = 0;
|
|
|
|
void increment() {
|
|
setState(() {
|
|
count++;
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return /* 위젯 빌드 */;
|
|
}
|
|
}
|
|
```
|
|
|
|
Hooks를 사용하면:
|
|
|
|
```dart
|
|
class CounterWidget extends HookWidget {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final count = useState(0);
|
|
|
|
return /* 위젯 빌드 */;
|
|
}
|
|
}
|
|
```
|
|
|
|
## UI 및 레이아웃
|
|
|
|
### Q: 반응형 UI를 구현하는 가장 좋은 방법은 무엇인가요?
|
|
|
|
Flutter에서 반응형 UI를 구현하는 여러 방법이 있습니다:
|
|
|
|
1. **MediaQuery 사용**:
|
|
|
|
```dart
|
|
final width = MediaQuery.of(context).size.width;
|
|
if (width > 600) {
|
|
// 태블릿/데스크톱 레이아웃
|
|
} else {
|
|
// 모바일 레이아웃
|
|
}
|
|
```
|
|
|
|
2. **LayoutBuilder 사용**:
|
|
|
|
```dart
|
|
LayoutBuilder(
|
|
builder: (context, constraints) {
|
|
if (constraints.maxWidth > 600) {
|
|
return WideLayout();
|
|
} else {
|
|
return NarrowLayout();
|
|
}
|
|
},
|
|
)
|
|
```
|
|
|
|
3. **flutter_screenutil** 같은 라이브러리 사용:
|
|
|
|
```dart
|
|
Container(
|
|
width: 100.w, // 화면 너비의 100%
|
|
height: 50.h, // 화면 높이의 50%
|
|
)
|
|
```
|
|
|
|
### Q: ListView의 성능을 최적화하는 방법은?
|
|
|
|
ListView 성능 최적화를 위한 팁:
|
|
|
|
1. `ListView.builder` 사용하여 필요한 항목만 렌더링
|
|
2. `const` 위젯 활용
|
|
3. `RepaintBoundary`로 리페인트 영역 제한
|
|
4. 복잡한 항목에 `cacheExtent` 조정
|
|
5. 이미지에 `cached_network_image` 패키지 사용
|
|
6. 큰 목록은 `ListView.builder` 대신 `Sliver` 위젯 고려
|
|
|
|
```dart
|
|
ListView.builder(
|
|
// 크기 지정으로 불필요한 레이아웃 계산 방지
|
|
itemCount: items.length,
|
|
// 더 많은 항목을 미리 로드하여 스크롤 시 부드럽게
|
|
cacheExtent: 100,
|
|
itemBuilder: (context, index) {
|
|
return RepaintBoundary(
|
|
child: MyListItem(
|
|
key: ValueKey(items[index].id),
|
|
item: items[index],
|
|
),
|
|
);
|
|
},
|
|
)
|
|
```
|
|
|
|
### Q: 스크롤 시 앱바가 사라지는 효과를 구현하려면 어떻게 해야 하나요?
|
|
|
|
`CustomScrollView`와 `SliverAppBar`를 사용하여 구현할 수 있습니다:
|
|
|
|
```dart
|
|
CustomScrollView(
|
|
slivers: [
|
|
SliverAppBar(
|
|
floating: true, // 살짝 스크롤업 하면 보임
|
|
pinned: false, // 스크롤해도 상단에 고정되지 않음
|
|
snap: true, // 스크롤업 시 완전히 표시됨
|
|
title: Text('타이틀'),
|
|
expandedHeight: 200.0,
|
|
flexibleSpace: FlexibleSpaceBar(
|
|
background: Image.asset(
|
|
'assets/header.jpg',
|
|
fit: BoxFit.cover,
|
|
),
|
|
),
|
|
),
|
|
// 나머지 콘텐츠
|
|
SliverList(
|
|
delegate: SliverChildBuilderDelegate(
|
|
(context, index) => ListTile(title: Text('항목 $index')),
|
|
childCount: 50,
|
|
),
|
|
),
|
|
],
|
|
)
|
|
```
|
|
|
|
## 네트워킹 및 API
|
|
|
|
### Q: API 호출 시 최적의 에러 처리 방법은 무엇인가요?
|
|
|
|
API 호출 시 에러 처리를 위한 권장사항:
|
|
|
|
1. 명확한 예외 계층 정의:
|
|
|
|
```dart
|
|
abstract class AppException implements Exception {
|
|
final String message;
|
|
AppException(this.message);
|
|
}
|
|
|
|
class NetworkException extends AppException {
|
|
NetworkException(String message) : super(message);
|
|
}
|
|
|
|
class ServerException extends AppException {
|
|
final int statusCode;
|
|
ServerException(String message, this.statusCode) : super(message);
|
|
}
|
|
```
|
|
|
|
2. API 응답을 Result 패턴으로 래핑:
|
|
|
|
```dart
|
|
class Result<T> {
|
|
final T? data;
|
|
final AppException? error;
|
|
|
|
Result.success(this.data) : error = null;
|
|
Result.failure(this.error) : data = null;
|
|
|
|
bool get isSuccess => error == null;
|
|
bool get isFailure => error != null;
|
|
}
|
|
```
|
|
|
|
3. 비동기 호출 처리:
|
|
|
|
```dart
|
|
Future<Result<UserData>> fetchUserData(String userId) async {
|
|
try {
|
|
final response = await dio.get('/users/$userId');
|
|
return Result.success(UserData.fromJson(response.data));
|
|
} on DioException catch (e) {
|
|
return Result.failure(
|
|
ServerException(
|
|
e.message ?? 'Unknown error',
|
|
e.response?.statusCode ?? 500,
|
|
),
|
|
);
|
|
} on Exception catch (e) {
|
|
return Result.failure(NetworkException(e.toString()));
|
|
}
|
|
}
|
|
```
|
|
|
|
4. UI에서 사용:
|
|
|
|
```dart
|
|
FutureBuilder<Result<UserData>>(
|
|
future: fetchUserData('123'),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return CircularProgressIndicator();
|
|
}
|
|
|
|
if (snapshot.hasData) {
|
|
final result = snapshot.data!;
|
|
|
|
if (result.isSuccess) {
|
|
return UserInfoWidget(user: result.data!);
|
|
} else {
|
|
// 에러 타입에 따른 처리
|
|
if (result.error is NetworkException) {
|
|
return NetworkErrorWidget(
|
|
onRetry: () => setState(() {}),
|
|
);
|
|
} else if (result.error is ServerException) {
|
|
final error = result.error as ServerException;
|
|
return ServerErrorWidget(
|
|
statusCode: error.statusCode,
|
|
message: error.message,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return ErrorWidget('알 수 없는 오류가 발생했습니다.');
|
|
},
|
|
)
|
|
```
|
|
|
|
### Q: Dio vs http 패키지 중 어떤 것을 사용해야 할까요?
|
|
|
|
두 패키지 모두 API 통신에 사용되지만 다음과 같은 차이가 있습니다:
|
|
|
|
- **http 패키지**:
|
|
|
|
- 플러터 팀이 관리하는 공식 패키지
|
|
- 간단한 HTTP 요청에 적합
|
|
- 기본적인 기능만 제공
|
|
|
|
- **Dio 패키지**:
|
|
- 더 많은 기능을 제공
|
|
- 인터셉터, 취소 토큰, 폼 데이터, 글로벌 구성 등 고급 기능
|
|
- 타임아웃, 응답 변환, 에러 핸들링 등의 설정이 쉬움
|
|
- 파일 다운로드/업로드 지원이 더 나음
|
|
|
|
일반적으로 복잡한 API 통신이 필요한 프로젝트에는 Dio를 권장합니다.
|
|
|
|
## 성능 최적화
|
|
|
|
### Q: Flutter 앱의 성능을 분석하는 방법은?
|
|
|
|
Flutter 앱의 성능을 분석하는 여러 도구가 있습니다:
|
|
|
|
1. **Flutter DevTools**:
|
|
|
|
- 위젯 트리 검사
|
|
- 성능 오버레이 (`flutter run --profile` 모드에서 'P' 키)
|
|
- 메모리 프로파일링
|
|
- 네트워크 트래픽 모니터링
|
|
|
|
2. **Flutter Performance 위젯**:
|
|
|
|
```dart
|
|
import 'package:flutter/rendering.dart';
|
|
|
|
void main() {
|
|
debugPaintSizeEnabled = true; // 레이아웃 디버깅
|
|
debugPaintLayerBordersEnabled = true; // 레이어 경계 표시
|
|
debugPaintPointersEnabled = true; // 터치 포인터 표시
|
|
runApp(MyApp());
|
|
}
|
|
```
|
|
|
|
3. **애널리틱스 도구**:
|
|
- Firebase Performance Monitoring
|
|
- Sentry 성능 모니터링
|
|
|
|
### Q: 이미지 로딩 성능을 최적화하는 방법은?
|
|
|
|
이미지 로딩 성능 최적화를 위한 팁:
|
|
|
|
1. `cached_network_image` 패키지 사용:
|
|
|
|
```dart
|
|
CachedNetworkImage(
|
|
imageUrl: "http://example.com/image.jpg",
|
|
placeholder: (context, url) => CircularProgressIndicator(),
|
|
errorWidget: (context, url, error) => Icon(Icons.error),
|
|
)
|
|
```
|
|
|
|
2. 적절한 크기의 이미지 로드:
|
|
|
|
```dart
|
|
// 서버에서 이미지 크기 조정 (쿼리 파라미터 활용)
|
|
Image.network('https://example.com/image.jpg?width=300&height=300')
|
|
|
|
// 또는 Flutter에서 이미지 크기 제한
|
|
Image.network(
|
|
'https://example.com/large-image.jpg',
|
|
cacheWidth: 300, // 메모리에 캐시되는 이미지 크기 제한
|
|
cacheHeight: 300,
|
|
)
|
|
```
|
|
|
|
3. 여러 해상도 지원:
|
|
|
|
```dart
|
|
// 2x, 3x 해상도 이미지 제공
|
|
AssetImage('assets/image.png')
|
|
```
|
|
|
|
4. 이미지 포맷 최적화:
|
|
- JPEG: 사진에 적합
|
|
- PNG: 투명도가 필요한 이미지에 적합
|
|
- WebP: 더 나은 압축률 (작은 파일 크기)
|
|
|
|
## 앱 배포
|
|
|
|
### Q: 앱 출시 전 체크리스트에는 어떤 것들이 있나요?
|
|
|
|
앱 출시 전 체크리스트:
|
|
|
|
1. **앱 성능 및 UI 검토**
|
|
|
|
- 다양한 기기에서 테스트
|
|
- 화면 회전 및 다양한 화면 크기 대응
|
|
- 다크 모드 지원 확인
|
|
|
|
2. **리소스 최적화**
|
|
|
|
- 이미지 최적화
|
|
- 앱 크기 최소화
|
|
- 불필요한 의존성 제거
|
|
|
|
3. **Error handling**
|
|
|
|
- 모든 에러 시나리오 테스트
|
|
- 충돌 리포팅 도구 통합 (Firebase Crashlytics, Sentry 등)
|
|
|
|
4. **권한 및 개인정보 처리**
|
|
|
|
- 최소 필요 권한만 요청
|
|
- 개인정보 처리방침 준비
|
|
- GDPR/CCPA 준수 확인
|
|
|
|
5. **접근성**
|
|
|
|
- 화면 낭독기 지원
|
|
- 충분한 색상 대비
|
|
- 확대/축소 지원
|
|
|
|
6. **앱 메타데이터**
|
|
- 스크린샷 및 아이콘 준비
|
|
- 앱 설명 및 키워드 최적화
|
|
- 프로모션 자료 준비
|
|
|
|
### Q: Android와 iOS 모두 지원할 때 주의할 점은?
|
|
|
|
Android와 iOS 모두 지원 시 고려사항:
|
|
|
|
1. **플랫폼별 UI 가이드라인**
|
|
|
|
- Material Design (Android)
|
|
- Cupertino (iOS)
|
|
- `flutter/material.dart`와 `flutter/cupertino.dart` 적절히 사용
|
|
|
|
2. **플랫폼별 동작 차이**
|
|
|
|
- 뒤로 가기 제스처 (iOS의 스와이프)
|
|
- 알림 권한 처리 방식
|
|
- 앱 라이프사이클 이벤트 처리
|
|
|
|
3. **플랫폼 감지**
|
|
|
|
```dart
|
|
import 'dart:io' show Platform;
|
|
|
|
if (Platform.isIOS) {
|
|
// iOS 전용 코드
|
|
} else if (Platform.isAndroid) {
|
|
// Android 전용 코드
|
|
}
|
|
```
|
|
|
|
4. **플랫폼별 설정 파일**
|
|
|
|
- AndroidManifest.xml
|
|
- Info.plist
|
|
- 각 플랫폼에 맞는 권한 설명 추가
|
|
|
|
5. **플러그인 호환성**
|
|
- 사용하는 모든 플러그인이 양쪽 플랫폼을 지원하는지 확인
|
|
- 플랫폼별 구현이 필요한 경우 조건부 코드 작성
|
|
|
|
## 디버깅 및 테스팅
|
|
|
|
### Q: Flutter 앱을 효과적으로 디버깅하는 방법은?
|
|
|
|
Flutter 앱 디버깅을 위한 팁:
|
|
|
|
1. **print vs debugPrint**:
|
|
|
|
- `print`보다 `debugPrint` 사용 권장
|
|
- 릴리스 모드에서 자동으로 비활성화됨
|
|
- 출력 속도 제한으로 로그 손실 방지
|
|
|
|
2. **개발자 도구 활용**:
|
|
|
|
- `flutter run` 시 가능한 커맨드 (q, r, p 등) 숙지
|
|
- `flutter run --profile` 또는 `--release`로 성능 테스트
|
|
|
|
3. **IDE 디버깅 도구**:
|
|
|
|
- 중단점(breakpoint) 설정
|
|
- 변수 조사
|
|
- 호출 스택 추적
|
|
|
|
4. **로깅 라이브러리 활용**:
|
|
|
|
```dart
|
|
import 'package:logger/logger.dart';
|
|
|
|
final logger = Logger(
|
|
printer: PrettyPrinter(
|
|
methodCount: 2, // 호출 스택 표시 수
|
|
errorMethodCount: 8, // 오류 발생 시 호출 스택 표시 수
|
|
lineLength: 120, // 출력 줄 길이
|
|
colors: true, // 색상 활성화
|
|
printEmojis: true, // 이모지 표시
|
|
printTime: true, // 시간 표시
|
|
),
|
|
);
|
|
|
|
// 사용
|
|
logger.d("디버그 메시지");
|
|
logger.i("정보 메시지");
|
|
logger.w("경고 메시지");
|
|
logger.e("오류 메시지", error: e, stackTrace: s);
|
|
```
|
|
|
|
### Q: 위젯 테스트와 통합 테스트의 차이점은 무엇인가요?
|
|
|
|
- **단위 테스트**:
|
|
|
|
- 개별 함수, 클래스, 메서드 테스트
|
|
- 외부 의존성 없이 빠르게 실행
|
|
- 예: 유틸리티 함수, 비즈니스 로직
|
|
|
|
- **위젯 테스트**:
|
|
|
|
- 개별 위젯 또는 위젯 그룹 테스트
|
|
- 실제 기기/에뮬레이터 없이 가상 환경에서 실행
|
|
- UI 상호작용 및 렌더링 테스트
|
|
- 예: 폼 제출, 리스트 스크롤, 상태 변경 확인
|
|
|
|
- **통합 테스트**:
|
|
- 실제 기기/에뮬레이터에서 실행
|
|
- 전체 앱 흐름 및 여러 위젯 간 상호작용 테스트
|
|
- 외부 서비스 및 플랫폼 API와 통합 테스트
|
|
- 예: 로그인 프로세스, 데이터 저장/검색, 플러그인 동작
|
|
|
|
## 기타 질문
|
|
|
|
### Q: Flutter 웹 개발 시 주의할 점은?
|
|
|
|
Flutter 웹 개발 시 고려사항:
|
|
|
|
1. **성능 최적화**:
|
|
|
|
- 초기 로딩 시간 최적화 (앱 크기 최소화)
|
|
- 이미지 최적화 및 지연 로딩
|
|
- `flutter build web --web-renderer canvaskit` vs `--web-renderer html` 선택
|
|
|
|
2. **브라우저 호환성**:
|
|
|
|
- 다양한 브라우저에서 테스트
|
|
- 모바일 브라우저 지원 확인
|
|
- 폴백 메커니즘 구현
|
|
|
|
3. **SEO 고려**:
|
|
|
|
- Flutter 웹은 기본적으로 SEO에 취약
|
|
- 서버 사이드 렌더링 또는 정적 HTML 생성 고려
|
|
- 메타데이터 및 robots.txt 관리
|
|
|
|
4. **플랫폼 감지**:
|
|
|
|
```dart
|
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
|
|
|
if (kIsWeb) {
|
|
// 웹 전용 코드
|
|
} else {
|
|
// 모바일 전용 코드
|
|
}
|
|
```
|
|
|
|
### Q: Flutter로 게임을 개발할 수 있나요?
|
|
|
|
Flutter로 간단한 2D 게임을 개발할 수 있습니다. 복잡한 게임은 Unity나 전용 게임 엔진이 더 적합합니다.
|
|
|
|
Flutter 게임 개발을 위한 옵션:
|
|
|
|
1. **Flutter 자체 기능 활용**:
|
|
|
|
- `CustomPainter`로 2D 그래픽 그리기
|
|
- 애니메이션, 제스처 인식기로 인터랙션 구현
|
|
- `StatefulWidget`과 `Ticker`로 게임 루프 구현
|
|
|
|
2. **라이브러리 활용**:
|
|
|
|
- `flame`: Flutter용 게임 엔진 ([링크](https://flame-engine.org/))
|
|
- `flutter_joystick`: 가상 조이스틱 구현
|
|
- `audioplayers`: 게임 오디오 재생
|
|
|
|
3. **한계점**:
|
|
- 복잡한 3D 게임에는 적합하지 않음
|
|
- 높은 프레임 레이트 요구사항에 제약
|
|
- 배터리 소모가 클 수 있음
|
|
|
|
### Q: Flutter Desktop 앱 개발 상태는 어떤가요?
|
|
|
|
Flutter Desktop은 macOS, Windows, Linux를 지원하며 안정적인 버전이 출시되었습니다:
|
|
|
|
1. **현재 상태**:
|
|
|
|
- macOS: 안정 버전 출시
|
|
- Windows: 안정 버전 출시
|
|
- Linux: 안정 버전 출시
|
|
|
|
2. **시작하기**:
|
|
|
|
```bash
|
|
flutter config --enable-windows-desktop
|
|
flutter config --enable-macos-desktop
|
|
flutter config --enable-linux-desktop
|
|
flutter create --platforms=windows,macos,linux my_desktop_app
|
|
```
|
|
|
|
3. **고려사항**:
|
|
|
|
- 파일 시스템 접근
|
|
- 네이티브 메뉴 및 윈도우 관리
|
|
- 플랫폼별 패키징 및 배포
|
|
- 하드웨어 가속
|
|
|
|
4. **추천 패키지**:
|
|
- `window_size`: 창 크기 및 위치 조정
|
|
- `flutter_acrylic`: 윈도우 불투명도 및 효과
|
|
- `desktop_window`: 데스크톱 창 제어
|
|
- `file_picker`: 네이티브 파일 선택 대화상자
|
|
|
|
Flutter Desktop은 계속 발전 중이며, 대부분의 기업용 앱과 도구 개발에 충분한 기능을 제공합니다.
|