<스파르타 App개발> 2주차 개발일지 - React Native, Expo, App frontend(Js, JSX), NPM, Yarn, Node.js...
굉장히 흥미로운 2주차 수업이었다.
저번주까지는 익숙했던 문법들에 대해서 배웠다면,
이번주에는 앱의 화면을 그리는 App Frontend에 관한 기초적인 것들을 배웠다.
1. 개괄 - React Native, JSX, Expo, node.js, npm, yarn...
복잡한 이름들이 많지만, 알고 보면 별 거 없다.
React Native란, 1주차에 다룬 Cross-platform 앱 개발에 쓰이는 JavaScript library이다.
쉽게 말해
- Android와 iOS에서 모두 사용할 수 있는 어플리케이션을 만들 수 있는,
- JavaScript로 된
- 도구모음 꾸러미
이다.
Expo란, React Native를 쉽게 사용할 수 있게 만들어 주는 도구인데
세가지 측면에서 그러하다.
- React Native를 사용하더라도, 안드로이드와 iOS 코드를 건드려야 하는 상황이 있는데 이를 피하게 해준다.
- 개발 중인 앱을 쉽게 확인할 수 있게 해준다.
- 앱 개발 프로젝트 생성, 실행, 빌드 관리 등을 편리하게 해준다.
Node.js란, 능력자들이 미리 만들어 놓은 JavaScript 선물 상자이다.
NPM이란 이러한 선물 상자에서 필요한 도구들을 쉽게 꺼낼 수 있게 해주는 도구이다.
Yarn이란 NPM보다 빠르고 가볍게 Js 패키지 관리를 해줄 수 있게 한다.
정리하면, 다음 그림과 같다.
2. Frontend 개발 준비
1. Node.js와 NPM을 컴퓨터에 설치한다. (Js 꾸러미와 꾸러미에서 꺼낼 도구를 설치!)
2. NPM을 이용하여 Yarn을 설치한다. (더 쉽게 꺼낼 수 있는 도구를 설치!)
커맨드 창에
npm install -g yarn
yarn -v //버젼 확인
3. Expo 명령어 도구를 설치한다. (Expo-cli, 컴퓨터에서 Expo를 사용할 수 있고, 즉 어플리케이션 개발 프로젝트의 생성, 실행 등을 쉽게 만들어준다.)
커맨드 창에
npm install -g expo-cli
4. Expo에 가입하고, 컴퓨터와 계정을 연결한다.
expo login
// 이메일(아이디), 패스워드 입력하면 성공
5. VS code로 프로젝트 폴더를 실행한 후, 터미널에서 Expo를 이용하여 새로운 프로젝트를 생성한다.
expo init sparta-myhoneytip-nogrowth
// sparta-myhoneytip-nogrowth 라는 이름의 expo 프로젝트를 생성한다.
이때 터미널에서 Expo 앱 유형을 물어보는데, 이때 blank를 선택하면
프로젝트가 생성되며 다음과 같은 파일 구조가 기존 프로젝트 폴더 내에 생성된다.
6. Expo 프로젝트를 실행한다.
주의할 점으로는 sparta-study가 아닌 그 하위폴더인 sparta-myhoneytip-어쩌구에 expo 프로젝트가 생성되었으므로
터미널에서 경로를 해당 폴더로 이동한 후 expo를 실행한다.
cd sparta-myhoneytip-nogrowth
expo start
이제 expo 서버가 실행되며, 내가 프로젝트에 만든 파일들을 웹이나 안드로이드 에뮬레이터(가상머신)로 실시간으로 확인할 수 있게 되었다!!
7. 안드로이드 에뮬레이터 만들기
웹으로 보는데에도 무리는 없고,
스마트폰에 Expo 어플을 깔면 앱의 현재 상태를 볼 수 있으나, 이러면 컴퓨터와 스마트폰을 번갈아 봐야해서 번거로우므로, 내 컴퓨터에 가상 안드로이드 머신을 만들어서 이와 연동하는 방법이 있다.
이 때 android studio라는 프로그램을 사용한다.
이제 준비가 끝났다!
3. React Native 프로젝트의 구조
Expo project의 구성은 다음과 같다.
여러 파일들이 자동으로 만들어 지는데, 기본적으로 javascript 파일인 App.js가 앱 화면을 그려주게 된다.
즉 App.js 파일에 자바스크립트로 React native를 이용하여 코딩을 하면 된다.
React Native는 언급했듯 Js library이므로 import를 해야 하며, 기본적인 App.js 파일의 구성은 다음과 같다.
import React from "react";
import { StyleSheet, Text, View } from "react-native";
export default function App() {
return (
<View style={styles.container}
<Text> App.js의 기본 구성 </Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#fff"
}
});
★중요★
1. Js 라이브러리인 React를 import하고
2. React-native에서 필요한 element들을 import한다.
3. export default 를 이용하여 App()이라는 함수를 내보내주는데
--> 이를 이용하여 expo가 app의 frontend를 그려낸다.
4. App() 함수가 return하는 구문은 ( ) 소괄호 안에 들어가며,
이는 JSX 문법으로 작성한다.
5. react native의 StyleSheet을 이용하여, styles에 스타일 요소들을 정의하여 이를 JSX에서 사용한다.
그렇다면 JSX란 무엇일까?
4. JSX
JSX란 JavaScript XML로서 Js에 XML을 추가하여 확장한 문법이다.
즉 HTML과 비슷한 구조를 갖는 태그 기반 언어이다.
따라서 태그의 여러 속성들을 이용해 태그 요소들을 조작한다.
JSX의 모양은 다음과 같다.
import React from "react";
import { View, Text, StyleSheet } from "react-native";
export default function App() {
return (
<View style={styles.container}>
<Text style={{fontSize=10, fontWeight:'bold'}} 안녕하세요? </Text>
</View>
)}
App() 함수가 반환하는 return 내부에 있는 요소들이 JSX로 작성된 것이다.
HTML과 굉장히 비슷한 구조를 가지고 있는 것을 알 수 있고
style 속성을 이용하고 있는 것도 볼 수 있다.
이런 View, Text 등의 태그들은 코드의 윗부분에서 볼 수 있듯 react-native에서 가져온 것들이기 때문에
어떤 속성을 사용할 수 있는 지는 다음의 React native documentation(공식문서)를 활용하면 찾아볼 수 있다.
React Native · Learn once, write anywhere
A framework for building native apps using React
reactnative.dev
JSX의 기본 원칙들
1. 모든 태그는 가져와서 사용한다.
HTML과 달리 기본 태그들이 정의되어 있지 않기 때문에, 어딘가에서 태그를 가져와서 사용해야 하며 우리는 이를 React native에서 가져와서 사용한다.
2. 모든 태그는 열고 닫는 태그와 자체적으로 닫는 태그를 구분해서 사용한다.
이는 공식문서에서 알아보면 된다.
3. 모든 태그는 감싸는 엘리먼트가 있어야 한다. 보통 <View>태그를 이용하여 전체를 감싸준다.
4. return에 의한 렌더링을 위해서는 () 소괄호로 감싸야 한다.
5. 주석에서의 차이점
return 문 밖은 JS 방식의 주석을 따르며 (// 주석)
return 문 안에서는 JSX 방식의 주석을 따라야 한다. ({/* 주석 */})
기본적인 태그들
React native는 여러 태그들을 제공하는데, 모든 태그들을 알아볼 필요도 없거니와 다 알 수도 없어 넘어간다.
기본적으로 다음 태그들을 자주 사용한다.
<View> : 영역(layout)을 잡아주는 엘리먼트
<Text>
<ScrollView> : 화면을 넘어가는 영역의 경우 ScrollView 엘리먼트로 감싸면 스크롤이 가능하다.
<Button> : 버튼을 만드는 태그이며, HTML의 onclick과 비슷한 onPress 속성을 자주 사용한다.
하지만 style 적용이 조금 까다로워서 TouchableOpacity 태그를 많이 사용한다.
<TouchableOpacity/> :
<button> 태그의 경우 본인 자체의 영역을 갖기 때문에 스타일에 매번 신경을 써야하는 번거로움이 있어서
TouchableOpacity 태그를 사용하면 화면에 크게 영향을 주지 않는 버튼을 만들 수 있어서 편리하다.
<Image> : 이미지를 표시하는 태그
HTML과 마찬가지로 프로젝트 폴더 내에서나, 외부에서 이미지를 가져올 수 있다.
1) 프로젝트 내의 assets 폴더에서 이미지를 가져오는 경우
import Image from 'react-native';
import favicon from "./assests/favicon.png"
<Image
source={favicon}
resizeMode={"repeat"}
style={styles.imageStyle}
/>
2) 외부 이미지를 가져오는 경우
import Image from 'react-native';
<Image
source={{uri:"외부 이미지 주소"}}
resizeMode={"repeat"}
style={styles.imageStyle}
/>
나머지 태그들이나, 각 태그의 자세한 속성들은 document를 참조하자.
5. Styles과 StyleSheet - 요소들을 꾸며보자.
CSS와 크게 다를 것이 없어 넘어간다.
6. 앱 layout의 구성 : Flex, justyfyContent, alignItems
Flex는 들어봤던 개념인 (줄 알았다.)
https://nogrowth.tistory.com/49
CSS #3. flex box, grid
반응형 웹을 만들기 위해 유용한 또한 웹페이지의 modulation을 쉽게 하고 관리하기 편하고, 디자인에도 도움을 주는 layout들에 대해 간단히 정리하고 가자. Flex box layout 기본적으로 주축에서 항목
nogrowth.tistory.com
기존 CSS를 공부하면서 페이지 레이아웃에 대해 고민하면서 정리한 글인데
CSS에서의 flex box와 StyleSheet의 flex는 약간 다르다.
flex는 영역을 나눠주는 개념으로, 상위태그가 가지고 있는 영역을 자식태그들끼리 땅따먹기한다고 생각하면 편하다.
<부모Tag style={styles.box}>
<자식Tag1 style={styles.innerbox1}></>
<자식Tag2 style={styles.innerbox2}></>
</>
const styles = StyleSheet.create({
box: {
flex: 1
},
innerbox1: {
flex: 1
},
innerbox2: {
flex: 2
}
})
위와 같이 설정하면
맨 상위 태그는 flex:1 이므로 화면 전체를 영역으로 갖는다.
이때 2개의 자식 태그들은 각각 flex:1, flex:2를 가지므로
각각 1:2 비율로 영역을 나눠가져가게 된다.
이때 나눠가져가는 방향은
부모태그의 flexDirection에 따라 달라지고,
기본적으로는 flexDirection 속성 'column'이기 때문에 이 위와 같이 세로 방향으로 나눠지며
부모 요소의 flexDirection을 'row'로 설정하면 세로 방향으로 나눠진다.
Flex와 많이 사용하는 속성들도 잠깐 알아보자.
justifyContent
justify는 코딩에서는 가로줄(행)을 맞춘다는 의미로 많이 쓰인다.
justifyContent는 해당 영역의 flexDirection과 동일한 방향으로 정렬한다는 속성으로
Direction이 column일 경우 상하 정렬, row일 경우 좌우 정렬을 뜻하며
flex-start, center, flex-end, space-between, space-around 값을 가질 수 있다.
alignItems
alignItems는 반대로 flex Direction과 수직한 방향으로 정렬하는 속성이다.
즉, Direction: 'column'에서는 좌우 정렬, 'row'에서는 상하 정렬을 뜻하며
flex-start, center, flex-end, stretch 값을 가질 수 있다.
7. JS 문법의 적용 - 모듈, 반복문, {}표현식, 조건문
화면을 그릴 때 배열 뿐 아니라, JS의 여러 문법들을 사용해야 할 일이 많으며
대표적으로 반복문, 조건문 등이 있다.
1) 외부 array 데이터를 가져와서 화면에 뿌려줘야 하는 경우 (import와 반복문의 사용)
전주에 배웠던 map 함수를 복습하면서 살펴보자.
json 형태의 데이터를 가져와서 화면에 그려준다고 생각해보자.
왼쪽의 data.json 에서 데이터를 받아와서 오른쪽처럼 앱에 뿌려줘야 하는 상황이다.
모든 태그를 일일히 손으로 작성한다는 것은 코딩의 의미가 없다.
다음과 같이 데이터를 불러와서 반복문을 사용해줄 수 있다.
import React from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';
import data from './data.json';
export default function App() {
let tip = data.tip;
let todayWeather = 10 + 17;
let todayCondition = "흐림"
import 구문으로 data에 data.json 파일을 받아왔고,
tip 변수를 선언하여 data 내부의 tip 리스트를 저장했다.
<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>
tip 변수에 map 메서드를 이용하여 반복문을 쉽게 사용했다.
복습삼아 살펴보면,
다음과 같이 array에 map 메서드를 사용하고 parameter들을 두개 넣어주면, 앞에 value가, 뒤에 index가 할당되어 반복문이 돌아간다.
화살표 함수 또한 복습해보면,
tip.map( ) 안에 뭔가를 돌리는데
tip의 value를 content, index를 i에 할당하여 반복문을 돌리면서
화살표 함수로 정의된 함수는
return ( ) 소괄호 내부의 내용을 반환하며
이때 주의할 점은
- 함수 내의 최상위 태그에 key 속성을 이용하여 {i}, 즉 index를 할당해 줘야 한다는 점
- 그리고 tip.map 함수를 전체 { } 중괄호를 이용하여 묶어줘야 한다는 점이다.
2) 조건에 따라 모양을 달리해줘야 하는 경우 (조건문, 삼항 연산자의 사용)
마찬가지로 JS의 if~ else~ 조건문 또한 { } 안에 넣어서 JSX에 사용할 수 있다.
이렇게만 하면 너무 뻔하기 때문에 새로운 JS 문법을 하나 강의에서 소개하였다.
삼항 연산자
삼항 연산자란 조건이 두개 뿐일 때 조건문을 간결하게 쓰는 형태이다.
let result = 10 > 2 ? "참" : "거짓"
(기본 모습)
let result = 조건 ? 참일 때 : 거짓 일때
(예제)
let result = 10 == 9 ? true : false // result <-- false 값 할당
let result = 10 !== 9 ? true : false // result <-- true 값 할당
let reuslt = 99 > 10 ? true : false // result <-- true 값 할당
위와 같이 간결하게 표현할 수 있다.
이를 JSX에 적용해보면,
{
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>)
})
}
위와 같이 map 메서드를 시행함에 있어
i에 따라 i가 짝수/홀수인 경우 style을 달리하기 위해
{ } 내부에 조건문을 넣어주었다.
그 결과 다음과 같이 홀수번째 카드에만 다른 배경색이 적용되었다.
8. 컴포넌트 / 페이지화
지금까지 우리는
App.js 파일에서 App()이라는 function을 정의하였고, 해당 함수가 반환하는 값을
export default를 이용하여 expo로 내보내서 렌더링하였고 그 결과는 위와 같다.
하지만 어플리케이션에는 페이지가 여러개 존재하기 때문에,
각 페이지를 따로 만들어두고, App.js 파일에서는 이를 불러오는 형태로 진행하게 된다.
예를 들어,
위에 만든 페이지를 MainPage
로딩창에 뜰 페이지를 AboutPage라고 할 때
프로젝트에 pages 폴더를 생성한 후, MainPage.js 파일과 AboutPage.js 파일을 각각 만들고
각 파일에서 MainPage(), AboutPage() 함수를 정의하여 export해둔 후
App.js 파일에서 이들을 import하는 방식을 택하게 된다.
import React from 'react'
import MainPage from './pages/MainPage';
import AboutPage from './pages/AboutPage';
export default function App(){
return (<MainPage/>)
// 필요에 따라 return (<AboutPage/>)
}
이런 식으로 여러 page들을 어플리케이션에 적용할 수 있다.
2주차를 마치며..
웹개발 종합반때부터 포함하여 한주간 배운 내용이 가장 많고 재미있었던 것 같다.
특히, emulator를 이용하여 휴대폰 화면에 내가 구성하는 application이 바로바로 반영되는 부분이 흥미로웠다.
다음주차가 기대되고 이제는 내가 어플리케이션을 만들 수 있는 도구를 얻었다는 사실에 무척 기분이 좋다.
'코딩 > 스파르타코딩클럽' 카테고리의 다른 글
<스파르타 App개발> 3주차 개발일지 (0) | 2022.08.12 |
---|---|
<스파르타 App개발> 2.9주차 개발일지 - 복습 : JS 함수 선언, 구조분해할당, map (0) | 2022.08.11 |
<스파르타 App개발> 1주차 개발일지 (0) | 2022.07.25 |
<스파르타 웹개발> 5주차 개발일지 (完) (0) | 2022.07.08 |
<스파르타 웹개발> 4주차 개발일지 (0) | 2022.07.02 |