2024. 11. 5. 19:48ㆍflutter
Flutter 9주차 - 카카오 API를 이용해 도서 정보 가져오기
이번 주차에서는 카카오 API를 이용해 도서 정보를 가져오는 실습을 진행할 예정이다.
주요 기능은 다음과 같다.
- 입력 : 사용자가 원하는 검색어를 입력할 수 있는 TextField 제공.
- 스크롤 감지 : 사용자가 리스트를 아래로 스크롤 할 때 데이터 로드.
- API 호출 : 카카오의 도서 정보 API로 데이터를 가져옴.
- 결과 표시 : 가져온 데이터를 리스트 형태로 표시.
목차
http 패키지 가져오기
먼저 HTTP 통신을 통해 카카오 API에 요청할 예정이므로 HTTP 패키지가 필요하다.
pub.dev 로 이동하여 패키지 설치를 진행하자.
예시대로 dependencies에 http 패키지를 추가한 후, 우측 상단에 Pub get를 눌러 패키지를 설치하자.
카카오에서 API 키 얻기
카카오 API를 사용하기 위해선 API키가 필요한데, 키를 얻기 위해선 카카오 개발자 사이트에 로그인하고 애플리케이션을 추가해줘야 한다.
https://developers.kakao.com 에 접속하면 아래와 같은 화면이 나올 것이다.
먼저 우측 상단 로그인을 클릭해서 로그인하자. 로그인은 본인의 카카오 아이디로 진행하면 된다.
로그인이 완료되면 상단의 '내 애플리케이션'을 클릭하자.
'애플리케이션 추가하기'를 눌러 테스트용 애플리케이션을 추가해보자.
앱 이름은 'httpBook'
회사명은 본인의 학교 이름 혹은 일단 아무거나 적어도 괜찮다. (실제로 서비스에 사용하지는 않으므로)
카테고리는 API를 사용하려는 애플리케이션의 카테고리를 선택하면 되는데 일단 교육으로 선택했다.
애플리케이션이 추가되고 나면, 방금 만든 httpBook을 클릭하여 들어가보자.
좌측 메뉴에서 '앱 키'를 선택하고 'REST API 키' 를 잘 복사하여 저장해놓자. 도서 정보 API를 사용하기 위해선 이 키가 필요하다.
앱 키는 각 애플리케이션마다 고유한 값을 가지므로 절대 유출되지 않도록 보안에 신경써서 보관해야 한다.
만약 앱 키가 유출되었으면 재발급해야 한다.
카카오 도서 정보 API 사용법 확인하기
https://developers.kakao.com/docs/latest/ko/daum-search/dev-guide#search-book
위 문서에 들어가보면 책 검색 API의 기본 정보를 확인할 수 있다.
여기서 우리가 사용할 응답값은 title(도서 제목), contents(도서 소개), url(도서 상세 url), authors(도서 저자 리스트), price(도서 정가), sale_price(도서 판매가), thumbnail(도서 표지 미리보기 URL), status(도서 판매 상태 정보) 이다.
조금 더 내려보면 해당 응답값들이 실제로 어떻게 오는지 예시를 확인할 수 있다.
코드 작성하기
import 'package:flutter/material.dart'; // Flutter의 Material 디자인 라이브러리
import 'package:flutter_202316035/http/test.dart';
import 'package:http/http.dart' as http; // HTTP 요청을 위한 라이브러리
import 'dart:convert'; // JSON 변환을 위한 라이브러리
// 앱의 진입점
void main() {
runApp(MyApp()); // MyApp 위젯 실행
}
// MyApp 클래스는 애플리케이션의 루트 위젯을 정의
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
// MaterialApp을 사용하여 앱의 구조를 설정
return const MaterialApp(
home: HttpApp(), // HttpApp을 홈 화면으로 설정
);
}
}
// HttpApp 클래스는 StatefulWidget으로 상태를 관리
class HttpApp extends StatefulWidget {
const HttpApp({super.key});
@override
State<HttpApp> createState() => _HttpAppState(); // 상태 객체 생성
}
// _HttpApp 클래스는 HttpApp의 상태를 정의
class _HttpAppState extends State<HttpApp> {
List<dynamic>? data; // API에서 가져온 데이터를 저장할 리스트
TextEditingController _editingController = TextEditingController(); // 검색어 입력을 위한 컨트롤러
ScrollController _scrollController = ScrollController(); // 스크롤 이벤트를 처리하기 위한 컨트롤러
int page = 1; // 현재 페이지 번호
@override
void initState() {
super.initState();
data = []; // 데이터 리스트 초기화
// 스크롤 리스너 추가: 스크롤이 끝에 도달하면 다음 페이지 데이터 요청
_scrollController.addListener(() {
if (_scrollController.offset >= _scrollController.position.maxScrollExtent && !_scrollController.position.outOfRange) {
page++; // 페이지 번호 증가
getJSONData(); // 다음 페이지 데이터 요청
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// AppBar에 검색 입력 필드를 추가
title: TextField(
controller: _editingController, // 입력 컨트롤러 설정
style: const TextStyle(color: Colors.blue), // 텍스트 색상 설정
decoration: const InputDecoration(hintText: "검색어를 입력하세요."), // 힌트 텍스트
),
),
body: Container(
padding: const EdgeInsets.all(16.0), // 컨테이너에 패딩 추가
child: Center(
child: data!.isEmpty // 데이터가 없을 경우
? const Text(
'데이터가 없습니다.', // 데이터가 없다는 메시지
style: TextStyle(fontSize: 20),
textAlign: TextAlign.center,
)
: ListView.builder(
itemCount: data!.length, // 데이터 개수
itemBuilder: (context, index) {
// ListView.builder를 사용하여 데이터 리스트 생성
return Card(
child: Row(
children: <Widget>[
// 책의 썸네일 이미지를 표시
Image.network(
data![index]['thumbnail'],
height: 100,
width: 100,
fit: BoxFit.contain,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, // 좌측 정렬
children: <Widget>[
// 책 제목
Text(data![index]['title'].toString(),
textAlign: TextAlign.center),
// 저자, 가격, 판매 상태 표시
Text('저자: ${data![index]['authors'].toString()}'),
Text('가격: ${data![index]['sale_price'].toString()}'),
Text('판매중: ${data![index]['status'].toString()}'),
],
))
],
),
);
},
controller: _scrollController, // 스크롤 컨트롤러 설정
)
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// FAB 클릭 시 페이지 초기화 및 데이터 새로고침
page = 1; // 페이지 번호 초기화
data!.clear(); // 데이터 리스트 초기화
getJSONData(); // 새로운 데이터 요청
},
child: const Icon(Icons.file_download), // 다운로드 아이콘
),
);
}
// JSON 데이터를 가져오는 비동기 함수
Future<void> getJSONData() async {
// Kakao API에서 데이터 요청
var url = 'https://dapi.kakao.com/v3/search/book?target=title&page=$page&query=${Uri.encodeQueryComponent(_editingController.text)}';
try {
// HTTP GET 요청
var response = await http.get(Uri.parse(url),
headers: {'Authorization': "KakaoAK 44144042718c0c1a63399dbc8e0e08cd"});
// 응답 상태 코드가 200일 경우
if (response.statusCode == 200) {
setState(() {
var dataConvertedToJSON = json.decode(response.body); // JSON 변환
List<dynamic> result = dataConvertedToJSON['documents']; // 책 데이터
data!.addAll(result); // 기존 테이터에 추가
});
} else {
throw Exception('Failed to load data'); // 오류 처리
}
} catch (e) {
print('Error: $e'); // 오류 메시지 출력
}
}
}
실행한 결과는 아래와 같다.
검색어를 입력하고 다운로드 아이콘을 클릭하면 검색어가 포함된 책들의 정보를 불러오게 된다.
리스트를 아래로 스크롤하면 추가 정보를 가져오게 된다.
'flutter' 카테고리의 다른 글
Flutter 중간시험 - 계산기 프로젝트 (0) | 2024.10.23 |
---|---|
Flutter 7주차 (3) - 아이콘과 아이콘 버튼 활용하기 (1) | 2024.10.16 |
Flutter 7주차 (2) - http 패키지 이용하기 (1) | 2024.10.16 |
Flutter 7주차 (1) - 애셋 활용하기 (1) | 2024.10.16 |
Flutter 5주차 - Dart언어의 함수 (0) | 2024.10.06 |