본문 바로가기
코딩생초보를 위한 플러터 빠르게 한바퀴

6.network

by 타이싸란 2023. 8. 22.

6회차 세부 과정 목차

이번시간에 공부할 내용은 네트워크통신이라는 아주 중요한 개념입니다.

 

우리가 앱을 구성하면서 , 사용하는 데이터나 이미지 등등은 앱내부 assets에서 꺼내 보여주는것도 있지만, 대부분 백엔드에 데이터를 요청하고 받아서 그 데이터를 가공하여 화면에 보여줍니다.

예를들어 쿠팡같은 쇼핑몰 앱보면 수많은 상품들이 있는데 그 내용을 앱에서 보관하고있을수도 없고, 보관하고있는다 해도 데이터에 계속 변화가 일어나기때문에 백엔드 서버와 통신을 해야합니다.

 

상품 "청소" 가 들어간 상품 100개 데이터 요청 ->

백엔드에서 데이터베이스에서 조건에 맞는거 100개 찾고, 그외 필요한 데이터 합쳐서 프론트로 Json 데이터로 보내줌 ->

프론트에서는 Json 데이터를 받아서 객체화 시키고 화면에 보여줌.

 

뭐 이런식인겁니다.

요청할때는 get , post , patch 방식등등을 정해서 보내준다거나

http 요청의 규칙이나 , 구성요소등, 아주 중요한 개념이긴 하지만, 개념부터 완벽히 익히고 하는게 아닌 상황에 닥쳐가며 그때그때 공부하는 것으로 하겠습니다.

 

그럼 새로운 프로젝트를 생성하고 강의를 따라할준비를 해주세요~

 

1.Http

목차로돌아가기

 

Flutter 에서는 외부통신을 할때 http 라이브러리를 사용합니다.

http 라이브러리를 pubspec.yaml 에 넣은뒤 Pub get 등등 라이브러리 사용할때 할일들을 해주세요.

 

http 통신으로 백엔드에서 데이터를 받아올건데 , 우리는 백엔드가 없잖아요? 그래서 누군가 착한 사람이 만들어놓고 백엔드 없는사람이 통신 연습할때 써라고 만들어놓은 백엔드 서버를 사용할것입니다.

백엔드 서버라고 하지만 api 통신을 위한 서버라서 api 서버 라고 합니다.

https://dummyjson.com

 

DummyJSON - Fake REST API of JSON data for development

Got tired of Lorem ipsum data? With DummyJSON, what you get is different types of REST Endpoints filled with JSON data which you can use in developing the frontend with your favorite framework and library without worrying about writing a backend.

dummyjson.com

dummyjson 이라는곳을 이용해 볼것입니다.

 

우선 프로젝트를 만든뒤 MainPage를 만들고 코딩해보겠습니다.

http 라이브러리를 import 했는데요, as 별칭을 사용해서 http 라고 지어주세요.

 

getDummy 라는 함수를 하나 만들어 주었습니다.

 

final response = awit http.get(uri) 

이 부분이 비동기 함수이구요.

get(uri) 이부분에서 uri 를 적어줘야하는데 url이 아니라 uri 입니다.

우리가 아는 url 을 적어준뒤 uri 로 변경하면됩니다.

 

url = "https://dummyjson.com/products"

라고 적어주세요. 그리고 uri 로 변경해주세요.

이건 dummyjson 에서 제공하는 product 리스트를 json 으로 보내주는 api 입니다.

 

이렇게 호출했을때 내용들이 response 라고 명명한 변수에 들어오게됩니다.

response 를 까보면 여러가지 정보가 있는데, 우리가 필요한 알맹이정보는 body 라는곳에 있습니다.

그래서 어떤건지 보기위해 print(response.body) 로 콘솔에 찍어보니 json 데이터가 콘솔에 나오는걸 볼수있습니다.

 

근데 이렇게 보면 너무 힘들기때문에 flutter dev tools 를 이용해보도록 합시다.

 

우측 부분에 Flutter Performance 라는게 보일겁니다.

아래부분에 Open Devtools 라고 있습니다. 이걸눌러주세요.

 

그럼 이렇게 DevTools 가 브라우져 창에 나타납니다.

여기서 Network 탭에가보세요. 지금은 아무것도 없을것입니다.

 

이창을 켜두고 호출을 다시 눌러보면 이렇게 어떤 네트워크 통신이 일어났는지 볼수있습니다.

Response 탭에 와보면 어떤 데이터가 어떻게 와있는지 볼수있습니다.

 

 

2.api 로 받은 데이터 객체화

목차로돌아가기

 

http 통신으로 데이터를 받아왔으니, 이걸 실제로 화면에 한번 보여주는걸 해봐야될 것 같습니다.

우선 저 데이터를 객체화 시켜줘야하는데, 데이터를 보니 ProductModel 과 Product vo 를 만들어야 하는게 눈에보입니다.

저번에 Json 데이터를 다루어 봤으니, 그대로 하시면됩니다.

 

우선 Vo 부터 만들어주겠습니다.

vo 디렉터리를 만들고 Product class 를 생성해주었습니다.

response 가 어떻게 어떤 변수명으로 들어오는지 확인하고 만들어주세요.

 

여기서 특이한점은 images 가 List 형태로 들어오는데 , String 문자열 배열로 되어있습니다.

그렇기 때문에 fromJson 부분에 .cast<String> 을 사용해주었습니다.

 

또 rating 부분이 double 형태로 받는것이 맞지만, 이 api 경우 rating 을 4.5 ,4.66 이렇게도 주지만 4 이렇게 int 형태로 주는경우도있습니다. 그래서 타입에러가 나네요.. 백엔드 api 를 잘짰다면 4.0 이렇게 줘야하는데 아쉽네요.

그래서 우리는 rating 부분을 double 이 아닌 num 으로 받도록 해주세요.

 

그다음은 ProductModel을 만들었습니다.

total, skip ,limit 은 그냥 받으면되는데,

products 의 경우 Product로 구성된 리스트이기 때문에

우선 products = <Product>[]; 이렇게 빈배열을 하나 만들어둡니다. 그뒤에

json['products] 로 값을 받아온뒤 그걸 forEach 로 한개한개 돌면서 Product.fromJson 을 통해 객채를 만들어 두고,

아까 만들어둔 빈배열인 products에 add 를 통해 하나하나 담도록 해두었습니다.

 

그럼이제 모델을 모두 만들었으니 MainPage.dart 로 가주세요.

productModel 변수를 하나 생성해주었고,

 

getProductList 라는 함수를 만들어줬습니다. 

그리고 retrun 부분을 잘보시면 fromJson 을 통해 만들어진 ProductModel 을 리턴하게 해주었습니다.

Json 부분 공부할때 한것이니, 조금은 익숙할것입니다.

 

그리고 그냥 클릭버튼 하나 만들어서 getProductList 를 호출하였습니다. 그리고 productModel 이라고 위에서 정의한 변수에 할당한뒤 setState 해주었습니다.

그러니 원하는 값들이 화면에 표시되는게 보입니다.

 

이렇게 http요청을 성공하고, api 로 받은데이터를 객체화 시켜주었습니다.

 

받은데이터를 화면에 조금은 그럴듯하게 꾸며보면 이렇게 리스트뷰로 나타내줄수 있을겁니다.

 

3.뷰 , 데이터, 로직 분리 MVC 패턴

목차로돌아가기

 

우리가 짠 코드를 보면 , 뷰를 나타내는 부분과, api통신을 위한 로직이 한 다트파일에 모두 들어있습니다.

문제는 없지만, 보통 뷰와 로직부분을 분리 관리해야 유지보수가 편하기때문에 , 한번 분리해보도록 하겠습니다.

 

저같은 경우는 뷰,로직,데이터 이렇게 3개로 나누어 관리합니다.

 

이 예시에서 데이터는 productModel 부분 , 로직은 getProductList 부분입니다.

 

우선 로직부터 분리해보죠.

 

global 디렉터리를 만든뒤 안에 httpService 라고 만들어주었습니다.

 

그리고 그안에 아까 getProductList 함수를 집어 넣었습니다.

앞으로 http 통신과 관계된 메소드는 HttpService class 에 모두 넣을겁니다.

 

그다음은 데이터 차례네요.

 

getX로 상태관리 했을때처럼 controller 를 만듭니다. main.dart 가서 get.put 해주시구요.

 

HttpService인스턴스를 하나 만들었습니다.

 

productModel 이라는 변수 하나 만들었구요.

메소드도 만들었습니다.

메소드안에는 try catch 가 있는데

try 안에 로직을 적고 이안에서 어떠한이유에서든 에러가 나면 catch 로 가서 그안에 로직을 수행합니다.

 

뷰 부분에는 데이터나 네트워크 로직없이 그냥 뷰 부분만 코딩해주었습니다.

그리고 데이터 가져오는 부분도 controller.getProductList() 이렇게 컨트롤러를 이용하게 해주었습니다.

 

이렇게 코드를 분리하고 관리하는것이 일반적으로 하는방법인데요 , 우리가 그냥 이렇게 한것이 사람들이 많이 하는 패턴이라 이름도 거창하게 MVC 패턴이라고 불립니다.

 

구지 대략 그림으로 표현하면 이런거겠네요.

 

View 부분에서 Controller에 데이터요청 또는 메소드발동 ->

Controller 에서 Model을 받아오고 Service안에 로직을 거친뒤 Model을 업데이트 ->

Controller에서 View 부분으로 데이터 전달

 

 

이런식으로 개발이 이루어집니다.

따라하기만 해서 잘모르겠고 답답하고 직관적이지 않아도 , 그냥 이렇게 계속사용하다보면 당연하게 받아들여질테니 너무 걱정마시길 바래요.

 

4. shared preferences

목차로돌아가기

 

shared preferences 는 앱에서 사용할수있는 아주 심플한 데이터베이스 정도로 생각하시면됩니다. 웹으로 치면 로컬스토리지 정도?

 

일반적인 데이터베이스는 앱과 별개의 데이터베이스 서버에 데이터를 저장해두고, 필요할때마다 백엔드에서 api 요청 -> 백엔드에서 데이터베이스 서버에 접속하여 데이터 얻음 -> 프론트로전달 이렇게 되는데요

 

shared preferences  는 서버에 데이터 올리고 그런게 아니라, 모바일디바이스 내부에 우리가만든 앱의 저장소에다가 넣어두는겁니다.

 

getx를 이용한 상태관리로 데이터를 저장하면 , 앱 구동중에는 계속 사용되지만, 앱을끄면 데이터가 사라지는데,

shared preferences는 앱을꺼도 데이터가 그대로 유지됩니다. (근데 앱삭제하거나 새로깔면 기존 데이터 사라져요)

 

대충 이런느낌이라고 보면됩니다.

 

그래서 앱에서 저장해야할 데이터중에 사라지지 않아야 할 데이터지만 , 디비서버까지 필요없는 데이터의 경우 이걸많이 씁니다.

예를들어 로그인을 위한 아이디와 비번 같은거 저장해두는거요.  어떤앱을열면 로그인창에 아이디와 비번이 자동으로 들어가져있어서 로그인 버튼만 누르면 로그인될수있도록 만들어 놓은걸 볼수있을텐데, 이런걸 이용한거라 보심됩니다.

이걸 이용하면 자동로그인이나 뭐 등등 할수있겟죠.

 

다른예시로 앱 테마를 저장한다거나 , 뭐 나이트 모드 , 데이모드 가 있는데 마지막 앱끄기전 나이트모드로 저장한뒤에 앱을껐는데 , 그다음 켯을때 나이트모드로 처음 세팅되서 보인다거나 그런것들이죠.

 

일단 말은 많이 필요없고, 실전으로 해보면서 봅시다.

 

 

일단 라이브러리를 설치해주세요.

 

SharedPreferences 인스턴스를 만들어야하는데 , 여러곳에서 사용할것이기 때문에 , 그냥 글로변 파일 하나 만들어서 이렇게 만들어주세요. 일단 인스턴스를 생성하기전에 사용하기전에는 반드시 초기화된다는 의미로 late 를 써서 변수 정의만해주세요.

 

그다음 메인페이지로 가서 인스턴스를 만들면되는데

먼저 WidgetFlutterBinding.ensureInitialized() 요거를 main함수 맨위에 적어주세요.

 

그다음 인스턴스를 생성하는데 네모친것 처럼 getInstance를 이용해서 인스턴스를 만듭니다.

prefs 저 변수는 아까 글로벌에서 만든거 그거 import 해서 들고온겁니다.

 

그다음 getInt , setInt 등으로 값을 얻거나 등록하는데 .getInt('userAge) 이렇게 하면 만들어진 sharedPreferences 인스턴스에서 userAge 라고 명명한 곳에 저장되어 있는 값을 불러오는겁니다.

 

그런데 저 라이브러리를 써서 처음 앱을 구동하면 당연히 userAge 값은 없겠죠? 그래서 if 문 분기처리를 해서 있으면 가져오고 없으면 만들어라 라는 로직을 짜준겁니다.

 

값을 만들때는 .setInt('userAge',10) 이렇게 (변수명,값) 이렇게 넣어주면됩니다.

 

 

실제로 실행해보면 , 처음 실행할때는 위에처럼 나오고 , 두번째 실행하니까 아래처럼 나옵니다.

 

예시에서는 int 형태의 변수만 했는데 String ,bool , double , StringList 형태까지 총 5가지 타입으로 저장할수있습니다.

그리고 불러오기 , 세팅하기 만 해봤는데 삭제하기도 물론있습니다. 그건 공식 홈피가서 확인하면됩니다. 대충 그림첨부할테니 이거 참고하심됩니다.

 

 

지금 이시점에 이 preferences 를 하는이유는 오늘 있을 숙제를 위한 빌드업이니 , 어떻게 사용하는건지 잘 익혀뒀다가 숙제할때 써먹어보세요.

 

5.Logger

목차로돌아가기

 

우리가 어떤값을 콘솔에 찍어볼때 print 라는 flutter 에서 제공하는 내장함수를 이용했었는데요, 이건 그냥 간단히 확인해볼때 사용하긴하지만 실제로는 이거 사용하는걸 자제해야합니다.

 

이유는 뭐 별거없긴한데 , 저함수는 개발뿐만아니라 실제 배포되었을때도 저 함수가 실행되서 만약 저 print 함수를 안지우고 배포를 하면, 배포된 앱에서도 저 print 함수가 실행됩니다.

웹에서는 개발자 콘솔을 띄울수있기때문에 확인이 가능해서 치명적인 부분이 있긴한데 앱은 사실 사용자가 개발자 콘솔을 사용할일이 없을거라서 상관은 없지만 왠지 찝찝하잖아요?

 

그래서 log 라는걸 이용해서 콘솔에 찍어봅니다. 이거는 개발환경에서만 콘솔에 표시되는겁니다.

그런데 저 log 를 좀더 예쁘고 잘 알아볼수있도록 하는 라이브러리가 있는데 그게 Logger 라는 라이브러리입니다.

 

 

 

이런식으로 상황에 따라서 색상도 줘서 개발할때 좀더 로그를 눈에보기쉽게 볼수있도록 하는거에요.

그래서 앞으로 콘솔에 뭐 찍어볼일 있을때 print 대신에 logger 를 사용할겁니다.

( 사실 디버그 모드를 이용해서 하는게 젤좋긴한데 지금 디버그를 배우는건 힘드니까 걍 이걸로하겠습니다.)

 

 

일단 라이브러리를 설치해주세요.

 

그리고 Logger 인스턴스를 하나 만들어주면되는데 , 여러곳에서 사용할것이니 글로벌에다가 만들어줬습니다.

로거 설정을 좀 해줘야하는데 , 저는 그냥 간단하게만 보고싶어서 설정을 저렇게 했습니다. 나중에 설정들좀 바꿔보며 자기한테 맞는걸로 한번 세팅해보세요.

 

사용해보면 이렇게 모드에 맞춰 색상구분이되어 나오게됩니다.

 

t,d,i,w,e,f 6가지가 있네요. 그냥 아무거나 사용하면됩니다.

i를 사용하면 파란색으로 나오는데 , 저걸 노란색으로 바꾸고싶다? 그건안됩니다.

근데 안드로이드에서는 저렇게 색상이 나오는데 IOS에서는 안나오더라구요.. 방법을 알아내야할텐데 .. 어쨋든 그렇습니다.

 

6.Drawer

목차로돌아가기

 

drawer 는 앱의 가장자리에서 서랍처럼 열리는 위젯입니다.

 

그림처럼 햄버거 버튼 누르면 저렇게 나오는거를 말합니다. 사이드바? 정도일까요

 

어쨋든 이걸 구현하려면 손가락의 슬라이드 제스처 라던지 그런걸 구현해야되는데, 좀 복잡하니까

flutter 에서 내장위젯으로 만들어 둔게 있습니다. 그게 Drawer 이라는 위젯입니다.

 

Scaffold 의 옵션으로 그냥 drawer 을 주면됩니다.

저는 MainPage.dart 파일에서의 Scaffold에 drawer 옵션에 Drawer() 위젯을 넣었습니다.

그러니 아무것도없는 빈 Drawer이 나타나게 됩니다.

이제 이걸 꾸며주기만 하면 되겠죠?

 

저는 대충 이렇게 꾸며줘봤습니다.

ListView로 안에 Drawer 안에 들어갈 내용들을 집어넣어줬습니다.

 

DrawerHeader 라고 drawer 의 헤더부분에서 주로사람들이 많이 사용하는 방식을 적용한 위젯이 있긴한데 , 그냥 커스텀으로 알아서 만들면됩니다.

ListTile 도 ListView 에서 사용하긴하는데 , 그냥 사람들이 많이 사용하는 방식을 위젯화시켜놓은거라 그냥 커스텀으로 꾸며도 됩니다.

 

 

7. Homework - TMDB api 를 이용한 영화소개 앱 만들기

목차로돌아가기

 

아까는 dummyJson 이라는 api 를 이용해서 실습을 해보았는데요,

이번엔 TMDM api 를 이용해서 영화소개앱을 만드는걸 숙제로 해볼겁니다.

https://www.themoviedb.org/?language=ko 

 

The Movie Database (TMDB)

Welcome. Millions of movies, TV shows and people to discover. Explore now.

www.themoviedb.org

 

대충 이런걸 만들어 볼텐데요 , 숙제로 해보시고 좀 비효율적이거나 한거는 수정하고 , 더하고싶은건 더해서 해보세요.

 

 

 

이걸 만들기 위해 몇가지 알려드릴게요.

먼저 위에 링크를 타고 TMDB 사이트로 가주세요.

회원가입은 간단하니, 먼저 회원가입부터 해주세요.

 

1. api key 발급

 

보통 외부 api 를 사용할때는 에세스토큰이라던지 어떤 특정사용자 즉 누가사용하는지 키값을 넣어줘야하는등 몇가지 규칙이 있습니다.

 

more 에 API를 눌러서 들어가주세요.

 

Developer 를 눌러준뒤, 약관에 동의해주세요.

 

 

여기 빈칸에 적절하게 넣어주세요.

이름에 대충 아무거나 넣고, 어플리케이션URL은 그냥 본인 홈피 URL 넣고,

어플리케이션 개요에 뭐 적절히 몇십자 적고 하면됩니다.

 

  

제가 어떻게 적었는지 기록을 보니 대충 이렇게 적었었네요.

 

내정보에 설정을 눌러 api 부분의 overview 를 보시면

 

api 키와 , api 읽기 엑세스 토큰이 발급되어 있는것을 볼수있습니다.

저위에 api 키는 발급은 되어있는데 실제로는 이거는 어디쓰는지 모르겠네요.

 

중요한건 api 읽기 엑세스 토큰 인데 이걸 잘 보관해둡니다.

 

 

무비 리스트 불러오는 부분을 한번 살펴보겠습니다.

 

more 에 API 를 누르면 이렇게 api에 관한 페이지가 나오는데 API Reference에 Movie 쪽으로 와서 Now Playing 쪽으로 와줍니다.

 

그러면 현재 플레잉중인 영화리스트를 보여주는 api 에 대한 내용이 나와있습니다.

맨위에 보시면 url 주소가 있고 , 쿼리파람스라고 해서 쿼리에 어떤 변수를 넣을수있는지도 나와있습니다.

이 api 는 방식이 get 이고, 변수는 쿼리파람스 형태로 받는다라고 되어있네요.

 

그리고 우측에보시면 바로 api 를 날려볼수있도록 제공도해주네요. 한번 try해보시길 바랍니다.

우측에 Shell, nodeJs 등등 프로그래밍언어들이 있는데 , 아무거나 선택해주면됩니다. 이거는 어떤 환경에서든 부를수있는 api 이기 때문에 각자의 언어에 맞춰 저렇게 예시로 짜면 된다라는걸 보여주고있습니다.

그런데 dart 언어는 없어서 그냥 nodeJs 를 선택해서 봤습니다.

 

그러니 특이한부분은 header 부분이 있습니다.

 

어쨋든 이런식으로 api 콜이되고 아래 결과가 나오는걸 볼수있습니다.

 

dart 언어가 없다고 해서 못하는게 아니라, 여기서 우리가 알아가야할것은 4가지입니다.

 

1.url 주소 = https://api.themoviedb.org/3/movie/now_playing

2.메소드 종류 = get

3.파라메터 방식 = url 파라메터

4.헤더 = accep , Authorization

 

이 4가지만 있으면 자바스크립트로 하든 자바로하든 파이썬으로 하든 다트로 하든 다 할 수있습니다.

 

 

우리 다트에서는 어떻게 했는지 볼까요?

 

 

1. url 주소를 넣어줬구요,

2.get 방식이라 http.get 했습니다.

3.파라메터는 몇가지 넣어줄수있는데 아무것도 안넣어줬습니다. 아무것도안넣어줬으니 기본값으로 나오겠네요.

4. header 를 맵으로 만들어서 넣어줬습니다.

 

이렇게 호출하고 dev tools 로 호출상황을 보니 잘나오네요.

 

url 파라메터는 어떻게 넣냐고요?

 

이렇게 넣습니다. 이걸 쿼리스트링 이라고합니다.

쿼리스트링의 각 키-벨류 사이에 & 이거 넣어주는걸 잊지마세요.

 

language = ko-KR 로 바꾸니 설명이 한글로된 결과로 호출되는걸 볼수있습니다.

 

accessCode는 다른 api 요청에도 쓰일꺼니까 global 이나 다른 중요한거 모아둔 파일에 정의해두고 이렇게 불러와서 사용하면되고,

language 나 page는 하나의 변수니까 이렇게 함수요청할때 매개변수로 받아서 사용하면 되겠네요.

 

ko-KR 을 넣으면 한국 나오는지 어떻게알았냐구요?

원래 api 호출하는 곳에서 설명을 해줘야하는데 설명이 잘 나와있지는 않아서 감으로 했습니다.

여기 어떤것들이 들어가는지는 나오는데 어떻값을 넣어야 되는지는 잘안나와있네요. 이부분이 좀 이 api 사용에 불편한 점이긴합니다.

 

어쨋든 이까지 했으면 과제를 할수는 있을겁니다.

이번 과제를 통해서 ui 꾸미기와 지금까지 한것들에 대해 익숙해지는 시간이 되시길 바랍니다.

 

'코딩생초보를 위한 플러터 빠르게 한바퀴' 카테고리의 다른 글

8.firebase2-auth,storage  (0) 2023.10.21
7.firebase1-firestore  (0) 2023.09.02
5.state management  (0) 2023.08.11
4.Json  (0) 2023.08.09
3.component  (0) 2023.08.03