우선 리액트 네이티브를 사용하려면 리액트 네이티브를 설치하여야한다.
그리고 안드로이드 스튜디오도 설치해야하고...
ios용으로 빌드하기 위해선 xcode도 설치해야하고...
watchman도...cocoapod도...create-react-native-app도...
그치만 그것은 생략맨
리액트 네이티브에 그래프큐엘을 부착해보려고 한다.
목표
1. expo를 사용하지 않고 React Native 프로젝트를 생성
2. Apollo Client를 사용하여 GraphQL 부착하기
1. expo를 사용하지 않고 React Native 프로젝트를 생성
먼저 프로젝트를 만들어보자.
리액트 네이티브 프로젝트를 만드는데 가장 널리쓰이는 방법은 2가지가 있다.
1) Expo를 사용
2) React-native CLI를 사용
네이티브 앱을 만든다는 특성상 android와 ios 시뮬레이터(에뮬레이터)는 빼놓을 수 없는 요소이다.
특히나 내가 사용하고 있는 컴퓨터가 윈도우 운영체제일때, ios 앱 빌드를 위해 맥 하드웨어를 구매해야하는 것은 굉장히 큰 부담이 된다.
그러나 expo를 사용하게 되면 배포, 업데이트가 용이할 뿐 아니라 윈도우에서도 ios 앱을 빌드할 수 있다.
create-react-native-app (CRNA)에서도 expo 기반의 프로젝트를 구성하고 있다.
다만 Expo를 사용하게되면 expo 관련 세팅, 기능 등이 포함되어서 불필요하게 큰 용량을 가진 채로 프로젝트가 생성되게 된다.
이 외에도 여러 장점이 있고, 여러 제약사항이 있지만 이 글에서는 다루지않도록 하고
아무튼 가벼운 샘플 프로젝트를 만드는 내용이기 때문에 Expo(혹은 CRNA)의 도움없이 프로젝트를 만드려고 한다.
npx react-native init SampleApp
위 명령어를 통해서 SampleApp 이라는 프로젝트를 하나 만들었다.
그러면 이런 구조를 가진 프로젝트가 하나 생성이 된다.
정상적으로 프로젝트가 생성되었는지 알기 위해 실행을 한번 해본다.
yarn run ios # ios
yarn run android # android
(ios 기준)
그랬더니 이런 ios 에뮬레이터가 뜨면서 리액트 네이티브 웰컴이오 하면 야호 1번 목표는 끝이여
이것 참 쉽구만.
사실 모든 프로젝트가 대부분 그렇지만 세팅과정에서 오류를 겪거나 하라는대로 따라해도 에러가 나는 등의 문제를 접하곤 한다.
react-native 또한 발생하는 에러의 케이스나 원인이 너무 다양한데 얘는 android, ios 별도로 문제가 발생할 수도 있어서 더 짜증이 난다.
근데 어쩌겠슴ㅋㅋ
index.js
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
index.js를 보면 이런 코드가 있는데
AppRegistry.registerComponent의 첫번째 파라미터는 프로젝트명(정보)로 보면 될 것 같다.
중요한 것은 두번째 파라미터인데, 실질적으로 화면을 등록하는 부분이다.
지금은 App.js 파일의 App 함수의 리턴값을 화면에 뿌려주도록 되어있다.
우선 src 폴더를 하나 만들고, 안에 NewApp.js 파일을 생성하여 아래와 같이 작성하였다.
src/NewApp.js
import React from 'react';
import {SafeAreaView, Text} from 'react-native';
const NewApp = () => {
return (
<SafeAreaView>
<Text>저는 새로운 화면입니다.</Text>
</SafeAreaView>
);
};
export default NewApp;
그리고 index.js를 아래와 같이 수정하였다.
index.js
import {AppRegistry} from 'react-native';
// import App from './App';
import NewApp from './src/NewApp';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => NewApp); // App을 NewApp으로 대체
그리고 나서 빌드 결과물을 보면...
띠띠용~
잘 바뀐 것을 확인 할 수 있다.
사실 React에서의 index.js와 같은 역할을 하는 것이다.
아무튼 프로젝트를 정상적으로 만들었다면, 다음은 GraphQL과 Apollo Client를 붙여보자.
2. Apollo Client를 사용하여 GraphQL 부착하기
아폴로가 뭐고 그래프큐엘이 뭐시여!
GraphQL은 페이스북에서 만든 쿼리 언어이다.
쿼리 언어라는 말을 쉽게 풀면, 데이터를 요청하는 언어라는 것이다.
예를 들어
호출주소가 이 API의 호출주소가 server.com/api/user 이고
아래와 같은 데이터를 반환하는 API가 있다.
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
...
그런데 내가 만약 필요한 정보가 userId와 title뿐이라면?
일반적인 REST API 구조에서는 우선 전체 데이터를 가져와야한다.
지금은 4개의 속성정보 중 내가 쓰고 싶은 속성값은 2개고, 버려질(안쓸) 속성값도 2개지만
만약 16개 반환 속성값을 가진 API에서 내가 쓰고자 하는 속성값이 3개 정도뿐이라면.
리소스가 불필요하게 낭비되고, 이를 처리하기 위해 또 다른 하나의 API를 만들어야할 수도 있다.
이러한 문제를 Over Fetching이라고 한다.
반대의 경우인 Under Fetching도 있을 수 있다.
화면에서 보여주고자 하는 데이터가 userId와 title, adress 라는 세 속성값이다.
그런데 userId와 title은 A API를 호출해야하고, adress는 B API를 호출해야한다면
한 화면에서 보여주고자 하는 데이터 호출을 위해 어쩔 수 없이 2개의 API를 호출해야한다.
GraphQL은 이러한 문제 해결에 특화되어 있는 언어이다.
우선 GraphQL에 대해서는 나중에 더 작성해보기로 하겠다!
아래 페이지를 참고하면 GraphQL의 기본적인 설명에 대해 읽어볼 수 있다.
Apollo는 이런 GraphQL을 좀 더 강력하게 사용 할 수 있게 해준다.
Apollo Client는 Redux를 대체할 수 있으며, Apollo Server는 REST API를 대체할 수 있다고 한다.
우리는 이 중에 Apollo Client를 이용하려고 한다.
우선 Apollo와 GraphQL을 프로젝트에 설치해주자.
npm install @apollo/client graphql
이렇게하면 일단 기본적인 프로젝트 구성은 끝!
이제 Apollo Client를 사용하여 GraphQL을 프로젝트에 등록해보고자 한다.
src/NewApp.js
import React from 'react';
import {ApolloClient, ApolloProvider} from '@apollo/client';
// Initialize Apollo Client
const client = new ApolloClient({
uri: 'https://countries.trevorblades.com',
});
const NewApp = () => {
return (
<ApolloProvider client={client}>
...
</ApolloProvider>
);
};
export default NewApp;
우선 ApolloClient 인스턴스를 생성하는데, 사용하고자 하는 GraphQL 서버의 주소를 넣어주도록 한다.
(샘플로 사용한 주소는 무료 GraphQL 서버이다.)
그리고 NewApp 함수의 가장 바깥 쪽를 ApolloProvider로 감싸주고, client를 등록한다.
Redux를 써봤다면 Provider로 감싸고, store를 등록하는 과정과 매우 유사하다고 느낄 것이다.
하는 일도 매우 비슷하다. 감싸진 Provider에 등록된 Client를, 내부에서 호출하는 컴포넌트에서 쓰겠다는 것!
src 폴더에 TempComponent.js 라는 파일을 하나 만들어서, 코드를 작성해보자.
src/TempComponent.js
import React from 'react';
import {SafeAreaView, View, StyleSheet, Text, FlatList} from 'react-native';
import {gql, useQuery} from '@apollo/client';
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#ffffff',
},
title: {
fontSize: 30,
},
});
const GET_DATA = gql`
query {
continents {
code
name
}
}
`;
const TempComponent = () => {
const {data, loading} = useQuery(GET_DATA);
const renderFunction = ({item}) => {
return (
<View>
<Text>
{item.name} ({item.code})
</Text>
</View>
);
};
return (
<SafeAreaView>
<FlatList
data={data?.continents}
renderItem={renderFunction}
keyExtractor={({item}) => String(item?.code)}
/>
</SafeAreaView>
);
};
export default TempComponent;
전체코드는 위와 같은데, 나눠서 설명을 하려다가 연결하여 설명하고자 전체코드를 써두었다.
1. styles
이 부분은 말 그대로 화면의 스타일을 정의하는 부분이다. CSS 같은 부분이니 넘어가도록 하겠다.
2. GET_DATA와 useQuery
GraphQL의 쿼리를 작성하는 부분이다.
gql이라는 템플릿 리터럴로 감싸서 가져오고자 하는 데이터를 정의하면 된다.
여기서 작성된 코드는 useQuery라는 Hook을 통해서 fetching되게 된다.
useQuery가 반환하면 loading 변수는 데이터를 가져오고 있을 땐 true, 가져왔을 땐 false값을 가지게 된다.
이를 이용해서 데이터를 가지고 오는 중 일때와 가져왔을 때의 분기처리를 쉽게 할 수 있다.
참고로 작성한 쿼리의 응답결과는 아래와 같다.
(https://countries.trevorblades.com에서 직접 작성, 테스트가 가능하다.)
3. FlatList
FlatList는 사실 React-native 문법이기 때문에 잘 설명해두신 분의 링크로 대체하도록 하겠
TempComponent를 작성했으니 NewApp.js에 해당 컴포넌트를 끼워넣도록 하자.
src/NewApp.js
import React from 'react';
import {ApolloClient, ApolloProvider} from '@apollo/client';
import TempComponent from './TempComponent';
// Initialize Apollo Client
const client = new ApolloClient({
uri: 'https://countries.trevorblades.com',
});
const NewApp = () => {
return (
<ApolloProvider client={client}>
<TempComponent />
</ApolloProvider>
);
};
export default NewApp;
renderFunction에서 지정해준 방식대로 데이터를 잘 표출하고 있는 모습이다.
얏호우우우루루
'프로그래밍 > Javascript' 카테고리의 다른 글
노션 페이지를 React로 웹에 띄워보자 (react-notion) (5) | 2020.11.21 |
---|---|
구조분해 할당(비구조화 할당) (Destructuring assignment) (0) | 2020.06.29 |
React에서 화면을 만드는 흐름 (index.js, index.html, app.js) (0) | 2020.06.03 |
VS Code로 React + SpringBoot 개발환경 세팅 (2/2) (0) | 2020.06.02 |
VS Code로 React + SpringBoot 개발환경 세팅 (1/2) (0) | 2020.06.02 |