ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [앱개발 종합]리액트-네이티브 Part.1
    카테고리 없음 2021. 7. 6. 17:41

    2주차. 리액트-네이티브로 앱개발하기

     

    <리액트-네이티브란?>

    리액트 네이티브는 우리가 배운 자바스크립트 언어 하나로 안드로이드 앱과 iOS앱 두 가지 모두 만들어주는 라이브러리(개발 도구) 입니다.

     

    <Expo란?>

    리액트 네이티브 앱 개발을 수월하게 도와주는 도구가 존재하는데, 이것이 바로 Expo입니다. 리액트 네이티브로 앱을 개발할 때, 안드로이드 & iOS 코드를 건드려야 하는 대부분의 상황들을 안 건드려도 되게끔 도와주는 툴입니다. 또한 앱 개발을 편리하게 해주는 도구들이 많이 존재합니다.

     

    Expo를 이용한 앱 개발 순서

    1. Expo명령어 설치하기

    2. 로컬에 Expo계정 세팅하기

    3. expo init 명령어로 기본앱 생성하기

    : 터미널에서 expo init 명령어로 프로젝트를 생성하면 Expo로 부터 기본 골격이 짜여져 있는 코드가 생성되는데, 각 파일들을 간단히 알아보자면.. asset - 앱이 동작되는데 기본적으로 가지고 있는 이미지나 아이콘을 담는 폴더,  nodes_modules - 앱 개발을 하면서 설치할 라이브러리들이 저장되는 장소, App.js - 앱의 메인 화면, app.json - 앱이 가지는 기본 정보들을 설정하는 파일

    4. expo start로 Expo 앱 실행하기 

    : 터미널에서 expo start 명령어를 실행해주면 QR코드가 생성됩니다.

    5. 휴대폰에 설치한 Expo 클라이언트 앱으로 Expo 앱 실행

    휴대폰으로 QR코드를 인식시키면 바로 앱 화면이 생성되는 것을 확인할 수 있습니다.

     

    추가) App.js로 개발하다보면 노란 경고창이 뜰 때가 있는데, 이 때 App.js에 다음과 같은 코드 한줄을 통해 안보이게 할 수 있습니다.

    console.disableYellowBox = true;

     

    <JSX 문법>

    HTML태그와 비슷하게 생긴 JSX는 App.js의 화면을 구성하는데 필요한 태그 문법입니다. 리액트 네이티브에서 return은 작성한 JSX문법으로 구성된 화면을 앱에 보여주는 역할을 하는 겁니다. (렌더링)

     

    1. <View></View>

       : 화면의 영역(레이아웃)을 잡아주는 엘리먼트 입니다. App.js에서 View는 화면 전체 영역을 가지게 됩니다. View를 통      해 화면을 분할하기도 하는데 이때는 StyleSheet가 필요하답니다.

    2. <Text></Text>

       : 앱에 텍스트를 작성하려면 반드시 사용해야 하는 엘리먼트입니다.

    3. <ScrollView</ScrollView>

       : 앱은 보통 많은 양의 정보를 담고 있습니다. 그래서 앱 화면을 벗어나는 경우가 많은데 이때 ScrollView를 사용하면       스크롤이 가능해지면서 모든 컨텐츠를 볼 수 있습니다. 

    4. <Button/>

       : 앱에서 버튼을 누르면 팝업이 뜨거나, 다른 페이지로 이동하는데 Button을 통해 쉽게 버튼을 만들 수 있습니다.

         버튼이 눌리면 팝업이 뜨게 하기 위해서는 onPress속성을 통해 팝업이 뜨게 할 수 있습니다.

    onPress={function(){   //onPress={()=>{
                Alert.alert('팝업 알람입니다!!')
    }}

    5. <TouchableOpacity/>

       : 영역을 충분히 가지는 텍스트 카드 부분이라고 할 수 있습니다. 버튼의 역할을 하는 이 엘리먼트는 화면의 임의의 영

         역과 디자인에 버튼 기능을 할 때 사용합니다.

    6. <Image>

       : 앱에 이미지를 삽입할 때 사용하는 태그로, 두가지 방식으로 이미지를 사용할 수 있습니다.

         - assets폴더에 있는 이미지를 가져와서(import) 사용하는 방법 ex) import favicon from "./assets/favicon.png" 

         - 외부 이미지의 uri를 넣어서 사용하는 방법

     

    <JSX문법 -  StyleSheet>

    구성한 앱화면을 꾸미기 위한 StyleSheet은 결국 객체(딕셔너리)를 하나 만드는데, 이쁜 옷들을 입혀주는 객체 입니다. 이 객체에 옷을 사용법대로 생성한 다음 잘 정리해 두고, JSX 엘리먼트에서 사용합니다. 각각의 태그별로 여러 Style을 가지고 있기 때문에 중요한 것 위주로 설명하고, 나머지는 직접 구성하면서 설명해보도록 하겠습니다.

    1. margin과 padding  

      : margin과 padding은 다음 이미지들 처럼, 영역의 바깥과 안의 여백을 결정합니다. margin은 어느정도 여백을 두고       배치할 것인지를 의미하고, padding은 어느정도의 여백을 두어 내부의 요소를 위치시킬 것인지를 결정합니다.

    2. 컨텐츠의 위치 : flex

       : flex는 영역을 차지하는 속성인데, 레이아웃을 상대적으로 결정하게 됩니다. 만약 전체 화면이 1이고 A가 1, B가 2ㅇ      니 경우에 A는 전체화면의 1/3을 차지하고, B는 전체화면의 2/3를 차지하게 되는 것입니다. 즉, 같은 레벨의 엘리먼        트들의 flex 합을 각자의 flex 속성값 대로 가져갑니다.

    3. flexDirection

       : 자리잡은 영역의 방향을 의미합니다. flexDirection:"row"는 가로 방향으로 , "colum"은 세로 방향으로 영역을 배치합       니다. 기본값은 colum입니다. 

    4. justifyContent

       : justifyContent는 flexDirection과 동일한 방향으로 정렬하는 속성입니다 flexDirection: 'column'에서 justifyContent는      상하 정렬, flexDirection: 'row'에서 justifyContent는 좌우 정렬을 뜻합니다. flex-start, center, flex-end, space-               between, space-around 속성을 가집니다.

    5. alignItems

       : Align Items는 Flex Direction과 수직한 방향(반대 방향이라고 생각하면 편합니다)으로 정렬하는 속성입니다.                 flexDirection: 'column'에서 alignItems는 좌우 정렬, flexDirection: 'row'에서 alignItems는 상하 정렬을 뜻합니다           flex-start, center, flex-end, stretch 속성을 가집니다.

     

    <메인 화면 꾸미기>

    import React from 'react';
    import { StyleSheet, Text, View, ScrollView, Image, TouchableOpacity } from 'react-native';
    
    export default function App() {
      return (
        <ScrollView style={styles.container}>
          <Text style={styles.textStyle}>나만의 꿀팁</Text>
          <Image 
            source={{uri:'https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fmain.png?alt=media&token=8e5eb78d-19ee-4359-9209-347d125b322c'}}
                // 사용설명서에 나와 있는 resizeMode 속성 값을 그대로 넣어 적용합니다
            resizeMode={"cover"}
            style={styles.mainImage}
          />
          <ScrollView style={styles.menucontainer} horizontal indicatorStyle={"white"} > //스크롤 뷰를 가로로 하기 위한 속성
            <TouchableOpacity style={styles.textContainer1}>
              <Text style={styles.menu_textStyle}>생활</Text>
            </TouchableOpacity>
            <TouchableOpacity style={styles.textContainer2}>
              <Text style={styles.menu_textStyle}>재테크</Text>
            </TouchableOpacity>
            <TouchableOpacity style={styles.textContainer3}>
              <Text style={styles.menu_textStyle}>반려견</Text>
            </TouchableOpacity>
            <TouchableOpacity style={styles.textContainer4}>
              <Text style={styles.menu_textStyle}>꿀팁 찜</Text>
            </TouchableOpacity>
          </ScrollView>
          <View style={styles.feed}>
              <Image style={styles.feedImage} source={{uri:"https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fpizza.png?alt=media&token=1a099927-d818-45d4-b48a-7906fd0d2ad3"}}/>
              <View style={styles.feedText}>
                <Text style={styles.feedTitle}>먹다 남은 피자를 촉촉하게!</Text>
                <Text style={styles.feedInfo} numberOfLines={3}>먹다 남은 피자는 수분이 날라가기 때문에 처음처럼 맛있게 먹을 수 없는데요. 이럴 경우 그릇에 물을 받아 전자레인지 안에서 1분 30초에서 2분 정도 함께 돌려주면 촉촉하게 먹을 수 있습니다. 물이 전자레인지 안에서 수증기를 일으키고, 피자에 촉촉함을 더해줍니다.</Text>
                <Text style={styles.feedDate}>2020.09.09</Text>
              </View>
            </View>
           
        </ScrollView>
    
      
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        backgroundColor: '#fff',
      },
      textStyle: {
        color:"black",
        fontSize:20,
        fontWeight:"700",
        marginLeft:20,
        marginTop:50
      },
      mainImage: {
        width:'90%',
        height:200,
        borderRadius:10,
        marginTop:20,
        alignSelf:"center"
      },
      menucontainer: {
        marginTop:20
      },
      textContainer1: {
        width:100,
        height:60,
        backgroundColor:'#fdc453',
        borderRadius:15,
        margin:10,
        padding:20
      },
      textContainer2: {
        width:100,
        height:60,
        backgroundColor:'#fe8d6f',
        borderRadius:15,
        margin:10,
        padding:20
      },
      textContainer3: {
        width:100,
        height:60,
        backgroundColor:'#9adbc5',
        borderRadius:15,
        margin:10,
        padding:20
      },
      textContainer4: {
        width:100,
        height:60,
        backgroundColor:'#f886a8',
        borderRadius:15,
        margin:10,
        padding:20
      },
      menu_textStyle: {
        color:"white",
        //글자의 크기를 결정합니다
        fontSize:15,
        fontWeight:"700",
        textAlign:'center'
      },
      
      feed:{
        marginTop:20,
        flex:1,
        flexDirection:"row",
        borderBottomWidth:1,
        borderBottomColor:"gray",
        paddingBottom:10
    
      },
      feedImage: {
        flex:1,
        width:100,
        height:100,
        borderRadius:10,
      },
      feedText: {
        flex:2,
        flexDirection:"column",
        marginLeft:10,
      },
      feedTitle: {
        fontSize:20,
        fontWeight:"700"
      },
      feedInfo: {
        fontSize:15
      },
      feedDate: {
        fontSize:10,
        color:"gray",
      }
    });

     

    <앱과 자바스크립트>

    -모듈과 반복문 (data.json)

    위에서는 피드(카드)에 해당하는 내용을 직접적으로 넣어주고 있는데 이 데이터가 많다면 어떻게 할까요? data.json에 준비된 데이터가 존재한다면 반복문을 통해 담겨져 있는 데이터를 사용할 수 있습니다. 

    //data.json
    {
        "tip":[
            {
                "idx":0,
                "category":"생활",
                "title":"먹다 남은 피자를 촉촉하게!",
                "image":"https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fpizza.png?alt=media&token=1a099927-d818-45d4-b48a-7906fd0d2ad3",
                "desc":"먹다 남은 피자는 수분이 날라가기 때문에 처음처럼 맛있게 먹을 수 없는데요. 이럴 경우 그릇에 물을 받아 전자레인지 안에서 1분 30초에서 2분 정도 함께 돌려주면 촉촉하게 먹을 수 있습니다. 물이 전자레인지 안에서 수증기를 일으키고, 피자에 촉촉함을 더해줍니다.",
                "date":"2020.09.09"
            },
            
            ....
            
       }

    준비된 데이터를 App.js에서 불러오기 위해서는 "import data from './data.json';"로 불러오게 됩니다. 이렇게 불러온 데이터를 내가 구성하고 싶은대로 구성하기 위해 반복문을 사용하는데 지난 시간에 학습했던 map을 이용하면 다음과 같이 코드를 구성할 수 있습니다.

    //App.js
    <View style={styles.cardContainer}>
        {/* 하나의 카드 영역을 나타내는 View */}
             { 
              tip.map((content,i)=>{
                return (<View style={styles.card} key={i}>
                  <Image style={styles.cardImage} source={{uri:content.image}}/>
                  <View style={styles.cardText}>
                    <Text style={styles.cardTitle} numberOfLines={1}>{content.title}</Text>
                    <Text style={styles.cardDesc} numberOfLines={3}>{content.desc}</Text>
                    <Text style={styles.cardDate}>{content.date}</Text>
                  </View>
                </View>)
              })
             }
    </View>

     

    -{}표현식

    export default function App() {
      console.disableYellowBox = true;
      //return 구문 밖에서는 슬래시 두개 방식으로 주석
    
      let tip = data.tip;
      let todayWeather = 10 + 17;
      let todayCondition = "흐림"
      return (
        <ScrollView style={styles.container}>
          <Text style={styles.title}>나만의 꿀팁</Text>
          <Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text> //{}표현식 사용
          <Image style={styles.mainImage} source={main}/>

    -if문

    if문, 조건문을 통해서 홀수의 데이터 혹은 짝수의 데이터만 다르게 보이게 할 수 있습니다. 위에서 작성하였던 코드에 삼항 연산자를 사용하여 홀수 데이터와 짝수 데이터를 구분하는 코드는 다음과 같습니다.

    <View style={styles.cardContainer}>
             {/* 하나의 카드 영역을 나타내는 View */}
             { 
              tip.map((content,i)=>{
                return i % 2 == 0 ? (<View style={styles.cardEven} key={i}> //삼항연산자 사용
                  <Image style={styles.cardImage} source={{uri:content.image}}/>
                  <View style={styles.cardText}>
                    <Text style={styles.cardTitle} numberOfLines={1}>{content.title}</Text>
                    <Text style={styles.cardDesc} numberOfLines={3}>{content.desc}</Text>
                    <Text style={styles.cardDate}>{content.date}</Text>
                  </View>
                </View>) : (<View style={styles.cardOdd} key={i}>
                    <Image style={styles.cardImage} source={{uri:content.image}}/>
                    <View style={styles.cardText}>
                      <Text style={styles.cardTitle} numberOfLines={1}>{content.title}</Text>
                      <Text style={styles.cardDesc} numberOfLines={3}>{content.desc}</Text>
                      <Text style={styles.cardDate}>{content.date}</Text>
                    </View>
                  </View>)
                
              })
             }  
    </View>

     

    <어바웃 화면 만들기>

     

    import React from 'react';
    import main from '../assets/main.png';
    import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView, Alert, Linking} from 'react-native';
    export default function AboutPage() {
      console.disableYellowBox = true;
      const customAlert = () => {
        //Alert.alert("OOO의 인스타계정으로 이동합니다.")
        Linking.openURL('https://www.instagram.com/instaId/')
      }
      return (
        <View style={styles.container}>
          <Text style={styles.title}>HI! 스파르타코딩 앱개발반에 오신걸 환영합니다</Text>
          <View style={styles.textContainer}>
            <Image style={styles.Image} source={{uri:"https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2FaboutImage.png?alt=media&token=13e1c4f6-b802-4975-9773-e305fc7475c4"}}/>
            <Text style={styles.context1}>많은 내용을 간결하게 담아내려 노력했습니다!</Text>
            <Text style={styles.context2}>꼭 완주하셔서 꼭 여러분 것으로 만들어가시길 바랍니다.</Text>
            <TouchableOpacity style={styles.button} onPress={customAlert}><Text style={styles.ButtonText}>OOO의 인스타 계정</Text></TouchableOpacity>
          </View>
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        height: 1000,
        backgroundColor: '#260074',
      },
      title: {
        fontSize: 40,
        fontWeight: '700',
        textAlign:'center',
        color:'#fff',
        marginTop:100,
        marginLeft:15,
        marginRight:15
      },
      textContainer: {
        marginTop:50,
        marginLeft:30,
        marginRight:30,
        marginBottom:50,
        height:550,
        paddingTop: 50,
        paddingLeft: 25,
        paddingRight: 25,
        borderRadius:30,
        backgroundColor:"#fff",
      },
      Image: {
        width:'50%',
        height:150,
        borderRadius:25,
        marginTop:20,
        alignSelf:"center"
      },
      context1: {
        fontSize: 25,
        fontWeight: '700',
        textAlign:'center',
        color:'#000',
        marginTop:20,
      },
      context2: {
        fontSize: 18,
        fontWeight: '700',
        textAlign:'center',
        color:'#000',
        marginTop:20,
      },
      button: {
        width:200,
        height:70,
        padding:20,
        backgroundColor:"#fdc453",
        borderRadius:15,
        margin:30,
        alignSelf:"center"
      },
      ButtonText: {
        color:"#fff",
        fontSize: 18,
        fontWeight:"700", 
        textAlign:"center"
      },
    });

     

     

     

     

     

     

     

         

     

     

     

     

     

     

     

     

     

     

     

     

Designed by Tistory.