문제 상황
플러터 웹을 구현하던 도중 애니메이션 효과가 너무 무거웠다. iOS의 경우 animation을 줄 때 비동기 프로그래밍으로 계산을 처리하기 때문에 여기서 아이디어를 얻어 isolated 를 써서 다른 스레드에서 작업을 돌리려고 했다. 하지만 애니메이션 효과는 영원히 나타나지 않았고 디버그 모드로 다시 실행시켜보니...
플러터 웹은 isolated를 지원하지 않는다고 한다....;;;;
아무리 모바일보다는 덜 사용하는 플러터 웹이지만 대부분 프레임워크에서 거의 필수적으로 들어가는 동시성 프로그래밍이 안된다는게 너무 이상해서 구글링을 해보았다. 다행히 isolate가 아닌 다른 방법으로 멀티프로세싱을 구현할 수 있었다.
Flutter Web에서 멀티 프로세싱하기
Flutter 웹에서 Isolate 없이 동시성 프로그래밍을하고 싶다면 dart:html 패키지를 통해 할 수 있다. 자바스크립트에서는 멀티 프로세싱을 위해 Web Worker 를 쓰고 있는데 html 패키지는 이러한 자바스크립트의 Webworker 기능을 포장하여 다트로 쓸 수 있게 해준다. 사실상 자스의 웹워커 기능을 사용하는거랑 같기 때문에 작동원리를 이해하기 위해서는 자바스크립트의 웹워커를 알아야한다.
Swift 언어처럼 하나의 코어에서 멀티스레딩을 지원하는 것과 달리 다트와 자스는 또 다른 스레드를 백그라운드로 돌리기 위해서는 어쩔 수 없이 코어 하나를 더 쓰게 된다. 메인 코어와 다른 코어 사이의 통신은 이벤트 루프에 의해 처리되고 각 코어의 스레드는 워커를 통해 만들어진다. 그리고 워커간의 메세지 교환은 postMessage() 와 onMessage() 메서드를 통해 이루어진다.
자바스크립트의 Worker를 플러터에서 동작시키기 위해서는 다트의 Blob이란 객체가 필요하다. Blob(Binary Large Object)의 어원을 살펴보자면 웹에서 이진 데이터의 큰 덩어리를 표현하는 객체로 메모리 상에 저장된 데이터의 덩어리 그자체이다.
Blob 객체 내부를 들여다보면 위와 같은데. 하나씩 살펴보자면 먼저 Native("Blob") 어노테이션은 Dart가 JavaScript의 Worker 객체와 연결되도록 해준다. 그리고 Blob 클래스는 JavaScriptObject를 상속하여 JavaScript의 기능을 쓰게 된다.
눈여겨 볼점은 생성자로 팩토리를 이용해 싱글톤 처리를 해주고 있다는 점이다. 따라서 (revokeObjectUrl() 메서드를 통해) blob을 만든다면 이후 메모리 해제가 중요하다는 것을 알 수 있었다.
위 코드를 통해 간단한 플러터웹 동시성 구현을 해보았다. 먼저 Blob 을 생성하고 workerCode 문자열에 Web Worker의 기능을 정의한다. 앞서 Blob이 메모리 데이터 덩어리 그자체라고 했는데 자바스크립트로 작성한 로직을 담고 나중에 이 로직을 스크립트처럼 동작시키는 방식으로 진행된다.
자바스크립트 문법으로 작성된 "데이터"를 실행시키기 위해서는 어디있는 데이터인지 찾기 위해 위치를 알아야하는데 이를 URL이 맡는다. URL을 생성하면, 해당 데이터에 접근할 수 있는 주소를 임시로 생성할 수 있기 때문이다. URL은 웹 페이지나 다른 코드에서 Blob 데이터를 사용할 수 있게 연결하는 다리 역할을 한다.
결과적으로 JavaScript 코드를 Blob에 저장하고 URL.createObjectURL로 URL을 생성하면, Worker가 외부 파일 대신 이 URL을 통해 Blob 데이터를 스크립트처럼 불러와 다른 스레드에서 작업을 하게되는 구조인 것이다..
사용후에는 URL.revokeObjectURL 메서드를 통해 더 이상 사용하지 않는 Blob URL을 해제하여 메모리를 효율적으로 관리한다.
위 코드를 실행시키면 Hello from Worker: Hello Worker! 로 찍혀 동시성 프로그래밍을 확인할 수 있다.
'Flutter' 카테고리의 다른 글
코디네이터 패턴을 플러터에 적용하며 생긴 _debugLocked 에러 (0) | 2025.01.14 |
---|---|
iOS와 다르게 왜 Flutter에서는 Code Gen이 흔한걸까? (1) | 2025.01.04 |
Tabbar 정렬 및 여백조정이 안되는 이슈 (0) | 2024.08.31 |
Warning: integration_test plugin was not detected. 이슈 (0) | 2024.08.14 |
이벤트에 반응하여 Stateless 위젯 아이콘 이미지 색 바꾸기 (0) | 2024.08.13 |