DEVELOP
article thumbnail

스파르타코딩클럽 - [왕초보] 나만의 수익성 앱, 앱개발 종합반 강의를 듣고 내용을 정리한 게시글입니다.

 

스파르타코딩클럽

5주 완성! 코딩을 전혀 모르는 비개발자 대상의 웹개발 강의

spartacodingclub.kr


JSX 

JSX

: 리액트 네이티브 앱 개발에서 구역(레이아웃)을 잡는 문법 언어 

  • 용도에 맞는 태그를 정해놓았기 때문에, 필요한 태그를 그때그때 꺼내서 사용하면 된다.
    • 화면의 구역을 잡을 때는 <Vies> 태그
    • 글자를 쓸 때는 <Text> 태그를 사용 

▼ JSX 문법 예시

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

<View>
  <Text>Hello, I am {props.name}!</Text>
</View>

앱 개발 준비 - 리엑트 네이티브 & Expo 설치 및 실행

React Native 

: 자바스크립트 언어 하나로 안드로이드 앱과 iOS앱 두가지 모두 만들어주는 라이브러리

  • 하지만, 리엑트 네이티브로만 앱 개발을 하면, 특정 상황에서는 안드로이드, iOS 각각의 폴더에 들어가 직접 코드를 만져야 하는 상황이 발생함 
    -> 하나의 언어로 앱을 만들 수 있다는 취지에서 벗어나게 됨 ( yarn & expo 필요 ) 

 

yarn 

: npm보다 가볍고 빠르게 자바스크립트 패키지를 관리할 수 있게 해주는 자바스크립트 패키지 매니저 툴

  • yarn 설치 위해서는 npm 설치해야 함 
  • yarn 설치하기 명령어 
    $ npm install -g yarn

Expo 

: 안드로이드 & iOS 코드를 건드려야 하는 대부분의 상황들을 안건드려도 되게끔 도와주는 프레임워크이자 플랫폼 

  • 개발 중인 앱 테스트를 위한 Expo Go 앱을 제공함
  • Expo 명령어를 통해서 Expo Go 앱에서 개발 중인 앱을 그때그때 눈으로 확인 할 수 있음  
  • Expo를 설치 및 사용한다 => 프로젝트 생성 / 실행 / 빌드 등등의 여러 기능들을 사용할 수 있다
  • Expo 설치하기 명령어 ( 관리자 권한으로 cmd 실행 )
    $ npm install -g expo-cli

 

Expo 사용하기

  1. Expo 가입 필요  https://expo.dev/ 
  2. 로컬에 Expo 계정 세팅하기
    $ expo login 
    아이디(or 이메일), 패스워드 입력하기
  3. vscode에서 프로젝트 폴더 열고 새 터미널에서 expo 프로젝트 생성하기 
    $ expo init myapp
    - blank 선택
  4. 프로젝트 폴더 안으로 들어가기
    $ cd myapp
  5. expo 서버 실행하기
    $ expo start
  6. QR코드를 스마트폰으로 인식하기 ( 같은 네트워크에 연결되어 있어야 함 )
  7. expo 서버 종료하기
    컨트롤 + c / command + c

로컬에 Expo 계정 세팅

 

Expo 프로젝트 기본 폴더 구조 

  1. assets
    : 앱이 동작되고 서비스되는데에 기본적으로 가지고 있는 이미지 및 아이콘 파일들을 담는 폴더
  2. node_modules
    :  라이브러리들이 저장되는 장소
  3. App.js
    :  앱이 시작되는 출발선이자 진입점 
       웹에서의 index.html 또는 main.html 같은 메인 파일 
  4. App.json
    : 앱의 이름, 앱의 출시 버전, 앱이 휴대폰에 설치될 때 보여질 아이콘, 앱이 켜질 때 보여지는 스플래시 스크린 화면, 안드로이드 또는 IOS 각각의 광고 설정 등 앱이 가지는 기본 정보들을 설정하는 파일

앱 화면 만들기 - JSX 문법 

JSX 기본 문법

  1. 모든 태그는 가져와서 사용한다.
    import { StyleSheet, Text, View } from 'react-native';
  2. 태그는 항상 닫는 태그와 자체적으로 닫는 태그를 구분해서 사용해야 한다.
  3. 모든 엘리먼트는 감싸는 최상위 엘리먼트가 있어야 한다.
    - 엘리먼트 == 태그 
  4. return에 의해 렌더링 될 땐 항상 소괄호로 감싸져야 한다.
  5. JSX 문법 밖에서의 주석과 안에서의 주석은 다르다.
  return (
		//JSX 밖에서의 주석
    <View style={styles.container}>
			{/*
				JSX 문법 안에서의 주석
			*/}
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );

앱 화면 만들기 - 화면을 구성하는 엘리먼트들

View

: 화면의 영역(레이아웃)을 잡아주는 엘리먼트

<View style={styles.container}></View>

Text

: 앱에 글을 작성하기 위해 반드시 사용해야하는 엘리먼트 

<Text>Hello World!</Text>

ScrollView

: 앱 화면을 벗어나는 영역의 경우에 스크롤로 감싸서 모든 콘텐츠를 볼 수 있게 해주는 엘리먼트 

- 태그 안에 있는 요소들이 스크롤바로 감싸진다.

<ScrollView style={styles.container}></ScrollView>

Button

: 버튼을 추가하는 엘리먼트

- 눌렀을 때 특정 이벤트가 일어나게 하려면 onPress에 함수를 연결해야 한다.

- 원하는 곳에 배치하기가 어렵고, 스타일링 주기가 어렵다.

          <Button
            title="Button"
            onPress={() => alert("안녕하세요!")}
          ></Button>

TouchableOpacity

: 임의의 영역과 디자인에 버튼 기능을 달고 싶을 때 사용하는 엘리먼트

- Button 컴포넌트는 안드로이드와 iOS에서 다르게 보이기 때문에 관리하는데에 어려움이 있다.

- Button을 대체해 주로 사용한다. 

  const customAlert = () => {
    alert("Hello World!");
  };
  
  
  return (
  /* ... /*
            <TouchableOpacity style={styles.container}>
            <Text onPress={customAlert}>TouchableOpacity</Text>
          </TouchableOpacity>

Image

: 이미지를 넣을 수 있는 엘리먼트 

- 이미지를 넣는 방법은 두가지가 있다.

  1. assets 폴더에 있는 이미지를 가져와서 사용하는 방법 (import)
  2. 외부 이미지 링크를 넣어서 사용하는 방법 (url)
import favicon from "./assets/favicon.png";

/* . . . */

        <Image
          source={favicon}
          resizeMode={"center"}
          style={styles.imageStyle}
        />
        <Image
          source={{
            uri: "https://images.unsplash.com/photo-1424819827928-55f0c8497861?fit=crop&w=600&h=600%27",
          }}
          resizeMode={"center"}
          style={styles.imageStyle}
        />

styles 속성

- 태그에 스타일을 주는 방식 또한 리엑트 네이티브에서 제공하는 StyleSheet 기능을 가져와 적용한다.

- 모든 태그에 공통적으로 있는 style 속성에 아래에 만든 객체 키 값을 부여하여 적용한다. 

- margin, padding 등의 속성이 자주 사용된다.

 

flex

: 영역의 레이아웃을 결정한다. 

  1. flex
    : 상대적으로 영역을 차지하는 속성
    - 위치한 곳의 영역은 같은 레벨의 flex 합 비율대로 가져간다. 
  2. flexDirection 
    : 자리 잡은 영역의 방향을 결정하는 속성
    - default값은 column 
    - row / column
  3. justifyContent
    : 영역 안에 있는 콘텐츠의 방향을 결정하는 속성
    - 상위 엘리먼트에 적용을 해야 안에 있는 컨텐츠에 영향이 간다.
    - flex-start / center / flex-end / space-between / space-around 
  4. alignItems
    : flexDirection과 수직한 방향 (반대 방향)으로 정렬하는 속성 
    - flexDirection:"column" 에서 alignItems는 좌우 정렬을 뜻한다.
    - flexDirection:"row" 에서 alignItems는 상하 정렬을 뜻한다.
    - 상위 엘리먼트에 적용을 해야 안에 있는 컨텐츠에 영향이 간다.
    - flex-start / center / flex-end / space-between / space-around 

앱 화면 만들기 - 메인화면 꾸미기 

▼ myapp/App.js 

더보기
import React from "react";
import {
  StyleSheet,
  Text,
  View,
  Image,
  ScrollView,
  TouchableOpacity,
} from "react-native";

export default function App() {
  return (
    <ScrollView>
      <Text style={styles.title}>나만의 꿀팁</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",
        }}
        style={styles.mainImage}
        resizeMode={"contain"}
      />
      <ScrollView style={styles.middleContainer} horizontal>
        <TouchableOpacity style={styles.middleButton}>
          <Text style={styles.middleButtonText}>미용</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.middleButton}>
          <Text style={styles.middleButtonText}>제테크</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.middleButton}>
          <Text style={styles.middleButtonText}>할인</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.middleButton}>
          <Text style={styles.middleButtonText}>기타</Text>
        </TouchableOpacity>
      </ScrollView>
      <View style={styles.cardContainer}>
        <View style={styles.card}>
          <Image
            style={styles.cardImage}
            source={{
              uri: "https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fpizza.png?alt=media&token=1a099927-d818-45d4-b48a-7906fd0d2ad3",
            }}
            resizeMode={"center"}
          />
          <View style={styles.cardText}>
            <Text style={styles.cardTitle}>먹다 남은 피자를 촉촉하게!</Text>
            <Text style={styles.cardDesc} numberOfLines={3}>
              먹다 남은 피자는 수분이 날라가기 때문에 처음처럼 맛있게 먹을 수
              없는데요. 이럴 경우 그릇에 물을 받아 전자레인지 안에서 1분
              30초에서 2분 정도 함께 돌려주면 촉촉하게 먹을 수 있습니다. 물이
              전자레인지 안에서 수증기를 일으키고, 피자에 촉촉함을 더해줍니다.
            </Text>
            <Text style={styles.cardDate}>2020.09.09</Text>
          </View>
        </View>
      </View>
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  title: {
    marginTop: "10%",
    marginLeft: "5%",
    fontSize: "25px",
    fontWeight: "bold",
  },
  mainImage: {
    height: 200,
    width: "90%",
    borderRadius: 10,
    marginTop: 20,
    alignSelf: "center",
  },
  middleContainer: {
    margin: 10,
  },
  middleButton: {
    width: 100,
    height: 50,
    padding: 15,
    backgroundColor: "#fdc453",
    borderColor: "deeppink",
    borderRadius: 15,
    margin: 7,
  },
  middleButtonText: {
    textAlign: "center",
  },
  cardContainer: {
    margin: 10,
  },
  card: {
    flexDirection: "row",
  },
  cardImage: {
    flex: 1,
    width: 90,
    height: 90,
    borderRadius: 10,
  },
  cardText: {
    flex: 2,
    marginLeft: 10,
  },
  cardTitle: {
    fontWeight: "bold",
    fontSize: 20,
  },
  cardDesc: { fontSize: 15 },
  cardDate: {
    fontSize: 10,
  },
});

 

메인화면


앱&자바스크립트 - 모듈, 반복문, 조건식

모듈 시스템 

: 여러 자바스크립트 파일이 있을 경우, 사로 다른 자바스크립트 파일에서 각 파일에 있는 함수를 불러오거나, 자바스크립트 파일 자체를 불러와 사용하는 것

- 여러 앱 파일을 만들 때, export default function 으로 함수를 내보낸다.

반복문 사용하기 -  map

▽ idx, category,title,image,desc,date 프로퍼티가 있는 객체가 저장되어 있는 data.json 파일이 있다. 

data.json

▼ myapp/App.js 

  • map으로 data.json에 있는 데이터를 가져와 화면에 표시한다. 
import data from "./data.json";
  let tip = data.tip;
  /* ... */
       {tip.map((content, i) => {
          return (
            <View style={styles.card} key={i}>
              <Image
                style={styles.cardImage}
                source={{
                  uri: content.image,
                }}
                resizeMode={"center"}
              />
              <View style={styles.cardText}>
                <Text style={styles.cardTitle}>{content.title}</Text>
                <Text style={styles.cardDesc} numberOfLines={3}>
                  {content.desc}
                </Text>
                <Text style={styles.cardDate}>{content.date}</Text>
              </View>
            </View>
          );
        })}

map 결과

조건문 사용하기 - 삼항연산자

- 선택 사항이 두가지 뿐이라면, if문 보다는 삼항 연산자를 사용한다.

▼ myapp/App.js 

  • card가 짝수번째일때와 홀수번째일때의 이미지 위치를 다르게 설정한다.
       {tip.map((content, i) => {
          return i % 2 === 0 ? (
            <View style={styles.card} key={i}>
              <Image
                style={styles.cardImage}
                source={{
                  uri: content.image,
                }}
                resizeMode={"center"}
              />
              <View style={styles.cardText}>
                <Text style={styles.cardTitle}>{content.title}</Text>
                <Text style={styles.cardDesc} numberOfLines={3}>
                  {content.desc}
                </Text>
                <Text style={styles.cardDate}>{content.date} 작성</Text>
              </View>
            </View>
          ) : (
            <View style={styles.card} key={i}>
              <View style={styles.cardText}>
                <Text style={styles.cardTitle}>{content.title}</Text>
                <Text style={styles.cardDesc} numberOfLines={3}>
                  {content.desc}
                </Text>
                <Text style={styles.cardDate}>{content.date} 작성</Text>
              </View>
              <Image
                style={styles.cardImage}
                source={{
                  uri: content.image,
                }}
                resizeMode={"center"}
              />
            </View>
          );
        })}

결과


2주차 숙제 - about 화면 만들기

▼ myapp/pages/AboutPage.js

더보기
import { StyleSheet, Text, Image, View, TouchableOpacity } from "react-native";

export default function AboutPage() {
  return (
    <View style={styles.container}>
      <Text style={styles.mainText}>
        HI! 스파르타코딩 앱개발{"\n"}반에 오신것을 환영합니다
      </Text>
      <View style={styles.middleContainer}>
        <Image
          style={styles.aboutImage}
          source={{
            uri: "https://storage.googleapis.com/sparta-image.appspot.com/lecture/about.png",
          }}
        />
        <Text style={styles.midderTextOne}>
          많은 내용을 간결하게 담아내려{"\n"}노력했습니다!
        </Text>
        <Text style={styles.middleTextTwo}>
          꼭 완주 하셔서 꼭 여러분것으로 만들어가시길{"\n"}바랍니다
        </Text>
        <TouchableOpacity style={styles.middleButton}>
          <Text style={styles.middleButtonText}>여러분의 인스타계정</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#1F266A",
  },
  mainText: {
    margin: 30,
    marginTop: 70,
    textAlign: "center",
    color: "white",
    fontSize: 30,
    fontWeight: "bold",
  },
  middleContainer: {
    alignSelf: "center",
    width: "80%",
    height: "60%",
    backgroundColor: "white",
    borderRadius: 20,
    alignItems: "center",
    justifyContent: "center",
  },
  aboutImage: {
    borderRadius: 30,
    width: 150,
    height: 150,
  },
  midderTextOne: {
    margin: 15,
    textAlign: "center",
    fontSize: 20,
    fontWeight: "bold",
  },
  middleTextTwo: {
    margin: 10,
    textAlign: "center",
    fontSize: 15,
    fontWeight: "bold",
  },
  middleButton: {
    margin: 10,
    width: 150,
    height: 50,
    backgroundColor: "orange",
    justifyContent: "center",
    borderRadius: 10,
  },
  middleButtonText: {
    fontSize: 15,
    textAlign: "center",
    fontWeight: "bold",
    color: "white",
  },
});

aboutpage 결과

 

profile

DEVELOP

@JUNGY00N