[flutter] 주소검색 API 사용

JunKim.dev·2023년 2월 1일
0

Flutter

목록 보기
1/5
post-thumbnail

0. 카카오 API

디자인 적으로나 개발 난이도 혹은 호환성에서 가장 맘에 드는 주소검색 api‼️
사용량에 대한 제한이 없고, 따로 키를 발급받을 필요가 없기에 유용하다.

기본 가이드는 다음 링크를 참고해주세요
Daum Postcode Service User Guide

1. pub.dev

Flutter 용 패키지로는 kopo 라는 이름으로 개발된 패키지가 있지만, 최근에 출시된 포크 버전 remedi-kopo 패키지를 사용해보았다.

1-1. 패키지 설치

터미널 창에서 아래 명령어를 실행한다.

$ flutter pub add remedi_kopo

or
pubspec.yaml 파일 dependencies 에 추가해준다.
(이후 터미널에서 flutter pub get 명령어 실행 추천)

dependencies:
  remedi_kopo: ^0.0.2

1-2. 패키지 import

사용하고자 하는 페이지에서 import

import 'package:remedi_kopo/remedi_kopo.dart';

1-3. 사용하기

버튼을 생성해주고, onTap 에서 아래 코드를 실행한다.

onTap: () async {
  KopoModel model = await Navigator.push(
    context,
    CupertinoPageRoute(
      builder: (context) => RemediKopo(),
    ),
  );

  logger.i(
    '${model.zonecode} / ${model.address} / ${model.buildingName}',
  );
  // => 13529 / 경기 성남시 분당구 판교역로 166 / 카카오 판교 아지트
},

1-4. 에러방지

구현해보고 실행해보면 알겠지만, 창을 띄운 상태에서 검색하지 않고 그대로 뒤로 가면 model 의 값이 Nullreturn 이 된다. 아래 코드처럼 방지해주자.

KopoModel? model = await Navigator.push(
  context,
  CupertinoPageRoute(
    builder: (context) => RemediKopo(),
  ),
);

if (model != null) {
  /// model 처리
}

2. 활용하기

가장 많이 사용될 듯한 TextFormField 에 적용시켜보자!

2-1. form state 생성

/// Form State
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Map<String, String> formData = {};

2-2. controller 생성

/// Controller
final TextEditingController _postcodeController = TextEditingController();
final TextEditingController _addressController = TextEditingController();
final TextEditingController _addressDetailController = TextEditingController();

2-3. _searchAddress 생성

void _searchAddress(BuildContext context) async {
  KopoModel? model = await Navigator.push(
    context,
    CupertinoPageRoute(
      builder: (context) => RemediKopo(),
    ),
  );

  if (model != null) {
    final postcode = model.zonecode ?? '';
    _postcodeController.value = TextEditingValue(
      text: postcode,
    );
    formData['postcode'] = postcode;

    final address = model.address ?? '';
    _addressController.value = TextEditingValue(
      text: address,
    );
    formData['address'] = address;

    final buildingName = model.buildingName ?? '';
    _addressDetailController.value = TextEditingValue(
      text: buildingName,
    );
    formData['address_detail'] = buildingName;
  }
}

2-4. Form 생성

우편번호와 기본주소 항목은 readOnly 로 수정을 못하도록 처리

Form(
  key: _formKey,
  child: Column(
    children: <Widget>[
      TextFormField(
        controller: _postcodeController,
        decoration: const InputDecoration(
          hintText: '우편번호',
        ),
        readOnly: true,
      ),
      TextFormField(
        controller: _addressController,
        decoration: const InputDecoration(
          hintText: '기본주소',
        ),
        readOnly: true,
      ),
      TextFormField(
        textInputAction: TextInputAction.done,
        controller: _addressDetailController,
        decoration: const InputDecoration(
          hintText: '상세주소 입력',
        ),
      ),
      CupertinoButton(
        onPressed: () => _searchAddress(context),
        child: const Text('주소검색'),
      )
    ],
  ),
),

전체 소스코드
GitHub

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:remedi_kopo/remedi_kopo.dart';

class KakaoAddressScreen extends StatelessWidget {
  KakaoAddressScreen({super.key});

  /// Form State
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  Map<String, String> formData = {};

  /// Controller
  final TextEditingController _postcodeController = TextEditingController();
  final TextEditingController _addressController = TextEditingController();
  final TextEditingController _addressDetailController =
      TextEditingController();

  Widget _gap() {
    return const SizedBox(
      height: 10,
    );
  }

  void _searchAddress(BuildContext context) async {
    KopoModel? model = await Navigator.push(
      context,
      CupertinoPageRoute(
        builder: (context) => RemediKopo(),
      ),
    );

    if (model != null) {
      final postcode = model.zonecode ?? '';
      _postcodeController.value = TextEditingValue(
        text: postcode,
      );
      formData['postcode'] = postcode;

      final address = model.address ?? '';
      _addressController.value = TextEditingValue(
        text: address,
      );
      formData['address'] = address;

      final buildingName = model.buildingName ?? '';
      _addressDetailController.value = TextEditingValue(
        text: buildingName,
      );
      formData['address_detail'] = buildingName;
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Kakao 주소검색 API'),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Form(
              key: _formKey,
              child: Column(
                children: <Widget>[
                  TextFormField(
                    controller: _postcodeController,
                    decoration: const InputDecoration(
                      hintText: '우편번호',
                    ),
                    readOnly: true,
                  ),
                  _gap(),
                  TextFormField(
                    controller: _addressController,
                    decoration: const InputDecoration(
                      hintText: '기본주소',
                    ),
                    readOnly: true,
                  ),
                  _gap(),
                  TextFormField(
                    textInputAction: TextInputAction.done,
                    controller: _addressDetailController,
                    decoration: const InputDecoration(
                      hintText: '상세주소 입력',
                    ),
                  ),
                  _gap(),
                  CupertinoButton(
                    onPressed: () => _searchAddress(context),
                    child: const Text('주소검색'),
                  )
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

실행결과

profile
아는 코드도 다시보자 🫠

0개의 댓글