[스파르타] 앱개발 2주차 리뷰

Amy·2021년 6월 16일
0

앱개발 개발일지

목록 보기
2/3
post-thumbnail

스파르타코딩클럽 앱개발 종합반 2주차 앱 개발 준비


기초적인 자바스크립트 문법과 사용 방법에 대한 저번 1주차에 이어 본격적으로 앱 개발 준비를 하고 앱 화면을 만들어보는 2주차를 진행했다.

이번주 목차

  • 리액트네이티브 & Expo
  • Expo 실행
  • JSX 기본 문법
  • 앱 화면 구현
  • 모듈과 반복문, 조건문
  • 숙제 설명 및 해설

이렇게 간단하게 목차를 정리했다.

01. 리액트네이티브 & Expo

  • 리액트 네이티브
    리액트 네이티브 (React Native)는 자바스크립트 언어 1개만으로 안드로이드, iOS 앱 2가지 모두를 만들어주는 라이브러리이다.
    하지만, 오로지 리액트 네이티브만 이용한다면, 특정상황에서 안드로이드 , iOS 각각의 폴더 안에 들어가 직접 코드를 만져야 하는 상황이 발생하게 된다.
    그래서 더 쉽고 빠르게 다른 개발 언어를 모르더라도 리액트 네이티브 앱 개발을 도와주는 도구가 존재한다.

  • Expo
    리액트 네이티브로 앱을 개발할 때, 코드를 건드려야 하는 대부분의 상황들을 안 건드려도 되게끔 도와주는 툴.

  • 설치 과정
    리액트 네이티브를 공부하면서 항상 의구심이 들었던 부분이다. 많은 블로그, 공식 도큐먼트를 보면 누구는 npm 누구는 npx 누구는 expo 매번 명령어의 의미조차 모른 채 다 다운 받기만 했었는데 앞으로 헷갈리지 않도록 정리한다.

    < Node & NPM >
    자바스크립트 "선물상자" 라고 생각하면 된다. Node.js로 자바스크립트 개발 환경을 구축하고, NPM으로 필요한 자바 스크립트 앱 개발 도구들을 가져온다.
    👉 설치를 위한 설치

    < Yarn >
    npm보다 가볍고 빠르게 자바스크립트 패키지를 관리할 수 있게 해주는 자바스크립트 패키지 매니저 툴로 언제든지 자바스크립트 도구를 설치할 수 있다. (npm으로 설치)
    👉 자바스크립트를 효율적으로 설치

    < Expo >
    앱 생성, 필요한 앱 개발 도구를 설치하기 위한 명령어 도구. 터미널에서 Expo 명령어를 사용할 수 있다. 프로젝트 생성, 실행, 배포까지 쉽게 가능하다. (npm으로 설치)
    👉 앱개발에 필요한 expo 도구상자

    다 설치가 끝났다면 Expo에 가입하고 계정을 세팅한다. expo 자체가 서비스이기 때문에 배포까지 관리해주고 도와주는데, 그래서 가입을 하고 내 로컬 컴퓨터와 연결을 시켜야 한다.

02. Expo 실행

데스크탑에 폴더를 하나 만들고 vscode로 열어준다.

expo init 프로젝트명 // 프로젝트 생성 

그리고 원하는 유형의 앱을 선택한다.

cd 프로젝트명
expo start 

생성이 완료되면 해당 폴더로 이동하고 앱을 실행시킨다.
자동으로 브라우저가 열리면서 서버가 켜진다. 이제 생성된 앱은 Expo go 어플을 통해 확인이 가능하다.

(이때, 꼭 개발PC와 스마트폰의 wifi가 동일해야 함)


지금까지의 과정 정리

  1. Expo 명령어 설치
  2. 로컬에 Expo 계정 세팅
  3. expo init 명령어로 기본 앱 생성
  4. expo start로 Expo 앱 실행
  5. 휴대폰에 설치한 Expo Go 앱으로 Expo 앱 실행

03. JSX 기본 문법

App.js는 JSX문법으로 그려져서 준비된 화면을 반환한다.
function App 함수가 JSX 코드를 리턴하고 이걸 Expo가 받아서 화면에 예쁘게 그려준다고 생각하면 쉽다.
개발자스럽게 말하면 이것을 렌더링(rendering) 이라고 부른다.
추가로 태그영역도 개발자스럽게 엘리먼트(element) 라고 불러도 알아먹도록 하자.

  • 기초 JSX 문법 원칙

    원칙1. 모든 태그는 react-native (라이브러리)에서 꺼내서 사용해야 한다. 위에 import문을 명시를 해야한다는 뜻.
    원칙2. 여는 태그, 닫는 태그 쓰는 구조를 태그마다 구분해서 써야 한다. (공식문서 참고)
    원칙3. 모든 태그는 감싸는 최상위 태그가 있어야 한다.
    원칙4. JSX 코드를 렌더링할 때는 감싸는 () 소괄호 가 있어야 한다.
    원칙5. JSX 코드 내에서는 {* *}, 밖에서는 //로 주석처리를 한다.

  • 기본적인 태그
    간단한 태그는 언급만 하고 헷갈리는 속성이나 정리하고 싶은 것들만 정리해본다.

    <view> : 영역을 잡아주는 태그. StyleSheet로 영역을 잡아줌.
    <Text> : 글을 작성하기 위한 태그.
    <ScrollView> : 앱 화면을 벗어나는 element를 감싸 스크롤하는 태그.
    <Button> : 버튼을 만들어주는 태그. onPress 속성을 이용해 함수와 바인딩함.
    <TouchableOpacity> : 버튼은 영역이 정해져있는 것과 달리 임의영역에 버튼 기능을 이용.
    <Image> : 이미지를 넣는 태그.
    방식1 - asset 폴더에서 가져와서 넣는 방식 (source)
    방식2 - 외부 이미지 링크를 넣는 방식 (source - uri)

  • Style 속성
    styleSheet : 태그에 스타일을 주는 기능
    styleSheet.create -> 옷을 입혀줄건데, 옷장을 다 만들어주는 코드.

    flex : 컨텐츠의 위치와 영역의 레이아웃을 결정.
    flexDirection : 자리 잡은 영역의 방향. default는 column이고 row로 설정 가능.
    justifyContent : flexDirection과 같은 방향으로 정렬하는 속성.

    alignItems : flexDirection과 수직한 방향으로 정렬하는 속성.

04.앱 화면 구현

  • 실습을 해보자

만들어야 했던 화면 (왼쪽) 과 내가 만든 화면 (오른쪽)

정확한 사이즈나 픽셀을 알려주진 않고 스크린샷만을 가지고 구현했기 때문에 크기나 색, 레이아웃은 조금씩 다르다. 전체적인 구성만 비슷하게 짜봤다.

import React from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView } from 'react-native';
export default function App() {
    return (
        <View style={styles.container}>
            <Text style={styles.title}>나만의 꿀팁</Text>
            <Image
                style={styles.image}
                resizeMode={'cover'}
                // overflow={'hidden'}
                source={{
                    uri: 'https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fmain.png?alt=media&token=8e5eb78d-19ee-4359-9209-347d125b322c',
                }}
            />
            <ScrollView horizontal={true} style={styles.scroll}>
                <TouchableOpacity style={styles.firstButton}>
                    <Text style={styles.text}>생활</Text>
                </TouchableOpacity>
                <TouchableOpacity style={styles.secondButton}>
                    <Text style={styles.text}>제테크</Text>
                </TouchableOpacity>
                <TouchableOpacity style={styles.thirdButton}>
                    <Text style={styles.text}>반려견</Text>
                </TouchableOpacity>
                <TouchableOpacity style={styles.forthButton}>
                    <Text style={styles.text}>꿀팁 찜</Text>
                </TouchableOpacity>
            </ScrollView>
            <View style={{ flexDirection: 'row' }}>
                <Image
                    style={styles.pizza}
                    source={{
                        uri: 'https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Fpizza.png?alt=media&token=1a099927-d818-45d4-b48a-7906fd0d2ad3',
                    }}
                />
                <TouchableOpacity style={{ width: '70%' }}>
                    <Text style={{ fontWeight: 'bold', fontSize: 18 }}>먹다 남은 피자를 촉촉하게!</Text>
                    <Text numberOfLines={3}>
                        먹다 남은 피자는 수분이 날라가기 때문에 처음처럼 맛있게 먹을 수 없는데요. 이럴 경우 그릇에 물을 받아 전자레인지
                        안에서 130초에서 2분 정도 함께 돌려주면 촉촉하게 먹을 수 있습니다. 물이 전자레인지 안에서 수증기를 일으키고,
                        피자에 촉촉함을 더해줍니다.
                    </Text>
                    <Text style={{ color: 'grey', fontSize: 9 }}>2020.09.09</Text>
                </TouchableOpacity>
            </View>
        </View>
    );
}
const styles = StyleSheet.create({
    container: {
        // height: '100%',
        marginHorizontal: 20,
        marginVertical: 50,
    },
    title: {
        fontSize: 20,
        fontWeight: 'bold',
    },
    image: {
        width: '100%',
        height: '35%',
        borderRadius: 10,
        overflow: 'hidden',
        marginVertical: 20,
    },
    scroll: {
        flexDirection: 'row',
        height: '1%',
        // alignContent: 'center',
    },
    firstButton: {
        margin: 5,
        width: 100,
        height: 50,
        backgroundColor: '#ffe699',
        borderRadius: 10,
        alignItems: 'center',
        justifyContent: 'center',
    },
    secondButton: {
        margin: 5,
        width: 100,
        height: 50,
        backgroundColor: '#ffb399',
        borderRadius: 10,
        alignItems: 'center',
        justifyContent: 'center',
    },
    thirdButton: {
        margin: 5,
        width: 100,
        height: 50,
        backgroundColor: '#99ffb3',
        borderRadius: 10,
        alignItems: 'center',
        justifyContent: 'center',
    },
    forthButton: {
        margin: 5,
        width: 100,
        height: 50,
        backgroundColor: '#ff9999',
        borderRadius: 10,
        alignItems: 'center',
        justifyContent: 'center',
    },
    text: {
        color: 'white',
    },
    pizza: {
        width: 90,
        height: 80,
        borderRadius: 10,
        marginRight: 10,
    },
}); 
  • 코드 재구현 & 리팩토링
  1. 기본 코드 구조

기억할 것

  • alignItems, justifyContent 를 이용해서 가운데 정렬을 시키고 싶을 때는 flex 속성을 사용했을 때 만 가능하다. 그래서 flex를 사용하지 않고도 가운데 정렬을 하고싶다면 alignSelf를 사용하면 된다.
  • 영역에 대해서 꾸미거나 구현하고 싶을 때는 borderWidth : 1 로 영역을 눈에 보이도록 설정해놓고 구현이 다 끝난 다음 지우는 습관을 들이자.
  • 수정한 코드
  1. 전체 페이지를 스크롤 하기 위해서 최상위 태그를 scrollView로 수정.
    처음 작성한 코드는 최상위 태그에서 크기를 조정해줬는데 각 요소별로 지정해주는 걸로 변경.
  2. 텍스트를 touchableopacity 가운데에 정확히 들어가게 하기 위해
    alignItems: 'center', justifyContent: 'center' 를 썼었는데, 좀 더 간편하게 상위 태그에서 padding을 주는 것으로 변경하고 textAlign : 'center'을 해줌.
  3. text 태그별로 style을 적용해주지만 통일되는 부분도 있기 때문에 전체를 크게 한번 text 태그로 묶어줌. (이 경우 numberOfLines 적용 안됨)
  4. 피자 이미지와 텍스트를 flex를 이용해서 비율을 1 : 3으로 설정.
  • 최종적으로 완성된 코드
import React from 'react';
import main from './assets/main.png';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView } from 'react-native';

export default function App() {
    return (
        <ScrollView style={styles.container}>
            <Text style={styles.title}>나만의 꿀팁</Text>
            <Image style={styles.mainImage} source={main} />
            <ScrollView horizontal={true} style={styles.middleContainer}>
                <TouchableOpacity style={styles.middleButton01}>
                    <Text style={styles.text}>생활</Text>
                </TouchableOpacity>
                <TouchableOpacity style={styles.middleButton02}>
                    <Text style={styles.text}>재테크</Text>
                </TouchableOpacity>
                <TouchableOpacity style={styles.middleButton03}>
                    <Text style={styles.text}>반려견</Text>
                </TouchableOpacity>
                <TouchableOpacity style={styles.middleButton04}>
                    <Text style={styles.text}>꿀팁 찜</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',
                        }}
                    />
                    <View style={styles.cardText}>
                        <Text style={styles.cardTitle}>먹다 남은 피자를 촉촉하게!</Text>
                        <Text style={styles.cardDesc} numberOfLines={3}>
                            먹다 남은 피자는 수분이 날라가기 때문에 처음처럼 맛있게 먹을 수 없는데요. 이럴 경우 그릇에 물을 받아 전자레인지
                            안에서 130초에서 2분 정도 함께 돌려주면 촉촉하게 먹을 수 있습니다. 물이 전자레인지 안에서 수증기를 일으키고,
                            피자에 촉촉함을 더해줍니다.
                        </Text>
                        <Text style={styles.cardDate}>2020.09.09</Text>
                    </View>
                </View>
            </View>
        </ScrollView>
    );
}

const styles = StyleSheet.create({
    container: {
        backgroundColor: 'white',
    },
    title: {
        fontWeight: '700',
        fontSize: 20,
        marginTop: 50,
        marginLeft: 20,
    },
    mainImage: {
        width: '90%',
        height: 200,
        borderRadius: 10,
        marginTop: 20,
        alignSelf: 'center',
    },
    middleContainer: {
        // borderWidth: 1,
        marginTop: 20,
        marginLeft: 20,
        height: 60,
    },
    middleButton01: {
        width: 100,
        height: 50,
        padding: 15,
        backgroundColor: '#fdc453',
        borderRadius: 10,
        margin: 8,
    },
    middleButton02: {
        width: 100,
        height: 50,
        padding: 15,
        backgroundColor: '#fe8d6f',
        borderRadius: 10,
        margin: 8,
    },
    middleButton03: {
        width: 100,
        height: 50,
        padding: 15,
        backgroundColor: '#9adbc5',
        borderRadius: 10,
        margin: 8,
    },
    middleButton04: {
        width: 100,
        height: 50,
        padding: 15,
        backgroundColor: '#f886a8',
        borderRadius: 10,
        margin: 8,
    },
    text: {
        color: 'white',
        fontWeight: '700',
        textAlign: 'center',
    },
    cardContainer: {
        marginTop: 10,
        marginLeft: 10,
    },
    card: {
        flex: 1,
        flexDirection: 'row',
        margin: 10,
    },
    cardImage: {
        flex: 1,
        width: 100,
        height: 100,
        borderRadius: 10,
    },
    cardText: {
        flex: 2,
        marginLeft: 10,
    },
    cardTitle: {
        fontSize: 20,
        fontWeight: '700',
    },
    cardDesc: {
        fontSize: 15,
    },
    cardDate: {
        fontSize: 10,
    },
});

05. 모듈과 반복문, 조건문

  • 앱에서의 모듈 시스템
    App.js는 앱의 화면을 그려주는 커다란 함수. 모듈 시스템에 의해 내보내진다.
    즉, 여러 앱 파일을 만들어서 export default function 으로 함수를 내보내면 된다.

  • 반복문
    반복문을 돌릴 때 최상위 태그는 키값을 가져야 하고 그 키값은 항상 unique한 키여야 한다.
    태그 안에서 js 문법을 쓰고싶다면 ? 중괄호 {} 를 쓰면 된다.

    <Text style={styles.weather}>
      오늘의 날씨: {todayWeather + '°C ' + todayCondition} 
    </Text>
    -> 출력? 오늘의 날씨: 27°C 흐림 
  • 조건문
    삼항연산자는 리액트 네이티브로 앱을 만들 때 가장 많이 사용되는 조건문이다.

    let result = 10 == 9 ? true : false // result <-- false 
    let result = 10 !== 9 ? true : false // result <-- true 
    let reuslt = 99 > 10 ? true : false // result <-- true

06. 숙제 설명 및 해설

이번주 숙제는 설계된 화면을 보고 그대로 클론코딩 해오는 것이다.
왼쪽이 주어진 과제고 오른쪽이 내가 구현한 과제.
이미지랑 폰의 배율이 살짝 달라서 캡쳐하니 살짝 가로 세로가 다른 것 같지만, 얼추 비슷하게 구현된 것 같다.

과제 구현 코드

import React from 'react';
import { View, Text, StyleSheet, Image, TouchableOpacity } from 'react-native';
export default function AboutPage() {
    return (
        <View style={styles.container}>
            <Text style={styles.title}>HI! 스파르타코딩 앱개발 반에 오신것을 환영합니다</Text>
            <View style={styles.contentContainer}>
                <Image
                    style={styles.contentImage}
                    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.mainText}>많은 내용을 간결하게 담아내려 노력했습니다!</Text>
                <Text style={styles.subText}>꼭 완주 하셔서 꼭 여러분것으로 만들어가시길 바랍니다</Text>
                <TouchableOpacity style={styles.instaButton}>
                    <Text style={styles.buttonText}>여러분의 인스타계정</Text>
                </TouchableOpacity>
            </View>
        </View>
    );
}
const styles = StyleSheet.create({
    container: {
        backgroundColor: '#262C74',
        flex: 1,
        paddingVertical: 60,
        paddingHorizontal: 35,
    },
    title: {
        flex: 1,
        color: 'white',
        fontSize: 30,
        fontWeight: '700',
    },
    contentContainer: {
        flex: 4,
        backgroundColor: 'white',
        borderRadius: 20,
        borderWidth: 1,
        padding: 30,
        alignItems: 'center',
        justifyContent: 'center',
    },
    contentImage: {
        width: 130,
        height: 130,
        borderRadius: 20,
    },
    mainText: {
        fontSize: 20,
        fontWeight: '700',
        marginBottom: 20,
        textAlign: 'center',
    },
    subText: {
        fontSize: 14,
        fontWeight: '700',
        textAlign: 'center',
    },
    instaButton: {
        width: 130,
        height: 50,
        borderRadius: 15,
        backgroundColor: '#F3B23E',
        justifyContent: 'center',
        marginTop: 20,
    },
    buttonText: {
        fontSize: 12,
        color: 'white',
        fontWeight: '700',
        textAlign: 'center',
    },
});

간단한 숙제여서 숙제 해설 영상은 안들었는데.. 시간이 되면 들어봐야겠다.

07. 2주차를 마치며

저번주보다 더 유익한 내용을 많이 배운 것 같다.
곧 시작하는 프론트 개발을 맡은 프로젝트가 있다보니 조금이라도 더 보탬이 되고자 열심히 공부하고 있다. 조금이라도 더 수월한 프로젝트 진행을 위해..
같은 디자인을 보고 다른 사람은 어떻게 짜는지, 내 코드와 어떻게 다른지 보고 비교하는 것이 중요하다고 느낀 2주차 수업이었다.
양이 조금 많았지만 도움이 많이 되는 시간이었다.

profile
serendipity :: 뜻 밖의 행운

0개의 댓글