React Native의 <View></View>는 React의 <div></div>라고 볼 수 있습니다. 모든 객체를 넣기 전에 <View></View>로 감싸주면 됩니다.

그리고 <View>의 파생으로서 <SafeAreaView>와 <ScrollView>가 있는데 <SafeAreaView>의 경우에는 아이폰 앱에서 최상위 <View>를 감싸줄 때 <SafeAreaView>를 사용하고 휴대폰 위의 카메라 양 옆 notch 부분을 제외한 부분만을 보여준다고 합니다. 그리고 <ScrollView>와 같은 경우 이름에서 알 수 있듯이 스크롤 기능을 추가해 줍니다.

View의 가장 기본적인 목적은 레이아웃을 짤 때 용이하게 하기 위함입니다. 그리고 View 안에 각종 style을 적용하여 그림과 텍스트 등 각종 오브젝트를 배치합니다.

실제로 코딩과 레이아웃을 다양한 예로 비교하여 확인해 봅시다.
html 도 그렇듯 처음에는 헷갈리지만 어느정도 확실히 자신만의 개념을 익히면 그렇게 어렵진 않습니다.
(그래도 가끔 헷갈리긴 합니다.)

import React from 'react'; 
import { View } from 'react-native'; 
const App = () => {
  return ( 
    <View> 
      <View style={{width: 400, height: 400, backgroundColor:"gold"}}> 
        <View style={{width: 300, height: 300, backgroundColor:"indigo"}}> 
          <View style={{width: 200, height: 200, backgroundColor:"indianred"}}> 
          </View> 
        </View> 
      </View> 
    </View> 
  ); 
}; 

export default App;

 

맨 상위 View는 그냥 놔두고 3중으로 View를 만들어 봅시다. 모든 View가 표현이 되기 위해서는 자신만의 넓이와 높이를 가져야 합니다. 하지만 자신의 하위(자식) View에서 값이 정해진 경우 높이의 경우는 그대로 따라가고(밀린다고 보면 될 것 같습니다.) 넓이의 경우는 100% 넓이로 표현됩니다.

그래서 아래 코드와 같이 금색 View의 가로세로 값을 지우게 되면,

 return ( 
   <View> 
     <View style={{ backgroundColor:"gold"}}> 
       <View style={{width: 300, height: 300, backgroundColor:"indigo"}}> 
         <View style={{width: 200, height: 200, backgroundColor:"indianred"}}> 
         </View> 
       </View> 
     </View> 
   </View> 
 );

이렇게 됩니다.

 

다음엔 하나의 View의 margin / border / padding을 알아봅시다. html과 비슷하게 생각하면 됩니다.

 return ( 
   <View> 
     <View style={{width: 400, height: 400, backgroundColor:"gold"}}> 
       <View style={{width: 300, height: 300, backgroundColor:"indigo", margin: 20, borderWidth: 20, borderColor: "indianred", padding: 20}}> 
         <View style={{width:100, height:100,backgroundColor:"lightgreen"}}>
         </View> 
       </View> 
     </View> 
   </View> 
 );

 

margin, border, padding이 적용된 View는 푸른색(indigo)색의 View입니다. 이를 기준으로 margin과 padding은 각각 밖과 안의 여백이며 border는 가장자리 경계선입니다.

그리고 이러한 margin, border, padding의 경우에는 셋 모두 marginTop, borderBottom, paddingRight 와 같이 네 변 중에서 한쪽만 지정할 수 있고 또 marginVertical(위/아래), borderHorizontal(양옆) 같이 마주보는 두 변을 지정할 수 있습니다.

 

그리고 border는 추가로 가장자리를 완만하게 바꿔주는 borderRadious : 숫자 가 있습니다.

 return ( <View> <View style={{width: 380, height: 380, backgroundColor:"gold", borderRadius:10}}> <View style={{width: 300, height: 300, backgroundColor:"indigo", borderWidth:5, borderRadius:30}}> <View style={{width:100, height:100,backgroundColor:"lightgreen", borderRadius:50}}> </View> </View> </View> </View> );

위와 같이 borderRadius 값에 따라 모서리의 완만함이 결정되고 일정 값 이상으로 가면 위의 연두색(lightgreen) View와 같이 원이 됩니다. 또한 borderWidth값을 지정해주면 가장자리 라인도 보이고 borderColor를 지정하지 않은 경우 기본값은 검은색이라는 것을 알수 있습니다.

아까부터 계속 신경쓰이는 부분이 있는데 각 View들이 왼쪽 위로 치우쳐져 있습니다. 아무 값을 입력하지 않으면 왼쪽 위(TopLeft)로 정렬된다는 것을 알 수 있습니다.

 

이제 Alignment(정렬)을 알아봅시다.
가장 먼저 알아볼 항목은 flexDirection 입니다. 내 하위 View들에 대한 정렬 방식을 선택하고 기본값은 column(열), 즉 세로 정렬입니다.

 return ( 
   <View> 
     <View style={{width: 300, height: 300, backgroundColor:"gold", marginBottom:10}}> 
       <View style={{width: 100, height: 100, backgroundColor:"indigo"}}> 
       </View> 
       <View style={{width: 100, height: 100, backgroundColor:"lightgreen"}}> 
       </View> 
     </View> 
     <View style={{width: 300, height: 300, backgroundColor:"gold", flexDirection:'row'}}> 
       <View style={{width: 100, height: 100, backgroundColor:"indigo"}}> 
       </View> 
       <View style={{width: 100, height: 100, backgroundColor:"lightgreen"}}> 
       </View> 
     </View> 
   </View> 
 );

두번째 노란색 View에 flexDirection을 'row'로 지정하니 하위(자식) View들이 가로 정렬 되었습니다.

그리고 이 flexDirection과 중앙 정렬이 연관됩니다.

기본적으로 View를 통한 Alignment(정렬)을 적용할 땐 딱 두가지만 기억 하면 됩니다.(물론 세분화하면 다른 것도 알아야 겠지만...)

- flexDirection이 column 일 때(없을 때)
- 객체의 상하 정렬을 할 때는 상위(부모) View에 justifyContent
- 객체의 좌우 정렬을 할 때는 내 자신 View에 alignSelf

- flexDirection이 row 일 때
- 객체의 좌우 정렬을 할 때는 상위(부모) View에 justifyContent
- 객체의 상하 정렬을 할 때는 내 자신 View에 alignSelf

이 두가지만 기억하면 됩니다.

 return ( 
   <View> 
     <View style={{width: 150, height: 150, backgroundColor:"gold", marginBottom:10, justifyContent:'center'}}> 
       <View style={{width: 100, height: 100, backgroundColor:"indigo"}}> 
       </View> 
     </View> 
     <View style={{width: 150, height: 150, backgroundColor:"gold", marginBottom:10}}> 
       <View style={{width: 100, height: 100, backgroundColor:"indigo", alignSelf:'center'}}> 
       </View> 
     </View> 
     <View style={{width: 150, height: 150, backgroundColor:"gold", marginBottom:10, flexDirection:'row', justifyContent:'center'}}> 
       <View style={{width: 100, height: 100, backgroundColor:"indigo"}}> 
       </View> 
     </View> 
     <View style={{width: 150, height: 150, backgroundColor:"gold", marginBottom:10, flexDirection:'row'}}> 
       <View style={{width: 100, height: 100, backgroundColor:"indigo", alignSelf:'center'}}> 
       </View> 
     </View> 
   </View> 
 );

flexDirection의 방향에 따라 justifyContent와 alignSelf의 방향이 바뀐다고 보시면 됩니다.

 

그리고 이제 복수의 View가 있을 경우 justifyContent의 값에 따라 배열이 바뀌게 됩니다.
각종 실제로 가장 많이 쓰이는 기능입니다.

return ( 
  <View style={{flexDirection:'row'}}> 
    <View style={{margin:10}}> 
      <Text>center</Text> 
      <View style={{width: 100, height: 130, backgroundColor:"gold", marginBottom:10, justifyContent:'center'}}> 
        <View style={{width: 30, height: 30, backgroundColor:"indigo"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"lightgreen"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"crimson"}}> 
        </View> 
      </View> 
      <Text>flex-start</Text> 
      <View style={{width: 100, height: 130, backgroundColor:"gold", marginBottom:10, justifyContent:'flex-start'}}> 
        <View style={{width: 30, height: 30, backgroundColor:"indigo"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"lightgreen"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"crimson"}}> 
        </View> 
      </View> 
      <Text>flex-end</Text> 
        <View style={{width: 100, height: 130, backgroundColor:"gold", marginBottom:10, justifyContent:'flex-end'}}> 
        <View style={{width: 30, height: 30, backgroundColor:"indigo"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"lightgreen"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"crimson"}}> 
        </View> 
      </View> 
    </View> 
    <View style={{margin:10}}> 
      <Text>space-around</Text> 
      <View style={{width: 100, height: 130, backgroundColor:"gold", marginBottom:10, justifyContent:'space-around'}}> 
        <View style={{width: 30, height: 30, backgroundColor:"indigo"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"lightgreen"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"crimson"}}> 
        </View> 
      </View> 
      <Text>space-between</Text> 
      <View style={{width: 100, height: 130, backgroundColor:"gold", marginBottom:10, justifyContent:'space-between'}}> 
        <View style={{width: 30, height: 30, backgroundColor:"indigo"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"lightgreen"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"crimson"}}> 
        </View> 
      </View> 
      <Text>space-evenly</Text> 
      <View style={{width: 100, height: 130, backgroundColor:"gold", marginBottom:10, justifyContent:'space-evenly'}}> 
        <View style={{width: 30, height: 30, backgroundColor:"indigo"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"lightgreen"}}> 
        </View> 
        <View style={{width: 30, height: 30, backgroundColor:"crimson"}}> 
        </View> 
      </View> 
    </View> 
  </View> 
 );

일단 flexDirection을 지정하지 않아 내부 View들이 세로로 정렬되고 각각의 View에 alignSelf 값을 넣지 않아 왼쪽으로 정렬되어 있습니다. 왼쪽 세가지 정렬방식은 각각 중앙, 시작(flexDirection에 따라 상단이 될 수 있고 왼쪽이 될 수도 있습니다.) 그리고 오른쪽 정렬방식은 각각 space-around의 경우 각각의 View들이 양 옆(위아래)으로 동일한 여백을 가진 상태로 정렬을 하고 space-between의 경우 처음과 끝 View의 경우 끝에 붙고 나머지 객체들이 동일한 여백을 갖게 됩니다. 그리고 space-evenly는 모두 동일한 여백을 갖습니다. space-evenly와 space-between의 경우가 가장 자주 쓰일듯 합니다. 물론 center와 함께...

위의 항목들만 알면 기본적인 레이아웃 구성은 할 수 있을듯 합니다. 하지만 여기서 좀 더 추가적인 기능을 알아봅시다.

 

먼저 elevation (안드로이드만 가능) 기능입니다.

 return ( 
   <View style={{flexDirection:'row'}}> 
     <View style={{width: 300, height: 600, backgroundColor:"gold", marginBottom:10, justifyContent:'space-evenly'}}> 
       <View style={{width: 80, height: 80, backgroundColor:"lightgreen", alignSelf:'center', }}> 
       </View> 
       <View style={{width: 80, height: 80, backgroundColor:"lightgreen", alignSelf:'center', elevation:5}}> 
       </View> 
       <View style={{width: 80, height: 80, backgroundColor:"lightgreen", alignSelf:'center', elevation:20}}> 
       </View> 
       <View style={{width: 80, height: 80, backgroundColor:"lightgreen", alignSelf:'center', elevation:50}}> 
       </View> 
     </View> 
   </View> 
);

개인적으로 그림자 효과가 강하지 않아서 크게 좋아하진 않지만 그런대로 입체감을 줄 수 있습니다.

그럼 보다 더 적극적으로 그림자 효과를 내 봅시다. 아예 똑같은 크기의 색은 다른 View를 만들어 살짝 포지션을 바꿔서 배치합니다. 바로 position : 'absolute' 를 이용합니다. View 두개를 겹치는 것입니다.

return (
  <View style={{flexDirection:'row'}}> 
    <View style={{width: 300, height: 600, backgroundColor:"lightgreen"}}> 
      <View style={{width: 80, height: 80, backgroundColor:"gold"}}> 
      </View> 
      <View style={{position:'absolute', top:5, left:5, width: 80, height: 80, backgroundColor:"gray"}}> 
      </View> 
    </View> 
  </View> 
);

position : 'absolute' 는 항상 이어서 위치 정보를 추가로 입력합니다. 위의 코드에서는 top : 5, left : 5를 주어 위와 왼쪽 끝부터 5픽셀씩 이동 후 View를 보여주는 것입니다. 하지만 absolute를 적용한 View의 경우 맨 앞에 와버리게 되서 그림자로 쓰려고 한 회색 View가 앞으로 튀어나와 버렸습니다.

 

이런 경우 zIndex 값을 써서 직접 레이어를 적용하면 됩니다. 큰수일수록 앞으로 작은수일수록 뒤로 layer가 형성됩니다.

return ( 
  <View style={{flexDirection:'row'}}> 
    <View style={{width: 300, height: 600, backgroundColor:"lightgreen"}}> 
      <View style={{width: 80, height: 80, backgroundColor:"gold", zIndex:1}}> 
      </View> 
      <View style={{position:'absolute', top:5, left:5, width: 80, height: 80, backgroundColor:"gray", zIndex:0}}> 
      </View> 
    </View> 
  </View> 
);

이제 뚜렷한 그림자가 완성 되었습니다.

이정도면 기본적인 기능들은 모두 익힌 셈이며 일반적인 레이아웃 디자인은 할 수 있습니다.

이제 내 휴대폰에 설치한 수많은 앱들의 디자인을 보며 react native로는 어떻게 구현할지 생각해보면 좋은 연습이 될 듯 합니다.

+ Recent posts