react-native와 Rest API 통신하기

What is Rest API ?

Representational State Transfer API 의 약자로, 자원을 이름으로 구분하여 자원의 상태(정보)를 주고 받는 모든 것을 의미한다.

다시 한 번 정리하자면, HTTP URI 를 통해 자원을 명시하고 HTTP Method(POST, GET, PUT, DELETE)를 통해 해당 자원에 대한 CRUD Operation을 적용하는 것을 의미한다.

Rest API는 자원과 행위, 표현으로 구성되어 있다.

  1. 자원: URI
    자원을 구별하는 ID는 '/groups/group_id'와 같은 HTTP URI이다.
    리소스명은 동사보다는 명사를 사용
  1. 행위: HTTP Method
    GET, POST, PUT, DELETE로 CRUD를 구현한다.
    ex) GET /members/1
  1. 표현
    Client가 자원의 상태(정보)에 대한 조작을 요청하면 Server는 이에 적절한 응답을 보낸다.
    REST에서 하나의 자원은 JSON, XML, TEXT, RSS 등 여러 형태로 나타내어 질 수 있다.

참고 (감사합니다 🙏)
https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html
https://meetup.toast.com/posts/92

React-native으로 기본 화면 구성 만들기

figma로 간단하게 프로토타입을 만든 후, 주요 기능 구현을 위한 화면 두 개를 만들었다. (navigate만 가능한 정도)

REST API 연동 전 사전 준비

이제 본격적으로 api 호출을 위해 axios 라는 라이브러리를 설치한다.
(yarn 대신 npm 으로 install 했고, 프로젝트 파일에서 설치해야 함)

$ npm install axios

설치가 다 끝났다면 app.js에 axios를 import 해온다.

import axios from 'axios';

그리고 useState 와 useEffect라는 리액트 함수를 사용하기 위해 import를 해온다.

import React, { useState, useEffect } from 'react';

배포된 서버에서 전달된 URI 구조 살펴보기

서버에서 전달해준 URI의 구조를 먼저 확인해본다. 내가 사용한 URI는 다음과 같은 구조로 구성되어 있다.

{"data":[
	{
    "id":1,
    "title":"기사제목",
    "writer":"기자",
    "date":"작성일",
    "company":"언론사",
    "img":"기사사진",
    "article_origin":["기사원문"],
    "article_extractive":["추출요약"],
    "article_hashtag":"해시태그",
    "category":"카테고리"
    }, ...
]}

위에서 다룬 useState를 이용해, 통신 과정에서 필요한 변수들을 정의한다.

const [news, setNews] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);

news - uri 내 뉴스 데이터를 가지고 있는 변수
loading - 통신 Loading 상태를 알 수 있는 변수
error - 로딩 과정에서 에러가 발생했을 경우 에러 내용을 담을 변수

uri에서 데이터를 불러온 후 news 변수에 넣어주는 코드

const fetchNews = async () => {
  try {
    // 요청이 시작 할 때에는 error 와 users 를 초기화하고
    setError(null);
    setNews(null);
      
    // loading 상태를 true 로 바꿉니다.
    setLoading(true);
      
    const response = await axios.get(
      'http://uri_주소'
    );
      
    // 데이터는 response.data.data 안에 들어있다.
    setNews(response.data.data);
  } catch (e) {
    setError(e);
  }
  // loading 끄기
  setLoading(false);
};

// 첫 렌더링 때 fetchNews() 한 번 실행
useEffect(() => {
	fetchNews();
}, []);
  • 에러 발생 주의: 내가 참고한 예시에서의 Uri 내부 구조와 내가 사용한 uri 내부 구조가 달라서 데이터 내용을 news 변수에 저장할 때 .data를 한 번 더 추가했다. (참고한 예시에서는 response.data 로 작성됨) uri 구조를 먼저 꼼꼼하게 살펴본 후에 로딩 하는 게 좋을듯..
if (loading) return <View style={{margin: 50, width: 300, height: 200}}><Text>로딩 중..</Text></View>;
if (error) return <View style={{margin: 50, width: 300, height: 200}}><Text>에러가 발생했습니다.</Text></View>;
if (!news) return null;

각각 loading이 될 때, error가 발생했을 때, news 데이터가 없거나 loading이 제대로 되지 않았을 때 나오는 문구이다.

<ScrollView style={styles.scrollContainer} horizontal={true} showsHorizontalScrollIndicator={false} >
  {news.filter(user => user.category == 'politic').map(user => (
    <View style={styles.newsContainer}>
      <View style={styles.companyHeader}><Text key={user.id} style={styles.companyText}>{user.company}</Text></View>
      <TouchableOpacity activeOpacity='1' onLongPress={function () {navigation.push('Detail', {id: user.id})}} style={styles.article}>
        <View><Text key={user.id} style={styles.artTitle}>{user.title}</Text></View>
        <View><Image key={user.id} style={styles.artImage} source={{uri: user.img }}/></View>
        <View style={styles.artContentContainer}>
          <View><Text key={user.id} style={styles.artContent}>{user.article_extractive}</Text></View>
          <View><Text key={user.id} style={styles.artInfo}>{user.writer}</Text></View>
        </View>
      </TouchableOpacity>
    </View>
  ))}
</ScrollView>

news에 저장된 데이터 중 category가 politic인 데이터만 filtering(.filter) 해서 해당되는 기사들을 scrollview에 나열하는 코드이다. map 함수를 이용해서 뉴스 데이터 하나하나를 <뷰>로 감싸진 코드로 바꿔 나열한다.

코드를 다 작성하고 실행하면 위와 같이 연결이 잘된 화면이 완성된다.

좋은 웹페이지 즐겨찾기