[앱개발 종합반] 2주 5일차 개발일지(2주 6-7강, 숙제)


📱TIL App.205

앱 & 자바스크립트

1. 모듈(module)과 반복문

1) 모듈 시스템(module system)

모듈이란(1주차 복습), 자바스크립트 안에서 만든 어떠한 함수나 파일을 외부에서 쓸 수 있도록 하는 시스템으로, importexport 키워드가 사용된다.

export default function App() {
  return (
    ...
)};

앱 개발에서는, App.js 파일의 함수 부분에서 export default 키워드를 볼 수 있었다. export default 키워드를 이용하면, App 함수가 그린 화면을 Expo 자체에서 가져가서(export) React Native가 최종적인 화면을 그릴(렌더링할) 수 있게 된다. 앞으로 만들 많은 페이지들의 화면을 그리는 App 함수들도 모두 export default 키워드를 사용할 예정이다.


2) 모듈 시스템으로 JSON 데이터 불러오기

App.js 파일과 같은 폴더에 data.json 폴더를 만들고 딕셔너리(Object)와 리스트(Array)의 복합 구조의 JSON 데이터를 입력했다. 이렇게 준비된 데이터는 불러온 파일에서 사용이 가능하다.


3) 반복문을 통해 JSON 데이터 사용하기

① JSON 데이터 불러오기

import data from './data.json'

App.js 파일 상단에 위 코드를 입력하면 파일로 JSON 데이터 파일을 불러와 사용할 수 있다. ./는 같은 폴더 내의 파일’이라는 뜻이다. 폴더 밖의 파일에 접근할 때는 ../을 사용한다.

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


② map 반복문으로 JSON 데이터 사용하기

import data from './data.json';

export default function App() {
  let tip = data.tip;

  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>)
  })
}

App 함수 안에 data.tip의 변수를 설정해서 데이터를 가져온다. 실제로 사용할 값은 tip이라는 key에 들어있는 리스트(Array) 값이기 때문에, 연결 연산자를 사용해 값을 갖고 온다. Array에 map method를 사용하면 반복문을 사용할 수 있다.



위 코드의 return을 보면, map으로 반복문이 실행될 때마다 함수가 JSX 문법을 반환하며 화면을 그린다. map의 parameter에서 각 Array의 element를 content라는 변수로 설정했기 때문에, {content.key이름}의 형식으로 각 element의 값을 불러올 수 있다.

JSX 문법 안에서 자바스크립트 변수를 쓰려면 중괄호({})로 감싸야 한다.



return에는 전체 JSX 태그를 감싸는 최상위 태그인 <View> 태그가 있고, key 속성이 있다. 반복문을 사용할 때에는 각 element의 index 값이 고유하므로, 이 값을 mapparameter로 넘겨서 key값으로 이용할 수 있다.

React Native에서 반복문을 돌려서 여러 JSX 문법을 화면에 보일 때, 최상위 태그는 항상 key 속성을 가져야 하며 그 값은 고유해야 한다.


2. {} 표현식과 조건문

1) {} 표현식

export default function App() {
  let todayWeather = 10 + 17;
  let todayCondition = "흐림";
  
  return (
    <Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text>
  )
}

위 코드와 같이, todayWeathertodayCondition라는 자바스크립트 변수를 활용하기 위해 {}를 사용했다. HTML에서 template literal로 ${} 기호를 쓴 것과 비슷한 느낌. {} 표현식을 사용하면 JSX 문법 안에서 자바스크립트의 연산과 변수 사용을 쉽게 할 수 있다.


2) {} 표현식 안에서의 조건문, 삼항 연산자(ternary operator)

조건에 따라 화면에 다른 모습을 보이거나 연산을 적용하고 싶다면 {} 표현식 안에서 조건문을 사용할 수 있다.

조건이 ‘A 아니면 B’와 같이 선택사항이 두 가지밖에 없을 때, if else 조건문 대신 삼항 연산자(ternary operator)를 사용할 수 있다. 기본 문법은 아래와 같다.

let result = condition ? exprIfTrue : exprIfFalse

삼항 연산자는 총 세 개의 parameter - 조건, 참일 경우의 표현식, 거짓일 경우의 표현식 - 을 받는다. result 변수는 조건문의 결과를 할당하는 변수로, 조건이 참일 경우 ? 뒤의 값이, 조건이 거짓일 경우 : 뒤의 값이 할당된다.


<View style={styles.cardContainer}>
  { 
    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>

const styles = StyleSheet.create({
  cardEven:{
    flex:1,
    flexDirection:"row",
    margin:10,
    backgroundColor:"#FFFED7",
    borderRadius:20,
    borderBottomWidth:0.5,
    borderBottomColor:"#eee",
    paddingBottom:10
  },
  cardOdd:{
    flex:1,
    flexDirection:"row",
    margin:10,
    borderBottomWidth:0.5,
    borderBottomColor:"#eee",
    paddingBottom:10
  }
)}

위의 예시 코드를 보면, 리스트 영역에서 return 키워드 뒤에 홀수와 짝수 카드를 구분하는 조건 i % 2 == 0을 넣어 짝수 index를 가진 카드에만 배경색이 들어갈 수 있게 했다. 변수를 설정하지 않고, 조건에 따른 값이 바로 return으로 내보내질 수 있도록 한 것이다.


3. 2주차 숙제

1) 페이지 여러 개 만들기

sparta-study 폴더 안에 pages 폴더를 만들고, 그 안에 MainPage.jsAboutPage.js 파일을 생성한다. App.js 파일 코드를 모두 MainPage.js 파일로 옮겨온 후, 파일 최상단에서 이미지와 JSON 데이터를 import할 때의 경로 주소를 바꿔 준다: 같은 폴더 내(./) -> 다른 폴더(../). 또한 파일 이름과 함수 이름은 항상 같아야 하기 때문에, App이라는 함수 이름도 MainPage로 바꿔준다.

다음으로, App.js 파일의 모든 코드를 지우고, 아래와 같은 importexport 코드를 입력한다.

import React from 'react'
import MainPage from './pages/MainPage'
import AboutPage from './pages/AboutPage'

export default function App() {
  return (<MainPage/>)
}

React Native에서 함수는 return 키워드가 있어야 화면을 반환한다. return이 반환하는 화면, 즉 parameter로는 다른 JSX 태그를 가져올 필요 없이 MainPage 함수를 그대로 태그로 가져오면 된다. 실제 App.js 파일을 실행시키면 화면이 그대로 뜨는데, 이는 MainPage 함수가 그린 그림 파일을 그대로 가져온 것이라 생각하면 된다.


import React from 'react'
import MainPage from './pages/MainPage'
import AboutPage from './pages/AboutPage'

export default function App() {
  //return (<MainPage/>)
  return (<AboutPage/>)
}

위 코드처럼 return <MainPage/> 코드를 주석 처리하고, return <AboutPage/> 코드를 입력하면 AboutPage.js 파일이 화면에 뜨는 것을 볼 수 있다.

이처럼 각각의 페이지를 만드는 파일은 많아도, 결국 App.js가 화면을 최종적으로 그리는 파일이며 return 키워드에 어떠한 값을 반환하냐에 따라 그려지는 화면이 달라진다. 페이지들 간 이동은 3주차 때 더 자세히 다룰 예정이다.


2) 예시 이미지 / 나의 결과 이미지


3) 예시 이미지 보고 스스로 해보기

import React from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native';
import about from '../assets/about.png'

export default function AboutPage() {
  console.disableYellowBox = true;
  return (
    <View style={styles.container}>
      <View style={styles.titleContainer}>
        <Text style={styles.titleText}>스파르타코딩 앱개발반에{'\n'}오신 것을 환영합니다.</Text>
      </View>
      <View style={styles.innerContainer}>
        <Image
          source={about}
          resizeMode={"cover"}
          style={styles.imageStyle}
        />
        <Text style={styles.subText}>많은 내용을{'\n'}간결하게 담아내려{'\n'}노력했습니다!</Text>
        <Text style={styles.descText}> 완주하셔서{'\n'}여러분 것으로{'\n'}만들어가시길 바랍니다.</Text>
        <TouchableOpacity style={styles.button}><Text style={styles.buttonText}>Instagram</Text></TouchableOpacity>
      </View>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    backgroundColor: "#001064"
  },
  titleContainer: {
    flex: 2,
    justifyContent: "center",
    alignItems: "center"
  },
  titleText: {
    color: "#fff",
    fontSize: 30,
    fontWeight: "bold",
    textAlign: "center",
    marginTop: 50
  },
  innerContainer: {
    flex: 5,
    width: "82%",
    borderRadius: 30,
    marginBottom: 50,
    backgroundColor: "#fff",
    justifyContent: "center",
    alignItems: "center"
  },
  imageStyle: {
    width: 150,
    height: 150,
    borderRadius: 30,
    marginBottom: 10
  },
  subText: {
    fontSize: 21,
    fontWeight: "bold",
    textAlign: "center",
    marginVertical: 15
  },
  descText: {
    fontWeight: "bold",
    fontSize: 16,
    textAlign: "center",
    marginVertical: 10
  },
  button: {
    width: 120,
    height: 50,
    backgroundColor: "orange",
    borderRadius: 15,
    justifyContent: "center",
    alignItems: "center",
    marginTop: 15
  },
  buttonText: {
    color: "white",
    fontWeight: "600"
  }
})


4) 🤔 Qna


☑️ 텍스트를 화면 가로 방향으로 정렬하기 위해 justifyContent 속성값을 center로 줬는데 아무 일도 일어나지 않는다.

✅ 앱 개발에서 React Native의 flexDirection default 값은 column, 즉 상하 방향이다. flexDirection은 주축을 설정하므로, 기본값에서 주축은 상하 방향, 교차축은 좌우 방향이다. justifyContent 속성은 주축 방향 정렬, alignItems는 교차축 방향 정렬이므로 좌우 방향(교차축) 정렬을 위해서는 alignItems 속성값을 이용해야 한다.



justifyContentalignItems는 글상자 자체의 정렬에 대한 속성이라면, textAlign은 글상자 안에서의 텍스트 정렬에 대한 속성이다.



☑️ 텍스트 내에서 가독성을 위해 줄바꿈을 하고 싶은데 어떻게 해야 할까?

<Text> 태그 안 텍스트에 {'\n'}을 입력하면 Enter 키를 적용한 것처럼 줄바꿈이 된다. 또는 template literal 형식을 사용하면 {``} 내의 줄바꿈이 자동 적용된다.


5) 해설 코드

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


export default function AboutPage(){
    const aboutImage = "https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2FaboutImage.png?alt=media&token=13e1c4f6-b802-4975-9773-e305fc7475c4"
  return (
    <View style={styles.container}>
      <Text style={styles.title}>HI! 스파르타코딩 앱개발 반에 오신것을 환영합니다</Text>
      
      <View style={styles.textContainer}>
        <Image style={styles.aboutImage} source={{uri:aboutImage}} resizeMode={"cover"}/>
        <Text style={styles.desc01}>많은 내용을 간결하게 담아내려 노력했습니다!</Text>
        <Text style={styles.desc02}> 완주 하셔서  여러분것으로 만들어가시길 바랍니다</Text>
        <TouchableOpacity style={styles.button}>
          <Text style={styles.buttonText}>여러분의 인스타계정</Text>
        </TouchableOpacity>
      </View>
  </View>)
}

const styles = StyleSheet.create({
  container: {
    flex:1,
    backgroundColor:"#1F266A",
    alignItems:"center"
  },
  title: {
    fontSize:30,
    fontWeight:"700",
    color:"#fff",
    paddingLeft:30,
    paddingTop:100,
    paddingRight:30
  },
  textContainer: {
    width:300,
    height:500,
    backgroundColor:"#fff",
    marginTop:50,
    borderRadius:30,
    justifyContent:"center",
    alignItems:"center"
  },
  aboutImage:{
    width:150,
    height:150,
    borderRadius:30
  },
  desc01: {
    textAlign:"center",
    fontSize:20,
    fontWeight:"700",
    paddingLeft:22,
    paddingRight:22
  },
  desc02: {
    textAlign:"center",
    fontSize:15,
    fontWeight:"700",
    padding:22
  },
  button:{
    backgroundColor:"orange",
    padding:20,
    borderRadius:15
  },
  buttonText: {
    color:"#fff",
    fontSize:15,
    fontWeight:"700"
  }
})


Categories:

Updated:

Leave a comment