내일배움단 App2.2
[앱개발 종합반] 2주 2일차 개발일지(2주 3-4강)
📱TIL App.202
1. JSX 문법
1) App.js 파일 살펴보기
App.js는 React Native 라이브러리, 그리고 Expo에서 제공하는 기능들을 사용해 앱의 화면을 그려주는 커다란 함수다. React Native로 앱을 만들 때, App.js 파일의 함수가 바로 우리가 보는 앱 화면에 해당한다. 아래 코드를 보면 App.js란 App
함수를 내보내기 하는 자바스크립트 파일이다. 이 함수가 내보내는 값인 return
부분을 보면 <View>
와 <Text>
같은 태그들이 보이는데, 이것이 앱의 실제 화면을 그릴 때 사용하는 JSX 문법이다.
import { StatusBar } from 'expo-status-bar';
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',
},
});
리액트 네이티브로 개발을 하다 보면 아래 권고사항을 알려주는 노란색 창이 뜨는데, App.js의 함수 return
위쪽에 아래 코드를 입력하면 창이 보이지 않도록 설정할 수 있다.
console.disableYellowBox = true;
Expo 클라이언트 앱(Expo Go)을 이용하면, App.js 파일을 수정했을 때 반영된 모습을 바로 확인할 수 있다.
2) JSX 기본 문법
JSX 문법이란 태그(<>)를 이용해 화면을 그리는 태그 문법이다. <View></View>
처럼 닫는 태그로 화면의 한 영역을 온전히 구성할 때, 이를 ‘엘리먼트(element)’라고 한다. 이는 화면을 구성하는 최소한의 영역이라는 뜻이다.
App.js 파일을 보면 App 함수가 JSX 문법, 즉 JSX로 그린 그림을 반환(return
)하는 것을 볼 수 있다. 이렇듯 JSX 문법을 화면에 그려주는 ‘반환’을 ‘렌더링(rendering)’이라 부른다. Expo는 이 App 함수가 반환한 그림을 받아서 휴대폰 화면에 그려준다.
① 모든 태그는 React Native(Expo)에서 꺼내 쓰기
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
우리는 React Native 기반 기술에 Expo를 얹어서 앱을 개발하는 것이기 때문에, 기본 소스는 React Native다. 따라서 React Native, 즉 라이브러리에서 필요한 태그들을 꺼내서 사용해야 한다. App.js 파일 최상단에 위치한 위 코드를 보면 react-native
에서 StyleSheet
, Text
, View
를 import
해오는 것(가져오는 것)을 볼 수 있다. 파일을 꺼내올 때는 꺼내 사용할 기능들을 파일 최상단에 명시해 주어야 한다. 더 자세한 사항은 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>
);
}
App.js 파일의 함수 부분을 보면 <View></View>
처럼 하나의 영역을 가지는 코드가 있고, <StatusBar />
처럼 스스로 열리고 닫히는 코드가 있다. 이러한 코드들은 마찬가지로 React Native 공식 문서나 Expo 공식 문서에서 해당 태그를 검색해 사용 방법과 예제를 익힐 수 있다.
③ 모든 태그는 바깥을 감싸는 최상위 태그가 있어야 한다!
위 태그를 보면, <View>
태그가 <Text>
태그와 <StatusBar>
태그를 감싸고 있다. 만약 태그를 감싸는 태그가 없다면, 파일을 저장했을 때 ‘Adjacent JSX elements must wrapped in an enclosing tag’라는 에러가 뜬다.
④ JSX 문법은 항상 return()
으로 감싸기
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<StatusBar style="auto" />
</View>
);
⑤ 주석 달기
코드를 짤 때는 내가 이 코드를 어떠한 의도로 짰는지 주석을 달아야 한다. 자바스크립트 파일에서는 // 주석
형식으로 적는다. JSX 문법 태그 안에서는 {/* 주석 */}
의 형식으로 주석을 쓴다. 하지만, 주석의 형태를 기억할 필요 없이 주석 내용을 드래그 후 Ctrl + /
을 입력하면 자동으로 주석 처리가 된다.
2. 앱 화면 만들기: 화면을 구성하는 element들
Expo 클라이언트 앱에서 화면이 보이지 않는다면?
1) Expo 서버와의 연결이 끊어져 있을 수 있다. 클라이언트 앱을 완전히 종료하고, 다시 켠 후 화면의 QR코드를 스캔하자.
2) 컴퓨터의 네트워크와 휴대폰의 네트워크가 동일해야 한다. 즉 두 기기가 같은 와이파이 망에 있어야 한다.
3) 브라우저 상의 Tunnel, LAN, Local을 차례로 눌러보며 휴대폰과 연결이 되는 방향을 찾아보자.
1) View 태그
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}>
<View style={styles.subContainerOne}></View>
<View style={styles.subContainerTwo}></View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
subContainerOne: {
flex:1,
backgroundColor:"yellow"
},
subContainerTwo: {
flex:1,
backgroundColor:"green"
}
});
<View>
태그는 화면의 영역을 잡아주는 태그다. 이 태그는 style 코드를 입혀주지 않는 이상 화면에 표시되지 않는다. View 태그는 style 태그로 영역을 잡을 수 있고, 색깔도 지정할 수 있다. 화면을 보면 노란색과 초록색 박스가 1:1 비율로 분할이 되어 있는데, 이러한 영역 지정은 style 태그에서 이루어진다.
2) Text 태그
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<Text>문자는 Text 태그 사이에 작성!!</Text>
<Text>문자는 Text 태그 사이에 작성!!</Text>
<Text>문자는 Text 태그 사이에 작성!!</Text>
<Text>문자는 Text 태그 사이에 작성!!</Text>
<Text>문자는 Text 태그 사이에 작성!!</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
<Text>
태그는 텍스트를 쓸 때 사용하는 태그다. 문자를 쓰려면 반드시 <Text>
태그 안에 입력해야 하며, 다른 태그에 문자를 입력하면 ‘Text strings must be rendered within a <Text>
component.’라는 에러 메세지가 뜬다. 화면에 에러가 뜰 때는 에러 메세지를 찬찬히 읽어보자!
위 코드를 살펴보면 JSX 기본 문법 규칙들이 적용된 것을 볼 수 있다. 여러 <Text>
태그들을 <View>
태그가 감싸고 있는 것, 또 모든 태그들이 return
뒤 소괄호 안에 위치하는 것을 확인할 수 있다.
StyleSheet
태그는 처음 보긴 하지만, CSS 문법과 비슷한 점이 많은 것 같다. 화면을 정렬할 때 flex
와 alignItems
, justifyContent
를 쓰는 점, backgroundColor
로 배경색을 입히는 것도 익숙하게 느껴진다. 또 자바스크립트 파일인 만큼 Object(딕셔너리) 구조에서의 key-value 값을 사용하는 것도 볼 수 있다.
3) ScrollView 태그
// 일반 'View'태그 사용
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function App() {
return (
// 화면을 넘어가는 부분은 잘린다.
<View 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>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
textContainer: {
height:100,
borderColor:'#000',
borderWidth:1,
borderRadius:10,
margin:10,
},
textStyle: {
textAlign:"center"
}
});
앱을 사용할 때, 기기 화면보다 보여지는 영역의 데이터가 더 많을 경우 스크롤을 이용한다. 위 코드를 보면, 전체를 감싸는 <View>
태그 안에 영역을 잡는 <View>
태그가 있고, 그 안에 <Text>
태그가 있다. 일반 <View>
가 아닌 <ScrollView>
태그는 화면에 넘치는 내용을 보일 때 스크롤이 가능하게끔 해 주는 태그다. CSS의 overflow
속성과 비슷한 느낌인 것 같다.
위의 코드에서 <View>
와 <Text>
태그는 style
이라는 속성을 갖는다. 이처럼 모든 태그는 style
속성을 갖고, 이 속성은 파일 최하단에 작성한 style 코드 객체(object)의 키 값을 부여해 element들에 스타일을 줄 수 있다. {styles.container}
처럼 dot notation을 사용해(연결 연산자 사용) object에서의 key-value 값을 이용하고 있음을 확인할 수 있다.
// '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>
</ScrollView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
textContainer: {
height:100,
borderColor:'#000',
borderWidth:1,
borderRadius:10,
margin:10,
},
textStyle: {
textAlign:"center"
}
});
일반 <View>
태그를 쓸 때와 달리 <ScrollView>
태그를 이용하면, 화면에서 잘리는 부분을 스크롤로 내려서 볼 수 있다. 코드 최상단을 보면, ScrollView
태그를 비롯한 모든 태그를 react-native
라이브러리에서 가져오는 것을 확인할 수 있다.
이미 개발한 코드를 복사, 붙여넣기 후 수정하는 습관을 들이자! 오타도 줄일 수 있고, 시간도 줄일 수 있다.
4) Button 태그
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>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
textContainer: {
height:100,
margin:10,
},
textStyle: {
textAlign:"center"
},
});
코드 최상단에서 Button
태그 역시 react-native
라이브러리에서 꺼내오는 것을 확인할 수 있다. <Button>
태그는 스스로 닫는 태그이며, 기존 태그들과는 달리 style
, title
, color
, onPress
등과 같은 속성들이 붙어있는 것을 확인할 수 있다. title
은 버튼의 내용, color
은 버튼의 색, onPress
는 일반 함수 또는 화살표 함수를 연결(bind)해 기능을 지정할 수 있다.
Alert
또한 react-native
라이브러리에서 꺼내서 사용한다. Alert
은 여러 함수를 가지고 있는데, 연결 연산자(.)를 이용해 alert
함수를 꺼내면 팝업창이 뜨는 기능을 구현할 수 있다. 더 자세한 사항은 <Button>
의 공식 문서를 참고하기! ‘Props’에서 속성들을 확인할 수 있다.
- 버튼에 함수를 지정하는 방법
위의 코드처럼 함수를 onPress
안에서 정의할 수도 있지만, JSX 밖에서 함수를 정의한 다음 연결할 수도 있다. JSX 밖에서 함수를 구현할 때는 화살표 함수로 구현한다.
export default function App() {
// 함수를 미리 지정할 수 있다.
const customAlert = () => {
Alert.alert("팝업입니다!");
}
return (
<View style={styles.container}>
<View style={styles.textContainer}>
<Text style={styles.textStyle}>아래 버튼을 눌러주세요</Text>
<Button
style={styles.buttonStyle}
title="버튼입니다"
color="#f194ff"
// 1. {} 안에 함수 이름 바로 넣기
onPress={customAlert}
/>
<Button
style={styles.buttonStyle}
title="버튼입니다"
color="#FF0000"
// 2. onPress 안의 함수 안에 함수 넣기
onPress={()=>{
customAlert();
}}
/>
</View>
</View>
);
}
5) TouchableOpacity 태그
import React from 'react';
import { StyleSheet, Text, View, ScrollView, TouchableOpacity, Alert } from 'react-native';
export default function App() {
const customAlert = () => {
Alert.alert("TouchableOpacity에도 onPress 속성이 있습니다")
}
return (
<ScrollView style={styles.container}>
<TouchableOpacity style={styles.textContainer} onPress={customAlert}>
<Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.textContainer} onPress={customAlert}>
<Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
</TouchableOpacity>
</ScrollView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
textContainer: {
height:100,
borderColor:'#000',
borderWidth:1,
borderRadius:10,
margin:10,
},
textStyle: {
textAlign:"center"
}
});
<TouchableOpacity/>
태그는 <Button>
의 또다른 이름이다. <Button>
태그는 고유한 영역을 갖기 때문에, 화면을 구현할 때 버튼의 영역을 고려하면서 코드를 써야 한다. 하지만 <TouchableOpacity/>
는 스타일을 고려할 필요 없이 <View>
나 <Text>
를 감싼 후 그 자체에 onPress
를 붙일 수 있다. 예를 들어, 카카오톡 채팅방은 버튼처럼 생기지는 않았지만, 그 영역을 클릭하면 채팅방으로 이동할 수 있다. 이처럼 특정 영역을 지정해서 누를 수 있는 기능을 더하고 싶을 때 <TouchableOpacity/>
태그를 사용한다. 보통 <Button>
태그보다 <TouchableOpacity/>
태그를 더 많이 사용한다.
6) Image 태그
<Image>
태그는 앱에 이미지를 넣어주는 태그다. 이 태그를 이용하는 방식에는 두 가지가 있다.
① assets 폴더의 이미지 가져와 사용하기
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={"repeat"}
style={styles.imageStyle}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent:"center",
alignContent:"center"
},
imageStyle: {
width:"100%",
height:"100%",
alignItems:"center",
justifyContent:"center"
}
});
코드 최상단을 보면 <Image>
태그를 react-native
에서 가져오는 것을 확인할 수 있고, 사용할 이미지 또한 import
를 사용해서 불러오는 것을 확인할 수 있다. 불러온 이미지를 사용하기 위해서는, <Image>
태그의 source
속성 중괄호({}
) 안에 불러온 이미지 이름을 그대로 쓴다. resizeMode
는 불러온 이미지를 어떻게 보여주는지에 대한 속성이다. 공식 문서에서 해당 속성의 다양한 값들을 살펴볼 수 있다.
② 외부 이미지 사용하기
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<Image
source={{uri:"https://images.unsplash.com/photo-1424819827928-55f0c8497861?fit=crop&w=600&h=600%27"}}
resizeMode={"cover"}
style={styles.imageStyle}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent:"center",
alignContent:"center"
},
imageStyle: {
width:"100%",
height:"100%",
alignItems:"center",
justifyContent:"center"
}
});
assets 폴더의 이미지를 바로 가져올 때는 코드 최상단에 사용할 이미지를 import
해서 불러왔다. 외부 이미지를 사용하기 위해서는 <Image>
태그의 source
속성 안에 새로운 중괄호({}
)를 쓰고, 그 안에 uri
라는 키의 값으로 이미지 주소를 넣는다.
이미지 주소가 너무 길어서 화면을 넘어갈 때에는
Alt + Z
누르기! 화면에 맞게 코드가 자동으로 줄바꿈이 된다.
Leave a comment