데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      [DEVOCEAN 스쿨] RN(React Native) 스터디 3주차

      Teus 23.05.04
      1,505 14 0

      안녕하세요 Teus입니다.


      올해부터 DEVOCEAN을 통해서 스터디를 진행하고 있습니다!

      제가 준비한 주제는 React를 활용해서 크로스플랫폼을 플랫폼 어플리캐이션을 만드는 React Native입니다!


      image.png

      이번주는 3주차에 진행한 스터디 내용을 다루는 포스팅 입니다!


      0. 스터디 운영

      이번 주 역시 3개의 조로 나누고, 각 조별로 6~7장(다이어리 관리 앱 만들기)내용을 실습 하였습니다.

      (근데, 저같은 경우 실습시간동안 에러 하나에 30분을 소비하느라, 제대로 실습도 못하고 씌익씌익 왜안돼! 했던건 함정....)


      이번주는 기존에 배웠던 내용 + Navigation + ContextAPI를 사용해서 Component간 전역변수 관리에 대한 내용이 주를 이룹니다.


      1. Navigation

      React를 기존에 사용해보신 분들은 아시겠지만, Component간 전환을 위해서 Navigation을 자주 이용합니다.

      React Native같은 경우 react-navigation을 이용하며 여기에 추가적으로 스택네비게이터, 드로어 네비게이터, 상단탭, 하단탭 네비게이터 등을 지원합니다.

      이때 어플리캐이션에서 자주 사용되는 하단 탭 네비게이터 예제를 보도록 하겠습니다.

      import React from 'react';
      import {NavigationContainer} from '@react-navigation/native';
      import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
      import {Text} from 'react-native';
      import {SafeAreaView} from 'react-native-safe-area-context';
      
      const Tab = createBottomTabNavigator();
      
      function HomeScreen() {
        return <Text>Home</Text>;
      }
      
      function SearchScreen() {
        return <Text>Search</Text>;
      }
      
      function NotificationScreen() {
        return <Text>Notification</Text>;
      }
      
      function MessageScreen() {
        return <Text>Message</Text>;
      }
      
      function App() {
        return (
          //하단탭 네비게이터를 구현하는 부분
          <NavigationContainer>
            <Tab.Navigator initialRouteName="Home">
              <Tab.Screen name="Home" component={HomeScreen} />
              <Tab.Screen name="Search" component={SearchScreen} />
              <Tab.Screen name="Notification" component={NotificationScreen} />
              <Tab.Screen name="Message" component={MessageScreen} />
            </Tab.Navigator>
          </NavigationContainer>
        );
      }
      
      export default App;

      기본적으로 최 외곽에 <NavigationContainer> 태그로 감싸준 뒤 내부에 네비게이션을 할 컴포넌트를 넣어주게 됩니다.


      이렇게 사용할 경우 내부 컴보넌트에서 useNavigation Hook을 통해서 자유롭게 다른 Component 화면으로 이동이 가능하게 됩니다.

      import React from 'react';
      import {createMaterialBottomTabNavigator} from '@react-navigation/material-bottom-tabs';
      import {Text, Button, View} from 'react-native';
      import Icon from 'react-native-vector-icons/MaterialIcons';
      import {
          useNavigation,
      } from '@react-navigation/native';
      
      (...)
      
      function OpenDetailButton() {
        //하위 컴포넌트에서 다른 Component로 넘어가기 위한 Navigation Hook
        const navigation = useNavigation();
      
        return (
          <Button
            title="Detail 1 열기"
            //Hook으로 얻어온 navigation 객체를 활용해 다른 Component로 이동하는 모습 + arguments를 활용하는 부분
            onPress={() => navigation.push('Detail', {id: 1})}
          />
        );
      }
      
      function HomeScreen() {
        return (
          <View>
            <Text>Home</Text>
            <OpenDetailButton />
          </View>
        );
      }

      또한 navigation을 통해서 전달된 Parameter를 이용할 경우 useRoute Hook을 활용해서 편리하게 사용이 가능하게 됩니다

      import React, {useEffect} from 'react';
      import {View, Text, StyleSheet, Button} from 'react-native';
      import {useRoute} from '@react-navigation/native';
      
      function IDText() {
        //하위 Component에서 useRoute를 통해서 바로 Routeing 변수에 접근
        const route = useRoute();
        return <Text style={styles.text}>id: {route.params.id}</Text>;
      }


      2. Context API

      React는 기본적으로 useState를 통해서 변수(Props)의 상태관리를 하고, 이 상태에 따라 알아서 Component가 rendering되게 됩니다.

      하지만 이런 Props가 많아질 경우 프로그램 전체를 다루기 어려울 때가 발생합니다(하위가 아닌 다른 Component에서 해당 값에 접근해야 한다던가...)

      이럴때 Component간 공유할 수 있는 전역변수를 만들고, 이를 사용한다면 보다 편리하게 활용이 가능하겠죠?

      이럴때 사용하는게 바로 Context API입니다.


      ContextAPI는 createContext를 통해서 만들고, 해당 값으로 만들어진 <ContextName.Provider> 태그로 최외곽을 감싼 후에 내부 Component에서 사용하게 됩니다.

      //LogContext.js
      import {createContext} from 'react';
      
      const LogContext = createContext('안녕하세요');
      
      export default LogContext;
      
      //App.js
      import React from 'react';
      import {NavigationContainer} from '@react-navigation/native';
      import RootStack from './screens/RootStack';
      import LogContext from './LogContext';
      
      function App() {
        return (
          <NavigationContainer>
            //하부에 있는 RootStack에서는 이제 
            //LogContext의 value(현재는 "안녕하세요")에 접근이 가능함      
            <LogContext.Provider value="안녕하세요">
            //value가 2개 이상인 경우
            //<LogContext.Provider value = {[text1, text2]}> 형식으로 사용함
              <RootStack />
            </LogContext.Provider>
          </NavigationContainer>
        );
      }
      
      export default App;

      이 상태에서 RootStack에 존재하는 Component에서 바로 활용이 가능합니다

      (...)
      import LogContext from '../contexts/LogContext';
      
      function FeedsScreen() {
        return (
          <View style={styles.block}>
            <LogContext.Consumer>
              {(value) => <Text>{value}</Text>}
            </LogContext.Consumer>
          </View>
        );
      }

      이때 Provider 내부에 있는 Component에서 useContext Hook을 사용항 경우 보다 직관적으로 사용이 가능합니다.

      function FeedsScreen() {
        const value = useContext(LogContext);
        return (
          <View style={styles.block}>
            <Text>{value}</Text>
          </View>
        );
      }


      3. useRef Hook

      useRef는 React에서 값을 저장하지만, 변화하는 값에 따라 Component의 Refresh가 일어날 필요가 없는경우 사용하게 됩니다.

      (==> 이때 Component의 unmount때도 해당 값이 손실되지 않는다는 장점이 있습니다)

      하지만 추가적인 활용 방안이 존재합니다.


      외부component 내에서 여러개의 내부component가 있을 경우, 외부 component의 useRef객체를 만들고 이 객체를 통해서 Focus를 가져갈 component를 정할수가 있습니다.

      import React, {useRef} from 'react';
      import {View, StyleSheet, TextInput} from 'react-native';
      
      function WriteEditor({title, body, onChangeTitle, onChangeBody}) {
        const bodyRef = useRef()
      
        return (
          <View style={styles.block}>
            <TextInput
              placeholder="제목을 입력하세요"
              style={styles.titleInput}
              returnKeyType="next"
              onChangeText={onChangeTitle}
              value={title}
            />
            <TextInput
              placeholder="당신의 오늘을 기록해보세요"
              style={styles.bodyInput}
              multiline
              textAlignVertical="top"
              onChangeText={onChangeBody}
              value={body}
              //TextInput 제목을 입력하세요에서 Enter를 칠 경우
              //해당 component로 알아서 포커스가 이동함
              ref={bodyRef}
            />
          </View>
        );
      }


      4. 애니메이션

      useRef를 보면 알수있지만, 이럴거면 그냥 Context API쓰는거랑 무슨 차이가 있나? 싶습니다.

      하지만 Animated를 활용하기 위해서는 useRef를 통해서 만들어진 Animated.Value를 활용해야 합니다.


      아래 예시를 보시죠

      import React, {useRef} from 'react';
      import {Animated, Button, StyleSheet, View} from 'react-native';
      
      function FadeInAndOut() {
        const animation = useRef(new Animated.Value(1)).current;
      
        return (
          <View>
            <Animated.View
              style={[
                styles.rectangle,
                {
                  opacity: animation,
                },
              ]}
            />
            <Button
              title="FadeIn"
              onPress={() => {
                Animated.timing(animation, {
                  toValue: 1,
                  useNativeDriver: true,
                }).start();
              }}
            />
            <Button
              title="FadeOut"
              onPress={() => {
                Animated.timing(animation, {
                  toValue: 0,
                  useNativeDriver: true,
                }).start();
              }}
            />
          </View>
        );
      }
      
      function CalendarScreen() {
        return (
          <View style={styles.block}>
            <FadeInAndOut />
              </View>
        );
      }

      해당 Component에서 <Animated.Tag> 를 통해서 Animation이 적용될 Component를 만들고, 해당 Component에 useRef로 만들어진 Value를 property로 집어넣는 방식으로 사용합니다.


      5. useWindowDimensions Hook

      모바일 환경에서는 가로, 세로 전환에 따라 화면의 크기가 바뀌게 됩니다.

      이 경우를 대비해서 useWindowDimensions hook을 이용할 경우 화면 가로/세로 전환에 따른 변화된 width, height를 사용할 수가 있습니다.

      import React from 'react';
      import {StyleSheet, useWindowDimensions, View} from 'react-native';
      
      function SearchHeader() {
        const {width} = useWindowDimensions();
        return <View style={[styles.block, {width: width - 32, height: 24}]} />;
      }


      6. 검색 구현하기

      검색을 구현하기 위해서는 list를 구현하기 위해서 사용되는 Object의 모든 keyword에 해당하는 value를 찾아볼 필요가 있습니다.

      이때 array.some((value)=>value.includes(keyword))를 할 경우 array에서 Element를 하나씩 꺼내고,

      이 Element에 특정 키워드가 포함될 경우 True를 반환한 뒤 반복을 멈추고, 마지막까지 없을경우 False를 반환합니다.


      그럼 이 array.some과 array.filter를 조합할 경우 object의 value값에 대한 filtering이 가능해 집니다.

      //logs에서 log하나를 빼옴
      logs.filter((log) =>
          //log의 title과 body에서 특정 keyword가 있는 지 찾아봄
          [log.title, log.body].some((text) => text.includes(keyword)),
      )

      해당 기능과, useState를 결합하면 Search결과만을 가지고와서 Rendering하는것이 가능해 집니다


      7. 스터디 3주차를 마치면서...

      IMG_2747.jpgIMG_2741.jpg

      IMG_2742.jpgIMG_2743.jpg


      이번주까지 진행을 하면서 문제점을 정리해보면

      1. 스터디를 모여서 책을 읽기에는 주제가 맞지 않았다.(1주차)

      2. 스터디에 참여한 인원들간의 사전지식의 차이가 있고, 모두 맞추어서 진도를 나가기가 쉽지않다.

      3. 책을 읽어오고 당일에 모여서 실습하는거는 토의보다는 모각코에 가까웠다.(2~3주차)

      라는 문제점들이 보였습니다.


      다행히 스터디 조교(사실상 리더) 왕태웅님의 도움 + 스터디원들의 VOC 덕분에

      스터디의 진행방향을 조금 바꾸게 되었습니다.


      다음주부터는 읽어온 책을 바탕으로 1시간 토의 + 1시간 프로젝트 구상 방식으로 변경될 예정입니다.

      이상 계속 진행이 바뀌는 우당탕탕 RN스터디 3주차 포스팅이었습니다!

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      Teus 님의 최신 블로그

      더보기
      동영상 기고하기