안녕하세요, Flutter 개발자 지망생 문호 입니다! 😄
최근 네이버 지역 검색 API를 활용한 장소 검색 앱을 개발하면서 여러 가지 도전 과제를 마주쳤습니다. 그중에서도 특히 기억에 남는 두 가지 트러블슈팅 경험을 공유하려고 합니다. 이 과정에서 얻은 교훈이 다른 개발자들에게도 도움이 되길 바랍니다!
1. 한글 입력 시 자음과 모음이 분리되는 문제
문제 상황
검색바(TextField)를 구현하고 사용자가 검색어를 입력하면 실시간으로 HomeViewModel에서 searchQuery를 업데이트하도록 했습니다. 그런데 실기기에서 테스트를 해보니 한글 입력 시 자음과 모음이 분리되는 문제가 발생했어요. 예를 들어 "맘스터치"를 입력하려고 하면 UI에 "ㅁㅏㅁ" → "마ㅁ" → "맘" 이런 식으로 단계적으로 표시되더라고요. 심지어 updateSearchQuery가 너무 빠르게 호출되면서 검색 요청이 중간에 끊기는 상황까지 발생했습니다.
원인 분석
TextField의 onChanged 이벤트가 키보드 입력마다 즉시 호출되는데, 한글은 자음과 모음이 조합되는 과정에서 여러 번 입력 이벤트가 발생합니다. 이 과정에서 onChanged가 너무 자주 호출되면서 HomeViewModel의 상태 업데이트가 조합이 완료되기 전에 실행된 거예요. 특히 실기기에서 입력 속도와 Flutter의 이벤트 처리 속도가 맞지 않아 문제가 더 두드러졌습니다.
해결 과정
이 문제를 해결하기 위해 입력 이벤트를 지연 처리하는 방법을 고민했습니다. 처음에는 단순히 Future.delayed를 사용해서 지연을 주려고 했지만, 더 체계적인 방법으로 Debouncer 클래스를 구현하기로 했어요. Debouncer를 통해 300ms 동안 추가 입력이 없으면 updateSearchQuery를 호출하도록 했습니다. 추가로 Future.microtask를 사용해 입력 완료 후 UI 업데이트를 마이크로태스크 큐에서 처리하도록 했죠.
class Debouncer {
final Duration delay;
Timer? _timer;
Debouncer({required this.delay});
void run(void Function() action) {
_timer?.cancel();
_timer = Timer(delay, action);
}
void cancel() {
_timer?.cancel();
}
}
// CustomSearchBar에서 사용
onChanged: (value) {
_debouncer.run(() {
Future.microtask(() {
viewModel.updateSearchQuery(value);
});
});
},
이렇게 수정한 후 실기기에서 테스트해보니 한글 입력이 자연스럽게 조합되면서 UI에도 제대로 반영되었습니다. 검색 요청도 입력이 완료된 후에만 실행되어 불필요한 API 호출이 줄어드는 효과도 있었어요!
2. 네이버 API의 KATECH 좌표계를 WGS84로 변환하는 문제
문제 상황
앱에서 geolocator 패키지를 사용하여 사용자의 현재 위치를 기반으로 장소 목록을 거리순으로 정렬하려고 했습니다. 네이버 지역 검색 API는 장소의 위치를 mapx와 mapy 필드로 제공하는데, 이 좌표를 geolocator의 distanceBetween 메서드로 거리를 계산하려고 했어요. 그런데 계산된 거리가 터무니없이 큰 값(예: 3940km)으로 나오는 거예요! 분명 서울 내 장소들인데 이렇게 나올 리가 없죠.
원인 분석
문제를 파악하기 위해 네이버 API 문서를 다시 확인해봤습니다. 알고 보니 mapx와 mapy는 KATECH 좌표계(한국에서 사용하는 좌표계)로 제공되고 있었어요. 반면, geolocator는 WGS84 좌표계(위도, 경도)를 사용하기 때문에 두 좌표계가 달라서 거리 계산이 잘못된 거였습니다. 예를 들어, mapx: 311277, mapy: 552097 같은 값은 위도/경도 값이 아니라 KATECH 좌표계의 x, y 좌표였죠. 이걸 그대로 위도/경도로 사용하려니 엉뚱한 결과가 나온 거예요.
해결 과정
이 문제를 해결하려면 KATECH 좌표를 WGS84 좌표로 변환해야 했습니다. 처음에는 직접 변환 공식을 찾아서 구현하려고 했지만, KATECH에서 WGS84로 변환하는 공식이 꽤 복잡하더라고요. 그래서 좌표 변환을 쉽게 처리할 수 있는 proj4dart 패키지를 사용하기로 했습니다.
먼저 pubspec.yaml에 proj4dart 패키지를 추가했습니다.
dependencies:
proj4dart: ^2.1.0
그 다음, KATECH와 WGS84 좌표계 정의를 proj4dart로 설정하고 변환 로직을 작성했습니다. 네이버 API의 KATECH 좌표를 WGS84로 변환하는 코드는 다음과 같습니다.
import 'package:proj4dart/proj4dart.dart' as proj4;
void convertKatechToWgs84(Place place) {
// KATECH 좌표계 정의 (EPSG:5178)
final katech = proj4.Projection.parse('+proj=tmerc +lat_0=38 +lon_0=128 +k=0.9999 +x_0=400000 +y_0=600000 +ellps=bessel +units=m +no_defs');
// WGS84 좌표계 정의 (EPSG:4326)
final wgs84 = proj4.Projection.parse('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs');
// KATECH 좌표 (mapx, mapy)
final katechPoint = proj4.Point(x: place.mapx.toDouble(), y: place.mapy.toDouble());
// KATECH -> WGS84 변환
final wgs84Point = proj4.ProjectionTuple(fromProj: katech, toProj: wgs84).forward(katechPoint);
place.lat = wgs84Point.y;
place.lon = wgs84Point.x;
}
마무리
이번 프로젝트를 통해 Flutter 앱 개발에서 실기기 테스트와 데이터 처리의 중요성을 다시 한번 깨달았습니다. 특히 외부 API를 사용할 때는 예상치 못한 데이터 형식이나 좌표계 차이를 처리할 준비가 필요하다는 점을 배웠어요. 이 글이 다른 개발자들에게도 도움이 되었으면 좋겠습니다! 혹시 비슷한 문제를 겪은 경험이 있다면 댓글로 공유해주세요. 😊
'Mystudy' 카테고리의 다른 글
| Flutter TMDB 영화 앱 개발기 트러블 슈팅은 어려워.. (1) | 2025.05.15 |
|---|---|
| [Flutter] 기차 예매 앱 개발 중 만난 문제와 해결법 (0) | 2025.04.02 |
| Dart 콘솔 RPG - 트러블 슈팅 정리 (0) | 2025.03.21 |
| Dart 콘솔에서 한글 인식 문제 - 트러블슈팅 (0) | 2025.03.14 |
| 플러터 위젯 트리란 무엇인가? (0) | 2025.03.04 |