리액트 네이티브에서 그림자를 설정하는 방법이다. 그림자 속성은 iOS와 Android에서 약간 다르게 처리되므로, 두 플랫폼을 모두 고려해야한다.

# iOS에서 그림자 설정

iOS에서는 shadowColor, shadowOffset, shadowOpacity, shadowRadius 속성을 사용하여 그림자를 설정할 수 있다.

1.shadowColor: 그림자의 색상을 설정한다. 예를 들어, #000은 검정색 그림자를 의미한다.

shadowColor: '#000',

2. shadowOffset: 그림자의 오프셋을 설정한다. width와 height를 포함하는 객체로, 그림자가 요소의 어떤 방향으로 떨어지는지를 정의한다.

shadowOffset: { width: 0, height: 2 },

3. shadowOpacity: 그림자의 불투명도를 설정한다. 0은 투명하고 1은 불투명하다.

shadowOpacity: 0.8,

4. shadowRadius: 그림자의 흐림 정도를 설정한다. 값이 클수록 그림자가 더 흐릿해진다.

shadowRadius: 4,

예제:

<View style={{
  width: 100,
  height: 100,
  backgroundColor: 'white',
  shadowColor: '#000',
  shadowOffset: { width: 0, height: 2 },
  shadowOpacity: 0.8,
  shadowRadius: 4,
}}>
</View>

# Android에서 그림자 설정

Android에서는 elevation 속성을 사용하여 그림자를 설정한다. elevation 값이 클수록 그림자가 더 강해진다.

1. elevation: 요소의 높이를 설정하여 그림자를 생성한다. 값이 클수록 그림자가 더 두꺼워진다.

elevation: 5,

예제:

<View style={{
  width: 100,
  height: 100,
  backgroundColor: 'white',
  elevation: 5,
}}>
</View>
 

# 플랫폼별 그림자 조정

iOS와 Android에서 동일한 시각적 효과를 얻으려면 두 플랫폼의 속성을 조정할 필요가 있다. iOS에서는 shadowOpacity와 shadowRadius를 조정하고, Android에서는 elevation을 조정하여 비슷한 효과를 얻을 수 있다.

# 복합적인 그림자 효과

복합적인 그림자 효과를 원한다면, View를 중첩하여 각각의 그림자 효과를 적용할 수도 있다. 예를 들어, 외부 그림자와 내부 그림자를 함께 설정하는 등의 효과를 사용하는 방식이다.

<View style={{
  width: 100,
  height: 100,
  backgroundColor: 'white',
  elevation: 5,
  shadowColor: '#000',
  shadowOffset: { width: 0, height: 2 },
  shadowOpacity: 0.8,
  shadowRadius: 4,
}}>
  <View style={{
    width: 80,
    height: 80,
    backgroundColor: 'gray',
    position: 'absolute',
    top: 10,
    left: 10,
    elevation: 3,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.5,
    shadowRadius: 2,
  }} />
</View>
 

이렇게 하면 외부 View와 내부 View에 각각 그림자 효과를 적용할 수 있다.

Flexbox는 레이아웃을 구성할 때 매우 강력한 도구로, 다양한 화면 크기와 해상도에 대응할 수 있도록 해준다. 주로 flexDirection, justifyContent, alignItems, flex, flexWrap 등의 속성을 설정하여 레이아웃을 조절한다.

  1. flexDirection: 이 속성은 자식 요소들이 배치되는 방향을 결정한다. 기본값은 column으로, 위에서 아래로 쌓인다. row로 설정하면 왼쪽에서 오른쪽으로 배치된다.
  2. justifyContent: 이 속성은 주 축(main axis) 방향으로 자식 요소들이 어떻게 정렬되는지를 설정한다. 예를 들어, center로 설정하면 중앙에 정렬되고, space-between으로 설정하면 요소들 사이에 균등한 간격을 둔다.
  3. alignItems: 이 속성은 교차 축(cross axis) 방향으로 자식 요소들이 어떻게 정렬되는지를 설정한다. flex-start, center, flex-end, stretch 등을 사용하여 정렬을 조절할 수 있다.
  4. flex: 이 속성은 자식 요소가 남은 공간을 얼마나 차지할지를 설정한다. flex: 1로 설정하면 자식 요소가 가능한 모든 공간을 차지하게 된다.
  5. flexWrap: 이 속성은 자식 요소들이 주 축 방향으로 넘칠 때 어떻게 처리할지를 설정한다. nowrap(기본값)으로 설정하면 넘치는 요소들이 한 줄에 표시되며, wrap으로 설정하면 다음 줄로 넘어가게 된다.

Flexbox를 잘 활용하면 다양한 화면 크기와 방향에서도 일관된 레이아웃을 유지할 수 있다. 각 속성들을 조합하여 원하는 레이아웃을 쉽게 구현할 수 있다.

React Native의 스타일링 시스템은 프레임워크를 통해 개발자가 JavaScript 및 React를 사용하여 iOS 및 Android용 기본 앱을 만들 수 있는 방법의 핵심적인 측면이다. 스타일 지정에 CSS가 사용되는 웹 기반 애플리케이션과 달리 React Native는 기본 레이아웃과 성능을 염두에 두고 CSS와 유사한 스타일의 하위 집합을 기반으로 하는 다른 시스템을 사용한다.


1. 스타일 지정을 위한 JavaScript 개체

React Native에서 스타일은 CSS 파일이 아닌 JavaScript 객체를 사용하여 정의된다. 이러한 객체에는 CSS와 유사하지만 기본 모바일 성능에 최적화된 속성이 포함되어 있다. 스타일은 style 소품을 통해 구성 요소에 전달된다.

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

const App = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Hello!</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f0f0f0',
  },
  text: {
    fontSize: 20,
    color: '#333',
  },
});

export default App;
  • 스타일은 스타일을 최적화하고 유효성을 검사하는 데 도움이 되는 StyleSheet.create 메서드를 사용하여 생성된다.
  • style 소품은 View 및 Text 구성 요소 모두에 전달된다.

2. CSS와의 차이점

React Native의 스타일링 구문은 CSS와 유사하지만 특정 기능들이 부족하다.

  • No cascade: React Native에는 CSS와 같은 계단식 스타일 시스템이 없다. 각 스타일은 적용되는 구성요소에 따라 다르다.
  • No inheritance: 하위 요소가 특정 스타일을 상속할 수 있는 HTML과 달리 React Native 구성 요소는 명시적으로 전달되지 않는 한 상위 요소에서 스타일을 상속하지 않는다.
  • Limited selectors: .class, #id 또는 element와 같은 CSS 선택기는 지원되지 않는다. 스타일은 style 소품을 통해 직접 적용된다.

3. 측정 단위

  • React Native는 CSS에서 사용되는 전통적인 픽셀 단위('px')가 아닌 밀도 독립적 픽셀(DIP)을 사용한다. 이렇게 하면 픽셀 밀도가 다양한 화면에서 UI가 보기 좋게 표시된다.
  • em, rem, % 또는 vh와 같은 단위를 사용할 수 있는 웹과 달리 React Native는 크기, 여백, 패딩 등에 대해 절대 숫자에만 거의 전적으로 의존한다.

4. 레이아웃용 Flexbox

React Native는 레이아웃 관리를 위해 Flexbox에 크게 의존한다. Flexbox는 컨테이너 내에서 구성 요소를 정렬하고 배포하는 효율적인 방법을 제공하는 레이아웃 모델이다.

React Native의 주요 Flexbox 속성은 다음과 같다:

  • flexDirection: 기본 축(행 또는 열)을 결정한다. 기본값은 'column'인 반면 웹 Flexbox에서는 기본값이 'row'이다.
    • row: 하위 구성요소가 가로로 배치
    • column: 하위 구성요소가 수직으로 배치
  • justifyContent: 기본 축을 따라 하위 항목을 정렬한다.
    • 값: flex-start, flex-end, center, space-between, space-around, space-evenly
  • alignItems: 교차축을 따라 하위 요소를 정렬한다.
    • 값: stretch(기본값), flex-start, flex-end, center.
  • flex: 형제에 비해 구성 요소가 어떻게 성장해야 하는지 제어한다. flex: 1이 있는 구성 요소는 flex가 있는 다른 구성 요소가 경쟁하지 않는 경우 사용 가능한 공간을 모두 차지한다.
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

 

 

5. 플랫폼별 스타일

React Native는 Platform 모듈이나 조건부 논리를 통해 플랫폼별 스타일을 허용한다.

  • 앱이 iOS에서 실행되는지, Android에서 실행되는지에 따라 조건부로 스타일을 적용할 수 있다.
import { Platform } from 'react-native';

const styles = StyleSheet.create({
  text: {
    ...Platform.select({
      ios: {
        fontFamily: 'Arial',
      },
      android: {
        fontFamily: 'Roboto',
      },
    }),
  },
});

 

여기서 Platform.select는 플랫폼에 따라 적절한 글꼴이 사용되도록 보장해준다.

 

6. 스타일시트와 인라인 스타일

React Native는 스타일을 정의하는 두 가지 주요 방법을 제공한다.

StyleSheet.create: 이 방법은 유효성 검사와 더 나은 성능을 제공하므로 선호된다. 스타일을 캐시하고 네이티브 브리지에 맞게 최적화한다.
인라인 스타일: 스타일은 인라인 JavaScript 개체로 직접 전달될 수도 있다. 그러나 이는 모든 렌더링의 스타일을 다시 계산하므로 효율성이 떨어진다.

<View style={{ backgroundColor: 'blue', padding: 10 }} />

인라인 스타일은 간단한 사용 사례에 작동하지만 보다 복잡한 스타일에는 StyleSheet.create를 사용하는 것이 좋다.

 

7. 스타일 결합

style prop에 배열을 전달하여 단일 구성요소에 대해 여러 스타일을 결합할 수 있다.

const baseStyle = {
  color: 'black',
  fontSize: 18,
};

const boldStyle = {
  fontWeight: 'bold',
};

<Text style={[baseStyle, boldStyle]}>Bold Text</Text>

이 경우 baseStyle과 boldStyle의 스타일이 모두 적용된다. 충돌이 있는 경우 배열의 뒷부분에 있는 스타일이 이전 스타일을 재정의한다.

 

8. 동적 및 조건부 스타일

스타일은 JavaScript 개체이므로 상태, 소품 또는 기타 논리를 기반으로 조건부 스타일이나 동적 스타일을 쉽게 적용할 수 있다.

const isActive = true;
const styles = {
  text: {
    color: isActive ? 'green' : 'red',
  },
};

동적 스타일을 사용하여 사용자 작업, 화면 크기 등에 따라 다양한 스타일을 적용할 수 있다.

 

9. 그림자 및 테두리 속성

React Native는 기본 그림자 및 테두리 속성을 지원한다.

  • 그림자 속성: iOS에서 사용할 수 있다.
  • shadowColor, shadowOffset, shadowOpacity, shadowRadius.
  • Elevation(Android 그림자용): Android에서는 elevation 속성을 사용하여 그림자가 생성된다.
const styles = StyleSheet.create({
  box: {
    width: 100,
    height: 100,
    backgroundColor: '#fff',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.8,
    shadowRadius: 3,
    elevation: 5, // 안드로이드 그림자
  },
});

 

10. 의사 클래스 및 미디어 쿼리

React Native는 :hover, :focus 또는 :before와 같은 의사 클래스를 지원하지 않는다. 대신 JavaScript 로직(예: 사용자 상호 작용 이벤트)을 사용하여 이러한 상태를 관리해야 한다.
마찬가지로 미디어 쿼리는 기본적으로 지원되지 않지만 react-native-Response와 같은 타사 라이브러리를 사용하거나 Dimensions를 쿼리하여 다양한 화면 크기를 수동으로 처리할 수 있다.

 

11. 반응형 디자인

React Native는 기본적으로 미디어 쿼리를 제공하지 않지만 다음을 통해 반응형 레이아웃을 만들 수 있다.

- 'Dimensions' 사용

import { Dimensions } from 'react-native';
const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;

기기 크기에 따라 UI 크기를 조정하기 위한 'react-native-Response' 또는 'react-native-size-matters'와 같은 라이브러리이다.

 

12. 애니메이션 및 변형

React Native는 Animated 라이브러리를 통해 기본적으로 애니메이션을 지원하며 구성 요소에 애니메이션 스타일을 적용할 수 있다. 또한 rotate, scale, translateX 등과 같은 transform 속성을 사용하여 시각적 모양을 동적으로 조작할 수 있다.

const animatedValue = new Animated.Value(0);
const animatedStyle = {
  transform: [{ translateY: animatedValue }],
};

 

AsyncStorage는 React Native 애플리케이션에서 비동기적으로 데이터를 저장하고 관리할 수 있는 API를 제공한다. 

AsyncStorage의 특징

1. 비동기 작업 처리

  • 설명: AsyncStorage는 비동기적으로 데이터를 처리한다. 이는 데이터 저장, 읽기, 삭제 작업이 네트워크 요청처럼 시간이 걸릴 수 있음을 의미한다. 모든 작업은 Promise를 반환하며, async/await 구문을 사용하여 비동기 작업을 쉽게 처리할 수 있다.
  • 장점: 비동기 처리는 UI의 반응성을 유지하면서 데이터 작업을 수행할 수 있게 해준다.

2. 저장된 데이터의 영속성

  • 설명: AsyncStorage는 데이터가 앱을 종료하거나 디바이스가 재부팅되어도 유지되도록 설계되었다. 이는 로컬 디바이스 스토리지에 데이터를 저장하기 때문이다.
  • 장점: 앱이 다시 실행될 때에도 저장된 데이터에 접근할 수 있어 사용자 설정, 로그인 정보 등을 유지할 수 있다.

3. 키-값 쌍으로 데이터 저장

  • 설명: AsyncStorage는 데이터를 키-값 쌍으로 저장한다. 데이터는 문자열 형태로 저장되며, 복잡한 데이터는 JSON 문자열로 변환하여 저장할 수 있다.
  • 장점: 간단한 데이터 저장과 조회를 지원하며, 키를 통해 특정 데이터를 쉽게 식별하고 접근할 수 있다.

4. 데이터의 삭제 및 갱신

  • 설명: AsyncStorage는 특정 키에 대한 데이터를 삭제하거나 갱신할 수 있는 메서드를 제공한다. 데이터 삭제는 removeItem, 모든 데이터 삭제는 clear 메서드를 사용하며, 데이터 갱신은 mergeItem 메서드를 통해 수행할 수 있다.
  • 장점: 저장된 데이터의 관리와 업데이트를 유연하게 수행할 수 있다.

5. 여러 항목의 한 번에 저장 및 삭제

  • 설명: AsyncStorage는 multiSet과 multiRemove 메서드를 통해 여러 항목을 동시에 저장하거나 삭제할 수 있다. 이는 여러 키-값 쌍을 한 번에 처리할 때 유용하다.
  • 장점: 배치 작업을 지원하여 데이터 처리 작업을 효율적으로 수행할 수 있다.

6. 키 목록 조회

  • 설명: getAllKeys 메서드를 사용하면 저장된 모든 키를 배열로 가져올 수 있다. 이는 현재 저장된 데이터의 키를 확인하거나 특정 데이터를 찾는 데 유용하다.
  • 장점: 저장된 데이터의 전체 목록을 조회할 수 있어 데이터 관리가 용이하다.

7. 다중 데이터 읽기 및 저장

  • 설명: multiGet 메서드를 사용하여 여러 키의 값을 동시에 읽어올 수 있으며, multiSet 메서드를 사용하여 여러 항목을 동시에 저장할 수 있다. 이는 많은 데이터를 처리할 때 유용하다.
  • 장점: 여러 항목을 동시에 처리할 수 있어 성능을 최적화하고 코드의 복잡성을 줄일 수 있다.

8. JSON 데이터의 변환

  • 설명: AsyncStorage에 저장할 데이터는 문자열이어야 하므로, 객체를 저장할 때는 JSON.stringify를 사용하여 문자열로 변환해야 한다. 읽어올 때는 JSON.parse를 사용하여 문자열을 다시 객체로 변환할 수 있다.
  • 장점: 객체와 같은 복잡한 데이터를 문자열로 변환하여 저장하고, 다시 원래의 형식으로 복원할 수 있어 다양한 데이터 유형을 처리할 수 있다.

9. 오류 처리 및 예외 처리

  • 설명: AsyncStorage의 메서드는 비동기적으로 작동하므로, 오류가 발생할 수 있다. try-catch 블록을 사용하여 오류를 처리할 수 있으며, .catch 메서드를 사용하여 Promise에서 발생할 수 있는 오류를 처리할 수 있다.
  • 장점: 예외 처리를 통해 애플리케이션의 안정성을 유지하고, 예상치 못한 오류에 대한 적절한 대응을 할 수 있다.

 

AsyncStorage 주요 기능

 

1. 데이터 저장하기 (setItem)

  • 설명: AsyncStorage.setItem 메서드는 특정 키에 값을 저장하는 기능을 제공한다.
  • 사용법: 이 메서드는 두 개의 인수를 받는다. 첫 번째 인수는 저장할 데이터의 키이며, 두 번째 인수는 저장할 값이다. 값은 문자열이어야 하며, 객체를 저장하려면 JSON 문자열로 변환해야 한다.
  • 예시
await AsyncStorage.setItem('user_token', 'abc123');

2. 데이터 읽어오기 (getItem)

  • 설명: AsyncStorage.getItem 메서드는 특정 키에 대한 값을 읽어오는 기능을 제공한다.
  • 사용법: 이 메서드는 저장된 키를 인수로 받아 해당 키에 대한 값을 반환한다. 반환된 값은 문자열이며, JSON 문자열로 저장된 객체는 다시 파싱해야 한다.
  • 예시
const token = await AsyncStorage.getItem('user_token');

3. 데이터 삭제하기 (removeItem)

  • 설명: AsyncStorage.removeItem 메서드는 특정 키에 저장된 데이터를 삭제하는 기능을 제공한다.
  • 사용법: 이 메서드는 삭제할 키를 인수로 받아 해당 키에 저장된 데이터를 제거한다.
  • 예시
await AsyncStorage.removeItem('user_token');

4. 모든 데이터 삭제하기 (clear)

  • 설명: AsyncStorage.clear 메서드는 모든 저장된 데이터를 삭제하는 기능을 제공한다.
  • 사용법: 이 메서드는 매개변수를 받지 않으며, 모든 저장된 데이터를 한 번에 제거한다.
  • 예시
await AsyncStorage.clear();

5. 모든 키 가져오기 (getAllKeys)

  • 설명: AsyncStorage.getAllKeys 메서드는 저장된 모든 키를 배열로 가져오는 기능을 제공한다.
  • 사용법: 이 메서드는 매개변수를 받지 않으며, 저장된 모든 키를 배열 형태로 반환한다.
  • 예시
const keys = await AsyncStorage.getAllKeys();

6. 여러 항목 읽어오기 (multiGet)

  • 설명: AsyncStorage.multiGet 메서드는 여러 키에 대한 값을 한 번에 읽어오는 기능을 제공한다.
  • 사용법: 이 메서드는 키 배열을 인수로 받아, 각 키에 대한 값을 포함한 배열을 반환한다. 각 배열 요소는 [key, value] 형식으로 되어 있다.
  • 예시
const result = await AsyncStorage.multiGet(['key1', 'key2']);
// result: [['key1', 'value1'], ['key2', 'value2']]

7. 여러 항목 저장하기 (multiSet)

  • 설명: AsyncStorage.multiSet 메서드는 여러 항목을 한 번에 저장하는 기능을 제공한다.
  • 사용법: 이 메서드는 키와 값 쌍을 배열 형태로 인수로 받아, 모든 항목을 동시에 저장한다.
  • 예시
     
await AsyncStorage.multiSet([['key1', 'value1'], ['key2', 'value2']]);

8. 여러 항목 삭제하기 (multiRemove)

  • 설명: AsyncStorage.multiRemove 메서드는 여러 항목을 한 번에 삭제하는 기능을 제공한다.
  • 사용법: 이 메서드는 삭제할 키 배열을 인수로 받아, 해당 키들에 대한 데이터를 제거한다.
  • 예시:
await AsyncStorage.multiRemove(['key1', 'key2']);

9. 값 업데이트하기 (mergeItem)

  • 설명: AsyncStorage.mergeItem 메서드는 특정 키에 저장된 데이터를 병합하는 기능을 제공한다. 기존 값에 새로운 값을 추가하거나 수정할 수 있다.
  • 사용법: 이 메서드는 두 개의 인수를 받는다. 첫 번째 인수는 키이며, 두 번째 인수는 병합할 데이터다. 데이터는 JSON 문자열이어야 한다.
  • 예시
await AsyncStorage.mergeItem('user_profile', JSON.stringify({ age: 30 }));

 

+ Recent posts