본문 바로가기
리액트(React)

React Native - 기본 Template Component 만들기(3)

by 즐거운코딩 2024. 11. 13.
반응형

이번 Template Component 는 기존 앞의 두 개 포스트와는 다른 좀 더 복잡하지만 효용성이 높은 Compound Component Design 패턴을 이용하여 만들어 보겠습니다.

 

우선 Compound Component Design에 대해 간단히 설명하고 사례를 들어보면 이해가 좀 더 쉽게 될 것 같습니다.

 

1.  Compound Component Design

  • 일반 컴포넌트와 다른 점은 다음과 같습니다.
    • 일반 컴포넌트
      : 단일 컴포넌트로 구성되며, props를 통해 데이터나 함수를 전달 받음
      : 로직과 UI가 하나의 컴포넌트에 집중
    • 컴파운드 컴포넌트
      : 여러 개의 관련 컴포넌트를 하나의 부모컴포넌트에 그룹화하여 구성함
      : 부모 컴포넌트가 전체 로직과 상태를 관리하고, 자식 컴포넌트들과 공유
      : 로직은 부모 컴포넌트에, UI는 자식 컴포넌트에 분리
      : 더 유연한 구조로 사용자가 필요한 서브컴포넌트만 선택적으로 사용 가능
      : 구조와 스타일을 더 쉽게 커스터마이징 가능

      : 관련 컴포넌트들의 로직을 한 곳에 관리하므로 유지보수가 용이
  • 컴파운드 컴포넌트의 단점?
    • 컴포넌트의 구조가 복잡해짐
    • Context API를 사용하지 않으면 자식 컴포넌트 간 데이터 공유에 제약이 있을 수 있음
    • 컴포넌트 간 강한 결합이 생길 수 있어 분리가 어려울 수 있음

 

2.  Header Compoud Component 만들기

앱의 헤더에는 화면 타이틀, 백 버튼, 닫기 버튼 등 다양한 컴포넌트의 조합이 필요하여 컴파운트 컴포넌트로 구현해 보겠습니다.

  • 구성
    • src (소스)  > components > Header 폴더 생성하고 하위에 다음의 파일 생성
    • 부모 컴포넌트 : Header
    • 서브 컴포넌트:  HeaderButton, HeaderGroup, HeaderTitle 

Header 폴더구성

 

  • HeaderButton Component 만들기
    • 기본 컴포넌트로 만든 Button, Icon 사용
    • props로 버튼 선택시 동작 함수와 표출할 아이콘 이름, 크기, 색상을 넘겨줌
import React, { Component } from 'react';
import Button from '../Button';
import Icon from '../Icons';

export default class HeaderIcon extends Component {
  render() {
    return (
      <Button onPress={this.props.onPress}>
        <Icon name={this.props.iconName} size={28} color='black' />
      </Button>
    )
  }
}

 

  • HeaderTitle Component 만들기
    • 헤더에 표시할 화면 제목으로 Typography 컴포넌트 활용
    • props로 타이틀 텍스트와 폰트사이즈를 넘겨줌
import React, { Component } from 'react';
import Typography from '../Typography';

export default class HeaderTitle extends Component {
  render() {
    return (
      <Typography fontSize={18}>{this.props.title}</Typography>
    )
  }
}

 

  • HeaderGroup Component 만들기
    • Button과 Title 컴포넌트를 그룹으로 묶기 위한 컴포넌트로 두 컴포넌트의 배열 등 스타일 지정
import React, { Component } from 'react';
import { View } from 'react-native';

export default class HeaderGroup extends Component {
  render() {
    return (
      <View style={{flexDirection:'row', alignItems:'center'}}>
        {this.props.children}
      </View>
    )
  }
}

 

  • Header Component 만들기
    • 부모 컴포넌트로 전체 화면에 배치와 필요한 props값을 서브컴포넌트에 전달하는 역할
    • 디바이스 특성에 따른 노치, 상태바, 홈인디케이터 등 으로 인해 방해받지 않고 화면표출을 정상적으로 하기 위해 Safe Area Insets Context 라이브러리를 설치하고 사용
      • npm install react-native-safe-area-context
      • class 형식의 컴포넌트에는 SafeAreaInsetsContext 사용
      • 함수형 컴포넌트에는 SafeAreaView 사용
    • insets 으로 안전영역에 해당되는 padding값을 넘겨줌
    • 컴포넌트 하단에 서브컴포넌트 사용에 대해 정의해줌
import React, { Component } from 'react';
import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
import { Dimensions, View } from 'react-native';
import Spacer from '../Spacer';
import HeaderTitle from './HeaderTitle';
import HeaderIcon from './HeaderButton';
import HeaderGroup from './HeaderGroup';

const { width } = Dimensions.get('window');

export default class Header extends Component {
  render() {
    return (
      <SafeAreaInsetsContext.Consumer>
        {insets => (
          <View style={{paddingTop:insets.top}}>
            <View style={{
              width:width,
              flexDirection:'row',
              height:56,
              borderBottomColor:'gray',
              borderBottomWidth:1,
              alignItems:'center',
              }}>
              <Spacer horizontal={true} space={12} />
              <View style={{flex:1, flexDirection:'row', justifyContent:'space-between'}}>
                {this.props.children}
              </View>
              <Spacer horizontal={true} space={12} />
            </View>
          </View>
        )}
      </SafeAreaInsetsContext.Consumer>
    )
  }
}

Header.Title = HeaderTitle;
Header.Icon = HeaderIcon;
Header.Group = HeaderGroup;

 

  • App.js 에 Header Component 적용하기
    • 컴포넌트 명칭은 Header의 서브 컴포넌트로 표현
      • Header.Group, Header.Icon, Header.Title
    • 서브 컴포넌트로 props 전달
      • 헤더 타이틀 : HEADER 
      • 아이콘 : arrow-back , close 
import { View } from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import Header from './src/components/Header/Header';

export default function App() {
  return (
    <SafeAreaProvider>
      <View style={{ flex: 1 }}>
        <Header>
          <Header.Group>
            <Header.Icon iconName='arrow-back'></Header.Icon>
            <Header.Title title='HEADER'></Header.Title>
          </Header.Group>
          <Header.Icon iconName='close'></Header.Icon>
        </Header>
      </View>
    </SafeAreaProvider>
  );
}

 

Sample - Header & Badge Component

 

지금까지 다양한 기본컴포넌트와 좀 더 복잡한 컴파운드 컴포넌트에 대해 다뤄 보았습니다.

프로젝트에 맞게 일부 수정하여 사용하면 다양한 앱을 만들 때 좀 더 쉽고 일관성 있게 개발할 수 있을 것 같습니다.

반응형