5월 1~2주차. 조건부 렌더링과 반응형 웹

변현섭·2024년 5월 3일
0

다우데이타 인턴십

목록 보기
14/17
post-thumbnail

1. 조건부 렌더링을 이용한 탭 레이아웃 구현

반응형 웹은 조건부 렌더링과 깊은 연관이 있다. 따라서, 조건부 렌더링을 이용한 탭 레이아웃 구성을 먼저 진행해보기로 한다.

① Tab.jsx 파일을 생성하고 아래의 내용을 입력한다.

import { useState } from 'react';
import styled from 'styled-components';

const TabMenu = styled.ul`
  width: calc(100% - 350px);
  background-color: #ffffff;
  color: #333;
  font-weight: bold;
  display: flex;
  flex-direction: row;
  align-items: center;
  list-style: none;
  padding: 0;
  border-radius: 10px;
`;

const MenuItem = styled.li`
  flex: 1;
  padding: 10px;
  text-align: center;
  cursor: pointer;
  transition: background-color 0.3s, color 0.3s;
  color: #000000;
  font-size: 22px;
  border-radius: 10px;
  &:hover {
    background-color: #f0f0f0;
    color: #0067A3;
  }

  &.focused {
    background-color: #0067A3;
    color: #ffffff;
  }
`;

const Tab = ({ menuItems, setCurrentTab }) => {
  const [selectedTab, setSelectedTab] = useState(0);

  const selectMenuHandler = (index) => {
    setCurrentTab(index);
    setSelectedTab(index);
  };

  return (
    <div>
      <TabMenu>
        {menuItems.map((item, index) => (
          <MenuItem
            key={index}
            className={index === selectedTab ? "focused" : ""}
            onClick={() => selectMenuHandler(index)}
          >
            {item}
          </MenuItem>
          
        ))}
      </TabMenu>
    </div>
  );
};

export default Tab;

② 탭 레이아웃을 적용할 jsx 파일에 아래의 내용을 추가한다.

  • currentTab의 값을 useState 훅을 이용해 관리하고, currentTab의 값에 맞는 화면을 렌더링(조건부 렌더링)한다.
function RegisterPage(props) {

    const [currentTab, setCurrentTab] = useState(0);
	...
    
	return (
    	<Wrapper>
			<Tab 
                menuItems={['스케줄링 등록', '스케줄링 목록']}
                setCurrentTab={setCurrentTab}
            />
            {currentTab === 0 && (
            	// 첫번째 탭을 클릭했을 때 나타날 화면
                ...
            )}
            {currentTab === 1 && (
            	// 두번째 탭을 클릭했을 때 나타날 화면
                ...
            )}
        </Wrapper>
    );
}

2. 반응형 웹

웹 페이지는 모바일, 태블릿, PC 등 다양한 디바이스에서 접근 가능하므로, 해상도와 무관하게 항상 우수한 UI/UX를 제공할 수 있어야 한다. 이러한 원칙에 따라 설계된 웹 어플리케이션을 반응형 웹이라 하는데, 반응형 웹을 만드는 방법은 media query를 사용하는 방법과 react-responsive를 사용하는 방법으로 구분된다.

1) Media Query

Media Query는 아래와 같은 형태를 취한다.

@media only screen and (min-width: 400px) {
	...
    
}

이제 위 쿼리의 의미를 해석하기 위해 Media Query의 구성요소에 대해 알아보자.

① 스타일 적용 대상

  • only: 뒤에 나오는 조건(미디어 타입, 속성)을 만족하는 경우에 대해 스타일을 적용한다.
  • not: 뒤에 나오는조건을 만족하지 않는 경우에 대해 스타일을 적용한다.

② 미디어 타입

  • all : 모든 미디어 타입
  • aural : 음성 합성 장치
  • braille : 점자 표시 장치
  • handheld : 손으로 들고 다니면서 볼 수 있는 작은 스크린에 대응
  • print : 인쇄 용도
  • projection : 프로젝터
  • screen : 컴퓨터 스크린
  • tty : 디스플레이 능력이 한정된 릴랙스, 터미널, 수동 이동 장치 등 고정된 글자를 사용하는 미디어
  • tv : 음성과 영상이 동시에 출력되는 장치
  • embrossed : 페이지에 인쇄된 점자 표시 장치

③ 속성

  • width : 웹 페이지의 가로길이
  • height : 웹 페이지의 세로 길이
  • device-width : 단말기의 가로길이
  • device-height : 단말기의 세로 길이
  • orientation : 가로모드 및 세로모드 설정
  • aspect-ratio : width / height 비율
  • device-aspect-ratio : 단말기의 물리적인 화면 비율
  • color-index : 단말기에서 사용하는 최대 색상 수
  • monochrom : 흑백 컬러만을 사용하는 단말기에서 흰색과 검은색 사이의 단계
  • resolution : 지원하는 해상도
  • color : 단말기에서 사용하는 최대 색상 수의 비트 수를 2의 지수 형태로 표현

즉, 위 쿼리는 화면 View Port의 너비가 400픽셀 이상인 경우에 적용할 스타일을 정의하겠다는 의미인 것이다. 이를 통해 다양한 해상도의 디바이스에 접근하더라도 해상도에 알맞은 UI를 제공할 수 있게 된다.

2) React Responsive

사실 Media Query를 사용하는 방법보다는 react-responsive 모듈을 import 하는 방식이 더 편리하다. react-responsive의 사용법은 아래와 같다.

① 아래의 명령을 이용해 react-responsive 모듈을 설치한다.

npm install react-responsive

② 이제 해상도에 따라 UI를 다르게 보여주기 위해, 현재 접속한 디바이스가 PC인지 모바일인지를 해상도를 통해 구분하는 컴포넌트를 만든다.

import React from 'react';
import {useMediaQuery} from 'react-responsive';

export const Mobile = ({children}) => {
  const isMobile = useMediaQuery({
    query : "(max-width:768px)"
  });
  
  return <>{isMobile && children}</>
}

export const PC = ({children}) => {
  const isPc = useMediaQuery({
    query : "(min-width:769px)"
  });
  
  return <>{isPc && children}</>
}

③ 이제 반응형 UI를 제공할 페이지에 가서 아래와 같이 코드를 수정한다.

  • 여기서는 PC에서는 기존 코드를 유지하고, 모바일에서는 간단한 텍스트를 출력하도록 만들었다.
import React, { useState } from 'react';
import { Mobile, PC } from './ResponsiveComponents';
...

function MainPage(props) {
	return (
        <CenterWrapper>
            <Mobile>
                <p>모바일 화면으로 인식</p>
            </Mobile>
            <PC>
            	...
            </PC>
                
        </CenterWrapper>
    );
}

④ 실행결과를 확인한다.

  • PC에서 직접 창의 크기를 줄이거나 F12 키를 누른 후 Toggle device toolbar 버튼을 클릭하여 반응형 웹 적용 여부를 확인할 수 있다.

여기서는 두가지 방법을 모두 사용하여 아래와 같이 MainPage를 반응형 웹으로 구성하였다. 웹 페이지가 축소되는 상황에도 반응할 수 있도록 Responsive 컴포넌트를 아래와 같이 수정하였다.

import React from 'react';
import {useMediaQuery} from 'react-responsive';

export const Mobile = ({children}) => {
  const isMobile = useMediaQuery({
    query : "(max-width:480px)"
  });
  
  return <>{isMobile && children}</>
}

export const HalfScreen = ({children}) => {  // PC에서 화면 축소
  const isHalfScreen = useMediaQuery({
    query: "(min-width: 481px) and (max-width: 1080px)"
  });
  
  return <>{isHalfScreen && children}</>
}

export const PC = ({children}) => {
  const isPc = useMediaQuery({
    query : "(min-width:1081px)"
  });
  
  return <>{isPc && children}</>
}

화면 크기에 따라 텍스트나 이미지 뷰의 크기가 동적으로 달라지기 때문에, 반드시 너비와 폰트 크기에 상한이 존재해야 한다. 여기서는 너비 제한(또는 높이 제한)은 min-width(min-height)max-width(max-height)로 설정하였으며, font-size 제한은 아래와 같이 미디어 쿼리를 이용해 설정하였다.

const TitleText = styled.p`
    font-size: 18px;
    font-weight: 700;
    height: auto;
    @media (max-width: 1080px) { // 큰 경우를 먼저 작성해야 함
        font-size: 16px; 
    }
    @media (max-width: 480px) {
        font-size: 14px; 
    }
`;

아래는 완성된 화면이다.

profile
LG전자 Connected Service 1 Unit 연구원 변현섭입니다.

0개의 댓글