[react-native] 디바이스 별 스타일을 어떻게 처리할까?

안녕하세요. 김용성입니다.
이전 포스팅에서는 제가 웹에서의 responsive units을 설명드렸는데요.

혹시 앱에서는 이러한 것들을 어떻게 처리해야할지 알고계시나요?
예를들어 작년에 아이폰 12가 나왔죠? 그 중에서 아이폰 12미니와 아이폰 12 max의 크기차이는 상당히 큽니다. 우리가 이러한 부분들에 대해 고려하지 않고, 고정된 값을 사용하여 보여지는 simulator에서만 그럭저럭 괜찮게 UI를 만들어놓는다면? 나중에 큰 문제가 생길 수도 있겠죠?

그래서 오늘은 react-native로 앱을 만들 때 이러한 부분에 대해 미연에 방지하고, 디바이스 별 크기에 따라 폰트 크기나, container크기가 잘 적용될 수 있게 하는 방법을 간단하게 포스팅하고자 합니다.

globalStyles.js

최근에 진행했던 졸업작품 frontend 디렉토리에서 가져왔는데요. 저는 react-native 프로젝트를 진행할 때 주로 위와 같은 디렉토리 구조를 선호합니다.

오늘의 중요한 것은 디렉토리 구조가 아니니 이에 대한 설명은 생략하고 쭉쭉 내려가다보면 config라는 디렉토리가 보일텐데요. 주로 저는 이 config 디렉토리 내에서 globalStyles라고 앱 전역적으로 사용될만한 스타일 변수들을 모아놓고 export/import 해서 사용합니다. 이러한 것에 대해 설명드리는 이유는, 오늘 제가 알려드린 부분을 일일이 컴포넌트 내에서 styling하지 마시고, 이렇게 전역적인 스타일 변수를 사용할 경우에 작업이 훨씬 편해진다는 것을 알려드리고 싶어서였습니다. :)

여튼 config 파일 내의 globalStyles라는 파일을 한번 살펴보도록 하겠습니다.


//globalStyles.js

import {Dimensions} from 'react-native';

export const colors = {
  primary: '#EC8B57',
  black: '#191919',
  red: '#FF3636',
  lightBlue: '#36D2FF',
  green: '#8FEF73',
  grey: '#767676',
  borderGrey: '#C9C9C9',
  statusGrey: '#666666',
  textGrey: '#A2A2A2',
  darkBlue: '#83abeb',
};

export const fonts = {
  SpoqaHanSansNeo: 'SpoqaHanSansNeo',
  SpoqaHanSansNeo_Thin: 'SpoqaHanSansNeo-Thin',
  SpoqaHanSansNeo_Light: 'SpoqaHanSansNeo-Light',
  SpoqaHanSansNeo_Medium: 'SpoqaHanSansNeo-Medium',
  SpoqaHanSansNeo_Regular: 'SpoqaHanSansNeo-Regular',
  SpoqaHanSansNeo_Bold: 'SpoqaHanSansNeo-Bold',
};

export const basicDimensions = { // 디자이너가 작업하고 있는 XD파일 스크린의 세로,가로
  height: 740,
  width: 360,
};

export const height = ( // 높이 변환 작업
  Dimensions.get('screen').height *
  (1 / basicDimensions.height)
).toFixed(2);

export const width = ( // 가로 변환 작업
  Dimensions.get('screen').width *
  (1 / basicDimensions.width)
).toFixed(2);

설명

react-native의 요소 중에는 Dimensions라는 녀석이 있어요.

이 녀석을 통해서 현재 사용하고 있는 screen의 가로, 세로 값을 가져올 수가 있는데요. 이제 이렇게 가져온 녀석을 나누어줍니다.

어떤 값으로 나눌까요?

저 같은 경우, 위 코드를 짤 때에는 제가 직접 XD파일을 만들었었어요. 그때 XD 스크린을 높이 740px, 가로 360px으로 지정해둔 채 만들었기 때문에 저는 해당 값을 BasicDimensions라는 변수를 통해서 정의해주었습니다.
(각자 zeplin이나 XD를 보면서 저 변수는 설정해주면 됩니다!)

저렇게 해서 만들어진 width,height는 우리가 이제 컴포넌트에서 폰트와 컨테이너의 크기작업을 해줄 때 아주아주 용이하답니다. :)

예시

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

import {colors, width, height} from '../config/globalStyles'; //width,height 받아오기
import MyIcon from '../config/Icon-font.js';

  return (
      <View style={styles.notification}>
        <TouchableOpacity activeOpacity={0.8} style={styles.notification}>
          <View style={styles.notificationBody}>
            <MyIcon
              name={'alarm-3'}
              size={width * 25} <!--아이콘에서도-->
              color={colors.borderGrey}
            />
            <Text style={styles.notificationContent}>{content}</Text>
          </View>
          <Text style={styles.notificationTime}>방금 전</Text>
        </TouchableOpacity>
      </View>
  );
};

export default Notification;

const styles = StyleSheet.create({
  notification: {
    width: '100%', 
    height: height * 70, //높이를 지정해줄 때도
    backgroundColor: colors.bottomTabBarBackgroundColor,
    padding: width * 10, // padding 값을 줄 때도
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  notificationBody: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  notificationContent: {
    marginLeft: width * 10, // margin 값을 줄 때도
    fontSize: width * 13, // 폰트 사이즈를 지정해줄 때도!
  },
  notificationTime: {
    fontSize: width * 11,
    color: colors.grey,
  },
});

위 코드를 보시면 우리가 globalStyles에서 한번 정의한 width,height를 가지고 컨테이너의 width/height 그리고 padding/margin, 게다가 폰트 사이즈까지 선언할 수가 있다는 것을 확인할 수 있습니다.


(xd파일의 width/height 표시창)

XD에서 보여지는 width/height 비율과 같기 때문에 초기 디자인에서 원하던 모습을 여러 디바이스에서 충족시킬 수가 있죠.

마무리

늘 사용하던 맥북이 지금 잠시 고장이 난 것 같아, 여러가지 스크린샷과 함께 설명드리고 싶었는데 그러지 못해 아쉽네요. ㅜㅜㅜㅜㅜ
종강 후에 맥북을 고치면 설명한 내용을 보다 더 직관적으로 보실 수 있도록 몇가지 스크린샷을 추가하도록 하겠습니다.

읽어주셔서 감사합니다:)

좋은 웹페이지 즐겨찾기