React Native 코드 분석

hj·2021년 10월 15일
0

1. navigations

react native는 navigator를 이용해 화면 전환을 한다. navigator의 종류에는 stack, drawer, tab이 있다.

프로젝트에는 크게 root, tab, stack, drawer 폴더로 나뉘어져 있다.

RootNavigator

최상단에 있는 navigator로 앱을 처음 실행시켰을 때 사용자에게 어떤 화면을 보여줄지 결정한다. 회원가입 and 로그인 과정을 거쳐 token을 가지고 있다면 앱의 메인 화면(피드)으로, 가지고 있지 않다면 회원가입 or 로그인 화면으로 이동한다.

TabNavigator

tab 폴더 안에는 여러개의 TabNavigator가 포함되어 있다. 그 중 MainBottomTabNavigator는 화면 하단의 탭으로 위치하며, 로그인을 한 후 화면 전환을 담당한다. 각각의 stack navigator로 구성된 피드, 채팅, 알림, 내 정보 탭으로 이동할 수 있다.

StackNavigator

stack 폴더 안에도 여러개의 StackNavigator가 포함되어 있다. 크게 피드, 채팅, 알림, 내 정보 화면을 구성하고 있는 navigator가 있다.

2. screens

Screens 폴더에는 화면을 구성할 UI들이 정의되어 있다. Navigator에서 특정 화면을 보여줄 때 Screens 폴더의 파일을 import하여 보여준다.

3. repositories

repositories 폴더에는 AsyncStorage에 데이터를 저장하거나 가져오는 기능이 구현되어 있다.
AsyncStorage에 로그인을 했을 때 발급받은 토큰이나 사용자가 고정한 카테고리 등을 저장한다.

state의 경우 앱이 꺼지면 모두 리셋된다. 앱을 껐다가 켜더라도 유지해야 하는 데이터의 경우 AsyncStorage를 이용할 수 있다.

4. client

client 폴더에는 Apollo Client와 관련된 설정들이 존재한다.

  • GraphQL 서버와의 데이터 처리/통신 방법(link)
  • Apollo Client의 캐시 설정
  • AsnycStorage에 캐시 데이터 저장

operation 타입(query, mutation/subscription)에 따라 다른 통신 방법(HTTP/Web socket)을 사용하기 위해서는 Apollo Client의 ApolloLink 라이브러리로 설정할 수 있다.

ApolloLink는 Apollo Client와 GraphQL 서버의 데이터 흐름을 제어(& 에러 로깅)할 수 있다.

GraphQL의 operation 타입에는 query, mutation, subscription이 있다. 채팅방 기능을 구현하기 위해서 GraphQL의 subscription을 이용하는데, query와 mutation을 사용할 때는 HTTP 통신 방법을, subscription을 사용할 때는 websocket 통신 방법을 사용한다.

- Http Link
HTTP 통신 방법을 이용해서 GraphQL의 서버로 오퍼레이션을 보낸다. POST, GET 요청을 할 때 사용할 수 있다.

import { HttpLink } from '@apollo/client';

const link = new HttpLink({
  uri: "http://localhost:8000/graphql",
});

ApolloClient 생성자를 초기화할 때 uri 옵션을 사용한 경우 기본적으로 ApolloLinkHttpLink를 이용해서 GraphQL 서버로 오퍼레이션을 보내게 된다.

import { ApolloClient } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://localhost:8000/graphql', // Http 프로토콜 이용
});

- WebSocket Link
GraphQL의 오퍼레이션 중 subscription을 보낼 때 주로 사용한다.

import { WebSocketLink } from "@apollo/client/link/ws";

const link = new WebSocketLink({
  uri: "ws://localhost:3000/subscriptions",
  options: {
    reconnect: true
  }
});

- Error Link
GraphQL 오퍼레이션을 실행할 때 나타나는 에러(network에러, 문법 에러 등)를 처리할 수 있다.

ApolloClient 생성자를 초기화할 때 여러 가지 link가 들어갈 수 있는데 각 link들이 실행될 순서나 방향을 정해주어야 한다.

link를 구성하는데는 2가지 방법이 있다.

  • Additive composition: 단방향
    단방향으로 구성(순서대로 실행)되어야 하는 링크가 2개 이상인 경우 ApolloLinkfrom 메소드를 이용해서 합쳐줘야 한다.
    ex) from([errorLink, authLink, httpLink])

  • Directional composition: 한 링크에서 분기하는 경우
    오퍼레이션에 따라서 링크가 달라지는 경우 ApolloLinksplit 메소드를 이용해서 나눠준다.
    split()메소드는 test, left, right 3개의 매개 변수로 구성되어 있다. test는 현재 실행 중인 오퍼레이션에 따라 왼쪽 link로 분기해야 하는 경우 true를, 오른쪽 link로 분기해야 하는 경우 false를 리턴해주면 된다. left, right에는 test에서 true, false를 반환했을 때 실행시켜야 할 링크를 넣어주면 된다.
                       ->   websocketLink
errorLink -> authLink 
                       ->   uploadLink

캐시

InMemoryCacheoptions 객체를 이용해서 캐시 설정을 할 수 있다.

Type Policies

options 객체는 여러가지 필드를 가지고 있다. 그 중 typePolicies는 GraphQL 서버에 정의된 스키마의 타입 별로 캐시가 어떻게 동작할지 설정할 수 있다. typePolicies는 스키마의 타입인 __typename을 키 값으로 가지고, 그 타입이 어떻게 동작해야하는지 정의할 수 있는 객체인 TypePolicy를 값으로 가지고 있다.

const cache = new InMemoryCache({ 
  typePolicies: {
    [__typename]: TypePolicy,
  },
});

GraphQL의 스키마의 타입이 Object type인 경우 __typename 필드를 가지는데 Object type의 이름으로 설정된다.

type Book {
  title: String
  content: String
}

Book 스키마가 위와 같이 정의되어 있을 때, Book 스키마의 __typenameBook이 된다.

Object type에는 GraphQL의 오퍼레이션 타입인 Query, Mutation, Subscription도 포함되어있다.

Field policies

TypePolicy 객체에는 fields 필드가 있는데 캐시가 특정 field를 읽고 쓰는 방법 or 페이지네이션을 위한 설정을 할 수 있다.

const cache = new InMemoryCache({ 
  typePolicies: {
    [__typename]: {
      fields: FieldPolicy,
    },
  },
});

페이지네이션이란?
클라이언트에서 서버로 필요한 데이터를 요청할 때 원하는 것보다 많은 데이터를 받을 수 있다. 이렇게 되면 오버헤드가 커지게 된다. GraphQL 서버에서 클라이언트에서 요청한 만큼의 데이터를 보내주는 방법으로 이 문제를 해결할 수 있는데 이를 페이지네이션이라고 한다.

오버헤드: 특정 기능을 수행하는데 드는 간접적인 시간, 메모리 등의 자원
https://donggu1105.tistory.com/175

페이지네이션 구현 방법 in Apollo Client
fetchMore 함수를 이용해서 추가적인 데이터를 요청할 수 있는데, (useQuery hook의 반환 값으로 제공된다.) fetchMorevariables 옵션으로 offset등을 설정할 수 있다.

페이지네이션되는 데이터를 캐시에 저장하는 경우, fetchMore 함수로 요청한 추가적인 데이터를 기존의 데이터와 합쳐주는 과정이 필요하다면 InMemoryCache의 field policy를 정의해주어야 한다.

posts 쿼리를 보냈을 때 반환되는 데이터를 합치는 예시

query {
  posts {
    id,
    title,
    content
  }
}
const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        posts: {
          keyArgs: [],
          merge() {},
        },
      },
    },
  },
});

5. operations

서버로 요청할 GraphQL의 query, mutation, subscription과 관련된 함수들이 구현되어 있다.

reference

0개의 댓글