React_ChakraUI

김귤·2023년 2월 21일
0

REACT

목록 보기
3/3

7개월 간 리액트를 공부하면서 가장 많이 쓰고 있는 템플릿에 관한 글이다.
사실 리액트를 직접 만지기 전 까진 쓰기는 커녕 존재 자체도 몰랐던 것들이다.
자바 스크립트를 이용하면서도 라이브러리 정도를 사용해봤지만, 스크립트로 짜여진 템플릿을 써본 경험은 극히 드물었다.

당시 사수의 영향도 있었다.
뭐든지 직접 만드는 것이 최우선이었고 무엇보다도 유지보수에 불리한 것이 바로 템플릿이다.
내가 직접 짜서 만든 것이 아니기 때문에 수정보완하는데 힘들다나.

그치만 모든 것을 일일이 직접 만들수는 없는 노릇이다.
템플릿의 무궁무진한 세계에 빠진다면 더 효율적이고 더 좋은 화면과 기능을 만듦과 동시에 시간도 절약되기 때문이다.

리액트 역시 마찬가지다.
특히나 규칙이 엄격하고 통제가 심한 이 세계는 템플릿의 영향이 더욱 중요하다고 본다.
그 무시무시한 제약을 다 통과하고 통용되는 템플릿이니, 더 확신을 가질 수 있지 않은가!

Chakra UI란?


후에 언급될 두 가지보다 더 자주 쓰이는 리액트 컴포넌트를 구성하는 스타일링 라이브러리이다. 쉽고 수월하고 빠른 인터페이스를 구성할 수 있도록 지정된 시스템이다. 리액트에서 구성되어 있기에 리액트 전용 라이브러리로 보면 된다.
차크라에 대한 설명과 설치방법, hook과 components등은 차크라 홈페이지(https://chakra-ui.com/) 참고하여서 사용한다면 더욱 효율적으로 사용할 수 있다.

Chakra UI의 특징

1. 각 기능(스타일)에 맞게 설정된 component

흔히 html엘에서 말하는 태그(tag)가 하나의 컴포넌트가 되어서 사용할 수 있다. 각 컴포넌트에 따라서 그것에 담겨진 의미, 기능 및 쓰임이 달라진다. 이용해봤던 컴포넌트 몇 가지로 그 예시를 다뤄볼까 한다.

  • Box
    : ChakraUI에서 가장 쉽고 보편적으로 사용할 수 있는 컴포넌트이다. 그러므로 흔히 많이들 알고 있는 div의 개념으로 이해하면 된다. inline요소, block요소 상관없이 자유자재로 쓸 수 있었다. as라는 props를 통해서 그 기능을 변환할 수 있는 특징이 있다.
<Box flex="1" bg="">
	<SimpleGrid columns={2} marginLeft="40px" width="300px">
		<Box width="150px" height="80px" className="cursor"></Box>
	</SimpleGrid>
 </Box>

- Number Input
: Input이라는 점이 가장 큰 특징인 컴포넌트이다. 그러나 나에게 차크라 UI의 장점이자 단점을 가장 잘 알려준 컴포넌트이다. 숫자값을 증가하고 감소하는 것을 통제하는 Input이라고 생각하면 된다.

<Text>
  {min_qty > 0 ? (
    <NumberInput
      width="120px"
      defaultValue={min_qty}
      min={min_qty}
      max={max_qty}
      step={multiple}
      onChange={handleChange}
    >
      <NumberInputField />
      <NumberInputStepper>
        <NumberIncrementStepper />
        <NumberDecrementStepper />
      </NumberInputStepper>
    </NumberInput>
  ) : (
    ""
  )}
  </Text>

NumberInput은 전체요소를 감싸는 큰 틀이며, NuberInputField는 숫자를 입력하는 input이다. NumberIncrementStepper/NumberDecrementSteper은 뜻 그대로 숫자를 증가하고 감소하는 버튼이며, NumberInputStepper은 이 두가지를 감싸는 틀이다. 즉, 이것은 숫자를 입력하고 증가하고 감소하는 하나의 큰 Input Box인 셈이다.

또한 NumberInput에서 가장 많이 쓰이는 props가 있다. minmax는 해당하는 값의 최소값과 최대값이다. 즉, 특정 숫자 이하와 이상 감소할수도 증가할 수도 없다. step은 값이 증가하고, 감소하는 숫자의 단위이다. 5를 입력하면 5만큼 증가하고 감소한다는 뜻이다. defaultValue는 Number Input의 초기값이다.

그러나 가장 큰 문제점은 바로 min값과 max값과 step의 매칭이었다. value값이 최대값 max를 넘어간 후 다시 값을 내리면 최대값 - step으로 남어가는 것이다.

총 재고 개수 : 21개
step : 5개씩 구매가능
(구매가능) 최소값 : 5개
(구매가능) 최대값 : 20개

인 상황에서. 최대값이 21개를 찍은 후, 다시 NumberDecrementStepper 키를 누르게 되면, 15개가 아닌 16개가 NumberInput에 찍히게 된다. 이것을 수정하기 위해 NumberInput 컴포넌트 자체를 수정하려고 했으나, 코드 상에서나 props에서나 효과적으로 수정할 수 있는 방법은 없었다.

async function clickPayment() {
	// 구매수량과 구매단위 일치 불일치 공식
    // 구매수량과 구매단위이 불일치할 때
    if (data.quantity % multiple != 0) {
      // 구매수량을 구매단위로 나눴을 때 나머지가 있는 상태일 때
      alert("구매단위에 벗어나는 수량입니다.");
      // 구매수량과 구매단위가 일치할 때
    } else if (data.quantity % multiple === 0) {
      // 구매수량을 구매단위로 나눴을 때 나머지가 없는 상태일 때
      // api 및 token값 설정 후, 장바구니에 상품이 담도록 하는 로직
      if (res.data.status === 201) {
        var result = window.confirm(
          "장바구니에 저장되었습니다. 장바구니로 이동할까요?"
        );
        // 장바구니에 이동
        if (result) {
          window.location.href = "/cart/view";
        }
        // 최대 구매수량을 초과했을 때 발생
      } else {
        alert("장바구니 저장중 오류가 발생했습니다. \n사유 : " + res.data.msg);
      }
      return;
    }
}

결국, 결제를 담당하는 버튼에서 step에 맞지 않는 값이 나올 경우 다음 페이지로 넘어갈 수 없도록 로직을 수정하였다.

  • Center/Flex
    : 이름 그대로 Center는 레이아웃 속의 내용이 자동적으로 중간 정렬이 되며, Flexdisplay:flex의 성질을 담고 있어서 자식 요소가 가로 일렬로 나열되는 것이다.
 <Flex w="1000px" margin="0 auto">
  <Box flex="1" bg="" pt={10} pb={10}>
    <Heading as="h4" size="md" mb={5}>
      무엇을 도와드릴까요?
    </Heading>
    <Box fontSize="md" className="footer-contact">
      <Box
        className="footer-contact__text-box "
        style={{ display: "flex" }}
        m="2% 0"
      >
        <Text flex="0.4">평일(월~목)</Text>
        <Text flex="0.42">09:00 ~ 18:00</Text>
        <Text flex="0.8"></Text>
      </Box>
      <Box
        className="footer-contact__text-box "
        style={{ display: "flex" }}
        m="2% 0"
      >
        <Text flex="0.4">평일(금요일) </Text>
        <Text flex="0.42">09:00 ~ 17:00</Text>
        <Text flex="0.8">(주말 및 공휴일 휴무)</Text>
      </Box>
      <Box
        className="footer-contact__text-box "
        style={{ display: "flex" }}
        m="2% 0"
      >
        <Text flex="0.4">점심시간 </Text>
        <Text flex="0.42">12:30 ~ 13:30</Text>
        <Text flex="0.8"></Text>
      </Box>
    </Box>
  </Box>
  <Box flex="1" bg="" pt={10} pb={10}>
    <Center as="h4" size="md" mb={5}>
      공지사항
    </Center>
    <List>
      {notice.length > 0
        ? notice.map((e) => (
            <Link href="/board/notice" key={e.wr_id}>
              <ListItem
                marginTop="5px"
                className="footer-notice"
                key={e.wr_id}
              >
                {e.wr_subject}
              </ListItem>
            </Link>
          ))
        : ""}
    </List>
  </Box>
  </Flex>
  • Text
    : html내에서 p의 역할을 담당하는 컴포넌트라고 보면 된다. 개념으로만 보면 전혀 설명에 추가될 필요가 없는 컴포넌트지만 치명적인 오류가 있다.

    Text 컴포넌트를 p 태그로 이해한 이유는 마찬가지로 inline 요소이기 때문에 이런 에러가 생긴다고 판단하였다. inline 요소 내에 Block은 물론 inline 요소를 포함할 수 없기 때문이다. 해당 오류는 Box 혹은 Badge로 변경하면서 해결하였다. (Badge 마찬가지로 block 요소인 span 태그처럼 이해한다.)

2.컴포넌트 속 props로 style요소 설정

html의 태그와 마찬가지로 style 속성을 직접 입력할 수 있다. 그러나 style 속성으로 넣을 수 있는 것이 제한적이며, 단축어처럼 사용된다.

 <Box
  bg=""
  borderTop="1px"
  borderColor="#ededed"
  w="100%"
  p={0}
  mb={5}
  color="#a3a5ad"
  fontSize={12}
  letterSpacing={-0.5}
  >
    <Stack
      direction="row"
      spacing={5}
      align="center"
      mt="5"
      mb="5"
      w="1000px"
      margin="0 auto"
    >
      <Link href="/policy/service">
        <Text colorScheme="gray" variant="ghost" p="2">
          이용약관
        </Text>
      </Link>
      <Link href="/policy/privacy">
        <Text colorScheme="gray" variant="ghost" p="2">
          개인정보처리방침
        </Text>
      </Link>
      <Link
        href="https://www.ftc.go.kr/www/bizCommList.do?key=232"
        target="_blank"
      >
        <Text colorScheme="gray" variant="ghost" p="2">
          사업자정보확인
        </Text>
      </Link>
      <Link
        href="https://mark.inicis.com/mark/escrow_popup.php?mid=pandapart1"
        target="_blank"
        rel="noopener"
      >
        <Text colorScheme="gray" variant="ghost" p="2">
          에스크로가입확인
        </Text>
      </Link>
      <Link
        href="https://www.ilogen.com/web/reservation/returns"
        target="_blank"
        rel="noopener"
      >
        <Text colorScheme="gray" variant="ghost" p="2">
          AS배송예약
        </Text>
      </Link>
    </Stack>
    <Text w="1000px" margin="0 auto" paddingTop="7">
      </br>
      Copyright © 2018. All rights reserved.
    </Text>
  </Box>

해당 예시만 style 요소가 단축어처럼 축약되어서 사용된다. widthheightwh, margin, padding, background는 각각 m, p, bg로 쓰인다. 또한 top/bottom/left/right 역시 margin/padding과 결합될 때 mt/mb/ml/mr 혹은 pt/pb/pl/pr처럼 축약된다. 아울러 두 가지의 단어로 합쳐진 style의 경우 카멜 표기법처럼 축약된다. min-width/verical-align/overflow-x의 경우처럼 minWidth/vericalAlign/overflowX처럼 처음이 아닌 다음번에 오는 단어가 대문자 형태로 나타난다. 그러므로 여러가지 props를 사용할 땐 암기해두는 것이 좋다.

0개의 댓글