오늘은 다른 프로그래밍 언어/프레임워크에서도 자주 나오는 개념인 비동기 프로그래밍을 Flutter의 관점에서 한 번 살펴보려고 합니다. 특히, 이 글에서는 Flutter에서 비동기 프로그래밍을 이해하는 데 필요한 핵심 개념인 Future와 async/await 을 중심으로 알아보겠습니다.
1. 비동기 프로그래밍이란 무엇인가?
비동기 프로그래밍이란 작업이 완료되기를 기다리지 않고 다른 작업을 계속할 수 있는 프로그래밍 방식입니다.
Flutter는 기본적으로 단일 스레드로 동작하기 때문에, 무거운 작업을 동기 방식으로 처리하면 UI가 멈추는 문제가 발생할 수 있습니다. 네트워크 요청이나 파일 읽기 같은 오래 걸리는 작업을 수행할 때가 대표적인 예시죠.
이 때, 비동기 프로그래밍을 사용하면 앱이 네트워크 요청, 파일 시스템 접근, 데이터베이스 쿼리 등을 처리하는 동안에도 사용자 인터페이스가 원활하게 동작하게 할 수 있습니다.
2. Future란 무엇인가?
Flutter에서 비동기 작업은 Future 객체로 표현됩니다. Future는 미래에 완료될 작업을 나타내며, 이 작업이 완료되면 성공 또는 실패 결과를 반환합니다. Future는 JavaScript의 Promise와 유사한 개념으로, 비동기 작업의 결과를 나중에 받기 위해 사용됩니다.
예를 들어, 서버에서 데이터를 가져오는 작업은 시간이 걸릴 수 있는데, 이 작업을 Future로 처리하여 결과가 반환될 때까지 기다릴 수 있습니다. Future는 다음과 같은 두 가지 상태를 가집니다:
- 완료되지 않음 (Pending): 작업이 아직 완료되지 않은 상태.
- 완료됨 (Completed): 작업이 완료되어 성공 또는 실패로 결과가 반환된 상태.
Future<String> fetchData() {
return Future.delayed(Duration(seconds: 2), () {
return '데이터 로드 완료';
});
}
위 코드에서 fetchData 함수는 2초 후에 데이터를 반환하는 비동기 작업을 나타냅니다. Future는 데이터를 즉시 반환하지 않고, 2초 후에 완료될 것임을 나타냅니다.
3. async와 await의 역할
Future를 사용할 때 결과를 처리하는 두 가지 방법이 있습니다.
then() 메서드를 사용하는 방법과 async/await 키워드를 사용하는 방법입니다.
두 가지 방법 중, Flutter에서는 주로 async/await을 사용하여 비동기 작업을 처리하는 것이 가독성이 좋고, 코드가 더 직관적입니다.
3.1 async 키워드
async 키워드는 함수가 비동기 작업을 포함하고 있다는 것을 Flutter에 알리는 역할을 합니다. async로 선언된 함수는 무조건 Future를 반환하며, 해당 함수 내에서 비동기 작업을 처리할 수 있습니다.
Future<void> loadData() async {
// 비동기 작업 수행
}
3.2 await 키워드
await 키워드는 Future가 완료될 때까지 기다렸다가, 그 결과를 받아올 수 있도록 도와줍니다.
await를 사용하면 Future가 완료될 때까지 다음 코드가 실행되지 않으며, Future의 결과를 변수에 저장할 수 있습니다.
Future<void> fetchData() async {
String data = await loadData();
print(data);
}
await는 비동기 작업의 결과를 기다리는 동안 다른 작업이 동기적으로 실행되지 않도록 보장합니다.
위 코드를 기준으로 설명드리면, loadData() 함수의 결과가 완료될 때까지 기다린 후, 그 값을 data 변수에 저장하고 출력하는 구조인 것입니다.
4. async/await 사용 예시
다음은 간단한 예시로, 서버에서 데이터를 가져오는 비동기 작업을 처리하는 방법입니다. fetchData 함수는 2초 후에 데이터를 반환하고, 해당 데이터를 출력하는 코드입니다.
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return '서버에서 데이터를 가져왔습니다.';
}
void main() async {
print('데이터 가져오는 중...');
String data = await fetchData();
print(data);
}
이 예시에서 await 키워드를 사용하여 fetchData() 함수가 완료될 때까지 기다렸다가, 완료된 결과를 data 변수에 저장한 후 출력하게 되고, 출력 결과는'데이터 가져오는 중...'과 '서버에서 데이터를 가져왔습니다.' 이 됩니다.
5. then() 메서드와 async/await 비교
Future의 결과를 처리할 때 async/await 외에도 then() 메서드를 사용할 수 있습니다. then()은 Future가 완료된 후 수행할 작업을 정의할 수 있는 메서드입니다.
fetchData().then((data) {
print(data);
});
위 코드에서 fetchData()가 완료된 후, 그 결과가 data로 전달되어 출력됩니다. 하지만 then()을 사용하면 중첩된 콜백 함수가 많아져 코드가 복잡해질 수 있습니다. 반면, async/await을 사용하면 비동기 코드를 동기 코드처럼 작성할 수 있어 가독성이 훨씬 좋아집니다.
- then을 사용한 경우
fetchData().then((data) {
print('데이터: $data');
}).catchError((error) {
print('오류 발생: $error');
});
- async와 await을 사용한 경우
try {
String data = await fetchData();
print('데이터: $data');
} catch (error) {
print('오류 발생: $error');
}
async/await 방식은 오류 처리도 try-catch 블록을 사용하여 더욱 직관적으로 작성할 수 있습니다. 따라서 코드의 복잡도를 낮추고 가독성을 높이는 데 유리합니다.
6. 비동기 프로그래밍을 사용할 떄 주의점
비동기 작업을 사용할 때 주의할 점은 메인 스레드를 차단하지 않도록 설계하는 것입니다. Flutter는 싱글 스레드로 동작하기 때문에, 모든 작업이 동기적으로 처리되면 UI가 멈추는 현상이 발생할 수 있습니다. 이를 방지하려면, 비동기 프로그래밍을 통해 작업을 백그라운드에서 처리하고, 그 결과를 UI에 반영하는 구조로 앱을 설계해야 합니다.
7. 결론
Flutter에서 비동기 프로그래밍은 앱 개발에 있어서 필수적인 기술입니다. Future, async/await는 비동기 작업을 처리하는 기본적인 도구이며, 이를 활용하여 네트워크 요청이나 파일 읽기 같은 시간이 오래 걸리는 작업을 처리할 수 있습니다. 또한 async/await 키워드를 사용하면 더 깔끔하고 직관적인 코드를 작성할 수 있으며, UI가 멈추지 않는 사용자 친화적인 앱을 개발할 수 있습니다.
비동기 프로그래밍을 잘 활용하면 복잡한 작업도 효율적으로 처리할 수 있고, 앱 성능을 극대화할 수 있습니다. Future와 async/await에 대한 개념을 확실히 이해하고 이를 프로젝트에 적절하게 적용해서 좋은 앱을 만드는 데 이 글이 도움이 되었으면 좋겠습니다.
'Flutter' 카테고리의 다른 글
Flutter의 핵심 위젯, Container 완벽 가이드: 속성부터 활용법까지 (0) | 2024.10.13 |
---|---|
[Flutter] StatefulWidget VS StatelessWidget 실제 코드와 함께 살펴보기 (0) | 2024.10.13 |
Flutter에서 화면을 전환하는 방법: Navigator 기본 사용법 (0) | 2024.10.13 |
Flutter의 가장 기본적이고 중요한 개념, 위젯에 대해 알아보기 (2) | 2024.10.12 |
요즘 뜨고 있는 Flutter 프레임워크에 대해 알아보기 (0) | 2024.10.12 |