리액트 네이티브 & Expo

리액트 네이티브

리액트(React) + 네이티브(Native)

리액트는 JS 기반인데 개발하다보면 카카오톡 로그인 등 안드로이드, iOS 각각의 코드를 알아야하는 상황이 생김 → Expo를 이용함

 

Expo

  • 리액트 네이티브 코어 앱 개발 코어 기술을 Expo로 감싸서 JS로만 개발할 수 있는 환경을 구축하도록 도와주는 역할
  • Expo 클라이언트 앱-Expo 서버를 킨다 → QR 코드를 찍어서 개발중인 앱을 확인한다.

개발 환경 준비

  1. Node & NPM-Node.js로 JS 개발 환경 구축-Node.js 설치 시 NPM 자동 설치
  2. -유용한 JS 도구를 가지고 올 때 NPM(Node Package Manager) 사용
  1. Yarn-NPM보다 더 효율적으로 JS 도구를 가져올 수 있는 도구
    💡
    npm install -g yarn * -g : 컴퓨터에 전역적으로 설치한다는 옵션
  2. -NPM을 이용해서 설치
  1. Expo 명령어 도구 설치-Expo 도구 : NPM을 이용해서 설치
  2. 💡
    npm install -g expo-cli
  1. Expo 가입 및 로컬에 Expo 계정 세팅
    • cmd창에서 Expo 서비스 로그인
    💡
    expo login —username 사용자이름
  1. Expo 실행하기
    • 바탕화면에 sparta study 생성
    • VS code에서 Open Folder - sparta study 폴더 선택
    • View - Terminal 클릭해서 터미널 창 열기
    • expo init으로 프로젝트 생성
    💡
    expo init sparta-honeytip-yewon
    *이때 오류나는 경우 터미널을 Powershell이 아닌 Command Prompt로 변경
    • 개발하기 위해 폴더 이동
    💡
    cd sparta-honeytip-yewon
    • expo 시작
    💡
    expo start
    *Expo 클라이언트 앱으로 개발을 진행할 것(같은 와이파이 상에서 연결이 안되는 문제 : LAN → Tunnel로 변경 후 새 QR 코드 인식해서 해결)
  2. → 구글 플레이스토어에서 앱 다운 후 QR 인식 (동일한 WIFI 연결)
  1. Expo 파일 간단 설명
    • assets 폴더 : 이미지 폴더
    • node_modules : 도구 폴더
    • App.js : 화면이 되는 파일
    • app.json : 앱 배포 시 설명서

React Native 태그, Styles, Flex

App.js

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

//메인화면
export default function App() {
	//화면 반환
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

//화면을 꾸밈
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
  • <View>, <Text> 등 꺽쇠를 이용한 부분 → JSX라고 함 (화면을 그리는 문법)
  • <View> </View> 처럼 태그로 화면의 한 영역을 구성할 때 → 엘리먼트라고 함

 

  • 사용할 태그는 import를 이용해서 가져온다.
import { StyleSheet, Text, View } from 'react-native';
  • 모든 엘리먼트는 감싸는 최상위 엘리먼트가 있어야 한다.
  • return을 이용해 렌더링할 때 항상 소괄호로 감싸져있어야 한다.
export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

 

View 태그

  • <View> : 화면의 영역을 잡아주는 엘리먼트

 

Text 태그

  • <Text> : 앱에 글을 작성하기 위해 사용하는 엘리먼트
  • 문자는 반드시 Text 태그 안에 써야함!

 

ScrollView 태그

import React from 'react';
import { StyleSheet, Text, View, ScrollView } from 'react-native';

export default function App() {
  return (
    <ScrollView style={styles.container}>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
    </ScrollView>
  );
}
  • <ScrollView> : 감싼 엘리먼트 스크롤이 가능해진다.

 

Button 태그

import React from 'react';
import { StyleSheet, Text, View, Button, Alert } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>아래 버튼을 눌러주세요</Text>
        <Button 
          style={styles.buttonStyle} 
          title="버튼입니다 "
          color="#f194ff" 
          onPress={function(){
            Alert.alert('팝업 알람입니다!!')
          }}
        />
        <Button 
            style={styles.buttonStyle} 
            title="버튼입니다 "
            color="#FF0000" 
            onPress={()=>{
              Alert.alert('팝업 알람입니다!!')
            }}
          />
          </View>
    </View>
  );
}
  • <Button> : 버튼을 만들 수 있는 엘리먼트
  • title 속성 : 버튼 안에 넣을 문자
  • color 속성 : 버튼 색상
  • onPress 속성 : 버튼 클릭 시 실행할 함수 연결

 

TouchableOpacity

  • <TouchableOpacity> : 버튼과 비슷한 역할을 함, 대신 화면에 영향을 주지 않음
  • 임의의 영역과 디자인에 버튼 기능을 추가할 때 주로 사용할 태그

 

Image 태그

import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
//이렇게 상단에 가져와 사용할 이미지를 불러옵니다
import favicon from "./assets/favicon.png"

export default function App() {
  return (
    <View style={styles.container}>
      <Image 
        source={favicon}
				// 사용설명서에 나와 있는 resizeMode 속성 값을 그대로 넣어 적용합니다
        resizeMode={"repeat"}
        style={styles.imageStyle}
      />
    </View>
  );
}
  • <Image> : 이미지를 넣는 태그
  • import를 통해 assets 폴더의 이미지 파일을 가져온 다음 사용
  • source : import한 이미지
  • resizeMode : 이미지를 보여주는 방식-repeat : 이미지가 반복-그 외 contain, stretch, center
  •  
  • -cover : 이미지가 화면 전체에 꽉 차게 보여줌
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
//이렇게 상단에 가져와 사용할 이미지를 불러옵니다
import favicon from "./assets/favicon.png"

export default function App() {
  return (
    <View style={styles.container}>
			{/*이미지 태그 soruce 부분에 가져온 미지 이름을 넣습니다 */}
      <Image 
        source={{uri:'https://images.unsplash.com/photo-1424819827928-55f0c8497861?fit=crop&w=600&h=600%27'}}
				// 사용설명서에 나와 있는 resizeMode 속성 값을 그대로 넣어 적용합니다
        resizeMode={"cover"}
        style={styles.imageStyle}
      />
    </View>
  );
}
  • 외부 이미지를 가져와서 사용하는 방법
  • source에 uri 지정

*코드가 너무 길면 alt+z를 눌러서 한 화면에 코드가 다 들어오도록 설정

 

Styles

import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>스파르타 코딩클럽!!</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent:"center",
    alignContent:"center"
  },
  textContainer: {
    margin:10,
    padding: 10,
    borderRadius:10,
    borderWidth:2,
    borderColor:"#000",
    borderStyle:"dotted",

  },
  textStyle: {
    color:"red",
    fontSize:20,
    fontWeight:"700",
    textAlign:"center"
  }
});
  • const style : 값의 재할당이 불가능한 style 변수 생성
  • StyleSheet에 딕셔너리를 넘겨줌
  • margin, padding, borderRadius, borderWidth, borderColor, borderStyle
  • color, fontSize, fontWeight, textAlign

 

Flex

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <View style={styles.containerOne}>

      </View>
      <View style={styles.containerTwo}>
        <View style={styles.innerOne}>
         
        </View>
        <View style={styles.innerTwo}>
          <Text>!!컨텐츠!!</Text>
        </View>

      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex:1
  },
  containerOne: {
    flex:1,
    backgroundColor:"red"
  },
  containerTwo:{
    flex:2,
    flexDirection:"row",
    backgroundColor:"yellow"
  },
  innerOne: {
    flex:1,
    backgroundColor:"blue"
  },
  innerTwo: {
    flex:4,
    flexDirection:"row",
    justifyContent:"flex-end",
    backgroundColor:"orange"
  }
});
  • flex : 레이아웃 비율 (상대적)
  • flexDirection : flex 방향 지정
  • 상하 : column (기본) / 좌우 : row
  • justifyContent : flexDirection에 따라 정렬
  • flex-start, flex-end, center를 가장 자주 씀, 그 외 space-around, space-between, space-evenly
  • alignItems : flexDirection 방향과 반대로 정렬 (flex 영역 내에서 사용 가능)
  • alignSelf : flex 없어도 가능
  • numberOfLines={3} : 텍스트 잘리는 부분 ... 으로 대체

 

앱&자바스크립트 모듈, 반복문

  • App.js : 모듈 시스템에 의해서 내보내짐
  • 앞으로 여러 파일들을 만들 때 export default function을 이용해서 내보낼 것
export default function App() {...}

 

  • data.json 파일 : 딕셔너리 + 리스트 구조
  • App.js에 data.json 파일 import
import data from './data.json'

 

  • data.tip으로 json 파일의 tip 가져오기
let tip = data.tip;
let todayWeather = 10 + 17;
let todayCondition = "흐림"

 

  • App.js JSX 문법 안에서 map을 이용한 반복문
  • 반복문을 돌릴 때 가장 최상위 태그에는 key값이 주어져야 한다. (key는 유니크함)
<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>

 

  • JSX 안에서 중괄호 { }를 쓰면 그 안에서 자바스크립트 문법을 쓸 수 있다!
<Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text>

 

삼항연산자

let result = 조건 ? 참일때 : 거짓일때
let result = 10>2 : '참' : '거짓'

tip.map((content,i)={
	return i%2==0 ? (<View>...</View>) : (<View>...</View>)
})

 

숙제

어바웃 페이지 만들기

Uploaded by Notion2Tistory v1.1.0


지난 주 1주차 수업에서는 자바스크립트의 기초를 배웠고

이번 주에는 본격적으로 리액트를 이용하여 앱을 만들어보는 시간을 가졌다.

Node.js, NPM, Expo 등 미리 세팅해야할 사항이 많아보여서 처음에는 약간 겁을 먹었으나

세팅을 무사히 마친 후 VS Code에서 JSX의 다양한 태그들을 활용하며 레이아웃을 구성하니 흥미로웠다.

 

태그를 사용하여 레이아웃을 구성하는 것은 안드로이드 스튜디오와 비슷해서 낯설지 않았고

이미 css를 공부했었기 때문에 StyleSheet를 활용하여 꾸미는 것도 익숙했다.

아직 flex 개념이 헷갈리는데 추가적으로 공부를 해서 익혀야겠다. (안드로이드 스튜디오 layout_gravity가 생각나는 속성이었다.)

 

Expo 클라이언트 앱을 이용하여 실시간으로 내가 수정한 코드가 반영된 모습을 볼 수 있는 점이 정말 편리했다.

안드로이드 스튜디오 같은 경우에는 미리보기 창으로 레이아웃을 얼추 볼 수 있긴 하나

제대로 실행시키려면 빌드를 해야하기 때문에 시간이 걸려서 은근 번거로운데

Expo는 ctrl+s 할 때마다 바로 핸드폰 화면에 수정 사항이 반영되기 때문에 앞으로 개발하면서 시간 단축이 많이 될 것 같다는 생각이 들었다.

또한 오류 메세지도 자세하게 나오는 편이라 어느 부분에서 오류가 났는지 확인하기 쉬웠다.

 

이번 주 강의를 열심히 수강한 결과, 마지막에 첨부한 이미지처럼 숙제로 어바웃 페이지를 구현할 수 있었다.

오늘 막 리액트에 입문한 것 치고 많은 것을 배우고 그것을 응용할 수 있는 능력을 가지게 된 것 같아 좋았다!

+ Recent posts