모든 자료들은 이 사이트 안의 정보들을 화용하였음을 명시합니다.
스타일 속성의 이름 표기법
- 스타일 객체가 가진 속성을 스타일 속성이라고 합니다.
- 스타일 속성에는 요가 엔진이 지정한 이름만 사용할 수 있으며 'flex', 'color'처럼 소문자로 시작합니다.
- 두 단어 이상으로 된 backgroundColor와 같은 속성 이름은 소문자 낙타 표기법(lower-camel-case-notation)을 사용합니다.
- flext와 background속성을 설정한 스타일 객체를 SafeAreaView 코어 컴포넌트의 style속성에 설정합니다.
<SafeAreaView style={{ flex: 1, backgroundColor: 'blue' }}/>
요가 엔진이란?
리액트 네이티브는 웹 브라우저에서 단수니 자바스클힙트 엔지만 떼어 낸 것이므로 HTML은 물론 CSS엔진 또한 존재하지 않습니다. 리액트 네이티브는 이 때문에 요가(Yoga)란 이름의 CSS엔진을 직접 만들었습니다. 요가 엔진은 페이스북이 컴포넌트의 배치와 스타일링을 위해 C++언어로 구현한 라이브러리입니다. 요가 엔진은 웹 브라우저의 CSS엔진과 비슷하게 동작하지만 완전히 똑같지는 않습니다. 특히나 플렉스박스 레이아웃 부분에 차이가 있습니다.
div와 같은 HTML 요소에는 style이란 속성을 사용할 수 있습니다. HTML과 비슷하게 모든 리액트 네이티브 코어 컴포넌트에는 style이란 속성이 있습니다. 컴포넌트의 style속성에 적절한 값을 설정하면 네이티브 모듈 쪽에서 동작하는 요가 엔진이 이를 해석하여 안드로이드 프레임워크나 iOS의 UIKit프레임워크가 요구하는 스타일링을 수행합니다.
1. '뷰' 컴포넌트의 backgroundColor 스타일링 속성
/* eslint-disable */
import React from 'react';
import {SafeAreaView, StyleSheet, Text} from 'react-native';
const App = () => {
return (
<SafeAreaView style={[{backgroundColor: 'blue'}]}>
<Text style={[{color: 'white'}]}>Hello World!</Text>
</SafeAreaView>
);
};
const styles = StyleSheet.create({});
export default App;
이 코드에서는 스타일 객체를 style속성에 설정했는데 이를 인라인 스타일이라고 합니다. 그런데 style속성에는 인라인 스타일 외에도 StyleSheet라는 API를 지정해서 설정할 수 있다.
/* eslint-disable */
import React from 'react';
import {SafeAreaView, StyleSheet, Text} from 'react-native';
const App = () => {
return (
<SafeAreaView style={[styles.safeAreaView, {backgroundColor: 'blue'}]}>
<Text style={[styles.text, {color: 'white'}]}>Hello World!</Text>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
safeAreaView: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
text: {
fontSize: 20,
},
});
export default App;
인라인 스타일과 StyleSheet스타일의 차이
컴포넌트는 필요에 따라 리액트 네이티브에 의해 재렌더링됩니다. 재렌더링은 상황에 따라 반복해서 발생합니다. 이런 상황을 고려할 때 인라인 스타일 방식은 자바스크립트 엔진 쪽 스레드에서 UI스레드 쪽으로 브리지를 경유하여 옮겨 가므로 내용이 컴포넌트 로직에 의해 바뀌지 않을 때는 앱의 디스플레이 속도가 떨어집니다. 이와는 달리 StyleSheet.create로 생성된 스타일 객체는 UI 스레드 쪽에서 캐시되므로 앱 전체의 디스플레이 속도가 빨라집니다. 그래서 내용이 변하지 않는 스타일 객체는 StyleSheet.create방식으로 구현하는 것이 효과적이고 컴포넌트 구현 로직에 따라 동적으로 변하는 스타일 객체는 인라인 스타일 방식으로 구현하는 것이 일반적입니다.
또한 React Native 의 스레드에 대해 조금더 심층적으로 분석해 보도록 하겠습니다
- 프로세스란
- 실행중인 프로그램입니다.
- 모든 프로세스에는 하나 이상의 스레드가 있습니다.
- 그리고 프로그램을 실제로 많은 프로세스로 구성될 수 있습니다.
- 단일 프로그램의 프로세스를 하위 프로세스라고 합니다.
- 다중 프로세스를 사용하는 프로그램을 다중 프로세스라고 합니다.
- 각 프로세스는 독립적이다.
- 단일 스레드
- 단일 스레드는 프로세스가 하나의 실행 스레드 만 갖도록 설계되었음을 의미합니다.
- 한번에 하나의 명령 집합 만 실행됩니다.
- (5 + 5) - (10 - 4)
- 0단계 : (5 + 5) - (10 - 4)
- 1단계 : (10) - (10 - 4)
- 2단계 : 10 - (6)
- 3단계 : 4
- 스레드 끼리는 Code, Data, Heap영역은 공유한다.
- 다중 스레드
- 다중 스레드는 프로세스에 두 개 이상의 스레드가 있음을 의미합니다.
- 여러 명령을 동시에 실행할 수 있습니다.
- (5 + 5) - (10 - 4)
- 0 단계 : (5 + 5) - (10 - 4)
- 1 단계 : (10) - (6) // 동일한 단계에서 5 + 5 및 10 - 4 단계가 모두 수행되었습니다.
- 2 단계 : 4
- React Native는 단일 스레드 입니다
- 각 프로세스에 대해 단일 스레드 만 있음을 의미합니다.
- 왜 React Native가 다중 스레드 대신 단일 스레드가 되는 이유가 무엇일지 궁금할 것입니다.
- 멀티 스레딩이 복잡성 증가, 테스트의 어려움, 성능 비용 등 몇 가지 단점을 가지고 있기 때문
- React Native는 단일 스레드이므로 많은 책임이있는 프로세스가 있으면 성능 문제가 발생할 수 있습니다.
- 화면에 비디오를 렌더링하고 비디오에 대한 댓글의 라이브 피드를 담당하는 프로세스가 있다고 가정해보자
- 비디오 렌더링으로 인해 라이브 피드가 올바르게 업데이트되지 않거나 라이브 피드로 인해 비디오에서 끊김이 발생할 수 있습니다.
- React Native는 다중 처리됩니다.
- 여러 스레드를 실행하는 대신 React Native는 여러 프로세스를 실행합니다.
- 3개의 주요 프로세스는 React Native에서 실행되고 1개의 프로세스는 Android L (5.0)에서만 실행됩니다
- 더 많은 프로세스를 생성하려면 react-native-threads라이브러리를 사용할 수도 있습니다.
- UI 스레드 : 이 프로세스는 Android 및 iOS뷰 렌더링을 처리하는 데 사용됩니다.
- JS 스레드 : 이 프로세스는 React 네이티브 애플리케이션의 모든 로직을 처리하는 데 사용됩니다.
- React Native Modules Thread : 이는 앱이 플랫폼 API에 액세스 해야 할 때 발생합니다.
- 예를 들어 애니메이션 작업을 하는 경우 기본 드라이버를 사용하여 애니메이션을 처리할 수 있습니다
안드로이드 프레임워크나 iOS UIKit 프레임워크 쪽 렌더링을 담당하는 UI스레드와 App.tsx와 같은 자바스크립트 코드를 실행하는 자바스크립트 엔진 스레드 2개가 동시에 작동하게 되는데, 이 두 스레드는 메시지 큐(message queue)방식으로 서로 렌더링과 관련된 데이터를 주고 받습니다. 사용자가 화면을 터치하거나 하면 UI스레드는 이 내용을 자바스크립트 쪽 스레드에 이벤트(event)형태로 넘깁니다. 그리고 이런 방식으로 동작하는 프레임워크를 브리지(bridge) 방식 프레임워크라고 합니다
* 자바스크립트 엔진처럼 1개의 스레드에서 동작하는 앱을 단일 스레드앱이라 하고 리액트 네이티브 앱처럼 2개 이상의 스레드에서 동작하는 앱을 다중 스레드 앱이라 합니다
2. 구글 머티리얼 디자인 색상과 react-native-paper 패키지
CSS에서 색상은 '#fff'혹은 '#2196f3'처럼 16진수 RGB값으로 표현할 수 있습니다. 하지만 '#fff'보다는 'white', '#2196f3'보다는 Colors.blue500처럼 표현하는 쪽이 실제 어떤 색깔인지 알아보기 좋습니다.
npm i react-native-vector-icons react-native-paper
npm i color
npm i -D @types/Color
를 터미널에서 실행합니다 그리고 아래 코드를 작성해 줍니다.
/* eslint-disable */
import React from 'react';
import {SafeAreaView, StyleSheet, Text} from 'react-native';
import {Colors} from 'react-native-paper';
import Color from 'color';
const App = () => {
return (
<SafeAreaView style={[styles.safeAreaView]}>
<Text style={[styles.text]}>Hello World!</Text>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
safeAreaView: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: Colors.blue500,
},
text: {
fontSize: 20,
color: Color(Colors.blue500).alpha(0.7).lighten(0.5).string(),
},
});
export default App;
Colors.blue500색상을 color패키지가 제공하는 Color 클래스를 사용하여 알팟값을 0.7배로 한 다음 밝기를 0.5배로 하고 이를 문자열로 다시 변환하는 과정을 거친 코드입니다.
3. View 컴포넌트와 CSS 박스 모델
3-1. Platform 과 Dimensions API
/* eslint-disable */
import React from 'react';
import {
SafeAreaView,
StyleSheet,
Text,
Platform,
Dimensions,
} from 'react-native';
import {Colors} from 'react-native-paper';
import Color from 'color';
const {width, height} = Dimensions.get('window');
const App = () => {
return (
<SafeAreaView style={[styles.safeAreaView]}>
<Text style={[styles.text]}>os: {Platform.OS}</Text>
<Text style={[styles.text]}>width: {width}</Text>
<Text style={[styles.text]}>height: {height}</Text>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
safeAreaView: {
backgroundColor: Colors.blue500,
},
text: {
fontSize: 20,
color: Color(Colors.blue500).lighten(0.9).string(),
},
});
export default App;
이름에 View자가 들어간 뷰 컴포넌트는 backgroundColor 스타일 속성으로 자신의 바탕색을 설정할 수 있습니다.
이와 달리 Text나 TextInput 컴포넌트는 자신의 바탕색은 설정할 수 없지만, 글자 색상은 color속성으로 바꿀 수 있습니다.
리액트 네이티브는 크기를 조절하는 4가지 방법이 있습니다
- 명시적으로 width, height를 설정하지 않고 리액트 네이티브의 기본 설정(default) 방식을 따르는 방법
- 픽셀(pixel, px) 단위의 숫자를 직접 설정하는 방법
- 부모 요소의 width, height를 기준으로 자식 컴포넌트의 크기를 퍼센트(%)로 설정하는 방법
- flex속성을 사용하여 여러 자식 컴포넌트가 부모 컴포넌트의 크기를 분할하여 가지는 방법
3-2. margin 스타일 속성
marginLeft값과 marginRight값이 같은 상황이면 marginHorizontal 스타일 속성으로 이 둘을 동시에 설정할 수 있으며 marginTop = marginBottom인 상황이면 marginVertical을 사용하여 두 값을 한꺼번에 설정할 수 있습니다
3-3. padding 스타일 속성
marign.. 과 비슷함로 생략
3-4. border 관련 스타일 속성
- borderWidth: border의 넓이를 의미한다
- borderColor: border색상을 의미한다
- borderRadius: border 모서리의 둥근 정도를 의미
- borderStyle: 실선, 점선 등 border 스타일을 의미한다
또한 안드로이드와 iOS환경을 생각해서 View컴포넌트를 스티일링을 해보면
Platform.select를 활용해서 짜보면
/* eslint-disable */
import React from 'react';
import {
SafeAreaView,
StyleSheet,
Text,
Platform,
Dimensions,
View,
} from 'react-native';
import {Colors} from 'react-native-paper';
import Color from 'color';
const {width, height} = Dimensions.get('window');
const App = () => {
return (
<SafeAreaView style={[styles.safeAreaView]}>
<Text style={[styles.text]}>os: {Platform.OS}</Text>
<Text style={[styles.text]}>width: {width}</Text>
<Text style={[styles.text]}>height: {height}</Text>
<View style={[styles.box, {borderRadius: 10}]} />
<View style={[styles.box, styles.border]} />
<View style={[styles.box, styles.border, {borderRadius: 10}]} />
</SafeAreaView>
);
};
const styles = StyleSheet.create({
safeAreaView: {
flext: 1,
backgroundColor: Colors.blue500,
paddingLeft: Platform.select({ios: 0, android: 20}),
},
text: {
fontSize: 20,
marginBottom: 20,
marginLeft: 50,
marginTop: 20,
},
box: {
width: '70%',
height: 100,
backgroundColor: 'white',
marginBottom: 10,
marginLeft: Platform.select({ios: 20, android: 10}),
},
border: {
borderWidth: 10,
borderColor: Colors.lime500,
},
});
export default App;
이와같이 짜줄 수 있다.
'React > ReactNative' 카테고리의 다른 글
React-Native ( style 속성과 StyleSheet API 이해하기) - part5 (0) | 2021.11.20 |
---|---|
React-Native ( style 속성과 StyleSheet API 이해하기) - part4 (0) | 2021.11.20 |
React-Native ( style 속성과 StyleSheet API 이해하기) - part2 (0) | 2021.11.19 |
React-Native ( style 속성과 StyleSheet API 이해하기) - part2 (0) | 2021.11.19 |