Flutter (앱 개발)/Flutter 트랙

[Flutter 숙련 TIL ] 책검색 앱 만들기 Part 02 :: OpenAPI 연동하기

Ize𓆜 2025. 4. 17. 17:18
728x90
728x90

 


Ⅰ. ✨ 시작하며

 

처음 해보는 Open API 연동, 막막함에서 출발

 

 

책 검색 앱을 만드는 이번 실습은

단순한 UI 구현을 넘어서

실제 외부 API를 활용한

데이터 연동까지 포함되었습니다.

 

처음에는 Client ID,

Secret, 그리고 헤더 설정 같은

개념이 낯설게 느껴졌고,

Thunder Client 같은 도구도

처음 접하다 보니 시행착오가 많았어요.



하지만 그 과정에서

 ‘실제 API 연동이

이렇게 작동하는구나’를

몸소 익히는 값진 시간이었습니다.


구조를 이해하니 머릿속이 정리되기 시작했다

 

API로 받은 데이터를

 Model로 변환하고 

Repository → ViewModel → View로 

흐름을 쪼개기 시작하면서

 Flutter MVVM 구조의 

강점을 다시 한 번 체감했습니다. 

 

특히 테스트를 통해

 API 응답 구조가 깨지는 경우까지

 대비할 수 있어 큰 도움이 되었어요.


Ⅱ. 🔍 본론 – 실습 요약 및 구성

 

Open API란?

 

[Thunder Client] Flutter REST API 테스트 도구 추천! VS Code 확장 Thunder Client 사용법과 후기

 

[Thunder Client] Flutter REST API 테스트 도구 추천! VS Code 확장 Thunder Client 사용법과 후기

목차 Ⅰ. 이 프로그램이 무엇인지 📌 1. Thunder Client란? 📌 2. Thunder Client의 탄생 배경 Ⅱ. 어떻게 활용할 수 있을까? 📌 1. Flutter API 연동 전 기능 점검 📌 2. 컬렉션으로 프로젝트별 API 정리 📌 3.

grmeems.tistory.com

 

  • OpenAPI는 외부 개발자에게 공개된 API로, 특정 서비스 기능을 사용할 수 있도록 정의된 인터페이스입니다.
  • 이번 실습에서는 네이버 책 검색 API를 활용하여 검색어를 통해 책 정보를 받아옵니다.

 


NAVER Developers에서 API 등록하기




Thunder Client로 API 테스트하기

 

  • VSCode 확장 프로그램인 Thunder Client를 설치
  • 요청 URL, 헤더(Client ID/Secret) 설정 후 테스트
  • 정상 응답을 받으면 JSON 데이터 확인 가능

 


Flutter 프로젝트에서 구현

 

UI와 UX는 밀접한 관련이 있지만, **각각 다른 역할을 수행하는 개념**입니다.

lib/
├── data/
│   ├── model/
│   │   └── book.dart
│   └── repository/
│       └── book_repository.dart
├── ui/
│   └── pages/
│       ├── home/
│       │   ├── home_page.dart
│       │   ├── home_view_model.dart
│       │   └── widgets/
│       │       └── home_bottom_sheet.dart
│       └── detail/
│           ├── detail_page.dart
├── main.dart

Model 클래스 생성

class Book {
  final String title, link, image, author, discount, publisher, pubdate, isbn, description;
  Book({ required this.title, required this.link, required this.image, required this.author, required this.discount, required this.publisher, required this.pubdate, required this.isbn, required this.description });
  Book.fromJson(Map<String, dynamic> json)
      : this(
          title: json["title"],
          link: json["link"],
          image: json["image"],
          author: json["author"],
          discount: json["discount"],
          publisher: json["publisher"],
          pubdate: json["pubdate"],
          isbn: json["isbn"],
          description: json["description"],
        );
  Map<String, dynamic> toJson() => { ... };
}

Repository 구현

class BookRepository {
  Future<List<Book>?> search(String query) async {
    try {
      final response = await get(
        Uri.parse('https://openapi.naver.com/v1/search/book.json?query=$query'),
        headers: {
          'X-Naver-Client-Id': '발급받은 Client ID',
          'X-Naver-Client-Secret': '발급받은 Secret',
        },
      );
      if (response.statusCode == 200) {
        final json = jsonDecode(response.body);
        return List.from(json['items']).map((e) => Book.fromJson(e)).toList();
      }
    } catch (e) {
      print(e);
    }
    return null;
  }
}

7. ViewModel과 View 연결

  • Riverpod을 통해 상태관리
  • Notifier<HomeState>를 통해 상태 초기화 및 데이터 업데이트 구현
  • HomePageConsumerStatefulWidget으로 변경하여 상태 감지 및 UI 갱신

8. BottomSheet + WebView 연결

  • Book 아이템을 누르면 HomeBottomSheet 표시 → ‘자세히 보기’ 클릭 시 DetailPage로 이동
  • DetailPage에서 flutter_inappwebview로 외부 링크 열기 구현 완료
 

Ⅲ. 📦 정리하며 – 시행착오 & 깨달음

실전 연동에서 발생한 실수들

 

  • Client ID/Secret을 공개 저장소에 올릴 뻔했던 실수
  • GET 요청 시 쿼리 파라미터 잘못 입력하여 응답 오류 발생
  • 초기엔 thunder client 없이 브라우저에서만 테스트하려다 헤더 미설정으로 실패


실전처럼 구성해보니 자신감 상승

 

  • 단순한 토이 프로젝트가 아닌 실제 외부 API 호출부터 MVVM 구조까지 경험하며 개발의 뼈대를 익혔습니다.
  • 각 계층을 나눠서 코드를 작성하니 추후에 리팩토링이나 테스트도 훨씬 수월할 것 같다는 느낌을 받았습니다.

 

728x90
728x90