조금조금 REACT, 폴더구조 및 리액트 코딩컨벤션

Edwin·2023년 2월 28일
3

조금조금 REACT

목록 보기
8/31
post-thumbnail

개발자들의 암묵적인 규칙

이러한 부분에 대해서까지 사용 설명서는 언급하지 않지만, 관행이라는 것은 중요하고 따라야 하는 부분이다. 그러한 부분의 대표적인 두 가지가 파일의 이름을 기록하는 코딩 컨벤션과 폴더의 구조를 만드는 내용이다. 먼저 폴더구조에 대해서 살펴보자.

01 컴파운드 컴포넌트 패턴

개발 코린이가 작업을 시작하면 파일의 몸집은 방대해지기 마련이다. 그 결과 발생되는 문제는 유지보수에 있어서 어떤 부분을 손봐야 하는지, 어디에 무엇을 기록했는지 찾기가 어려워진다는 점이다. 이러한 코린이들의 고민들에서 등장하게 된 내용들이 컴포넌트 패던이라는 부분이며 MVP, MVVM, Viper 등등의 패턴들이 등장하였다. 참고, 마기의 깃허브 즉 "화면에 보여지는 로직과 실제 데이터가 처리되는 로직을 분리"시키는 작업이 컴포넌트 패던의 의미이다.

1) MVC(Model+View+Controller)

Controller : 사용자의 입력을 받고 처리하는 부분이다.

Model : 프로그램에서 사용되는 실제 데이터 및 데이터 조작 로직을 처리하는 부분으로, 데이터를 불러오거나 업데이트를 하는 로직이 담겨 있다.

View : 사용자에게 제공되는 UI 부분이다.

위의 3개의 요소에서 처리하는 일은 1) Controller로 사용자의 입력이 들어오면 2) ControllerModel에게 해당 내용을 전달하고 Model은 전달된 내용을 갱신하여 저장한다. 3) 이후 Model은 갱신되어 저장된 데이터를 View에게 전달하여 화면에 표시하게 된다.

이 패턴은 보는 것과 같이 View와 Model이 서로 의존적인 관계를 형성하고 있다는 점이다. 이런 점에섬에서 서로의 의존성을 줄이고자 하는 고민이 발생되었고, 그 결과로 다음 패턴이 등장하였다.

2) MVP(Model+View+Presenter)

Presenter : Model과 View 사이에서 서로를 조율하는 부분으로, Presenter는 View에서 요청한 정보를 Model로부터 가공해서 다시 View에게 전달한다.

즉 MVP 패턴에서 View와 Model은 동일하지만, 1) MVC 모델과 달리 사용자의 입력을 View를 통해서 받는다. 2) View를 통해서 들어온 입력은 위해 ViewPresenter에게, Presentet는 이를 Model에게 요청하게 된다. 3) 요청에 대한 응답은 역순으로 진행되어 View에게 전달되며, View는 전달받은 데이터를 화면에 출력한다.

그러나 이 패턴을 보면 View가 의존하고 있는 대상이 Model에서 Presenter로 변경되었을 뿐 이전과 의존성의 부분에서 큰 차이가 없게 되었다는 점이다. 그 결과 새로운 패턴이 고안되었다.

3) MVVM(Model+View+ViewModel)

View Model : View를 표현하기 위해 만들어진 Model이다.

MVVM 패턴을 이해하기 위해서는 먼저 Command패턴과 Data Binding에 대해서 이해를 해야 하며, 결과적으로 이 두개의 패턴은 View가 다른 부분들과 형성했던 의존성을 사라지도록 했다는 것이다.

먼저, Command 패턴은 View로부터 들어온 사용자의 입력을 ViewModel에게 직접 명령한다.
둘째, Data Binding 패턴은 앞선 명령에 따라서 ViewModel의 값을 변경하고, 그 변경된 정보에 따라서 View의 정보를 변경시킨다.

이를 상세히 설명하면, 1) View를 통해서 들어온 사용자의 입력은 Command 패턴으로 ViewModel에게 명령을 내리게 된다. 2) ViewModel은 필요한 데이터를 Model 에게 요청하고 Model 은 결과를 다시 ViewModel 에게 전달해 준다. 3) ViewModel 은 전달받은 데이터를 가공해서 저장하게 되는데 이때 Data Binding 으로 인해서 View와 ViewModel 모두 자동으로 갱신된다. 쉽게 말해서 동기화가 이뤄진다는 점으로 의존성을 극복한 경우이다.

항해 매니저님께서 폴더구조를 어떻게 잡는가에 대해서 소개해주신 마기님의 글을 정리한 내용이 이 부분이지만, 아직 감이 오지는 않는다.

4) VAC(View Assent Component)

  • 해당 내용은 위에서 언급되지 않았지만, 항해 매니저님의 추천으로 함께 기록해 본다.

WIT블로그, 박우영님에 따르면, VAC는 프론트앤드 개발에서 렌더링에 필요한 JSX와 스타일을 관리하는 컴포넌트를 의미한다. View는 JSX 영역을 props 객체화하고, JSX를 VAC로 분리해서 개발하는 설계 방법의 일환이다. 그렇다면 근원적인 질문으로 나아가서, 이러한 설개는 왜 하는 것일까?

프론트앤드 개발에서의 View 정보 시각화와 상호작용

먼저 view(여기서 뷰란 화면을 말하는 것 같은데)를 개발하는 것은 3가지로 나눌 수 있음에 대해서 박우영은 정리하였다.

첫째, 사용자의 상호작용을 처리하는 UI의 동적기능 : JS 등
둘째, 데이터나 상호작용의 결과를 시각화하는 렌더링 처리 : 마크업, CSS 등
셋째, 비즈니스 로직, UI기능, 렌더링 처리의 통합 : React, Redux 등

박우영에 따르면, 네이버를 필두로한 많은 회사들이 디자인 영역과의 협업에 해당하는 "위에서 언급한 둘째" 영역과 "첫째/셋째" 영역을 다시 구분하고, 전자는 UI(마크업) 개발부서, 후자는 프론트앤드개발 부서로 구분한다고 한다. 그러나 React는 컴포넌트 자체가 JSX로 렌더링하기 때문에, 첫째와 둘째가 혼합된 형태로 개발이 이루어진다.

그러나 이러한 형태는 만약 후자가 코드를 완료한 시점에서 JSX를 두고 전자와 충돌이 발생되었을 때, 이를 수정하는 것이 결코 쉬운 문제가 아니라는 점에서 긴장을 준다. 이러한 문제를 해결하고자 등장한 개념이 VAC 패턴이다. 풀어서 설명하면 React 환경에서 UI개발자와 FE개발자 사이에서, View컴포넌트에서 JSX 영역을 분리한 것이다. 아래의 코드로 예제를 설명하는데 한 번 리액트에서 이를 실행시켜 보자.

import React, {useState} from 'react'

export default function App() {
  return (
    <Article>
      <SpinBox></SpinBox>
    </Article>
  )
}
// View Component

const SpinBox = () => {
  const [value, setValue] = useState(0);

  const props = {
    value,
    onDecrease: () => setValue(value - 1),
    onIncrease: () => setValue(value + 1),
  };

  // JSX를 VAC로 교체
  return <SpinBoxView {...props} />;
};

// VAC
const SpinBoxView = ({ value, onIncrease, onDecrease }) => (
  <div>
    <p><span>{value}</span></p>
    <Button onClick={onDecrease}>-</Button>
    <Button onClick={onIncrease}>+</Button>
  </div>
);

약간의 가독성을 위해서 CSS를 주었다. 이때 React 라이브러리 가운데 하나인 'styled-componets'로 디자인을 주었다.

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

export default function App() {
  return (
    <Article>
      <SpinBox></SpinBox>
    </Article>
  )
}

const Article = styled.div`
  width: 500px;
  height: 200px;
  margin: 0 auto;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;

  p {
    font-size: 50px;
    margin: 0;
    margin-bottom: 10px;
  }
`

const Button = styled.button`
width: 100px;
height: 30px;
font-size: 20px;
margin: 0 5px;
`

VAC 패턴

VAC의 특징은 (1) 오직 props를 통해서만 제어가 된다는 점이며, state를 관리하거나 변경하지 않는 컴포넌트라는 점이다. 즉 이벤트에 함수를 바인딩할 때 어떤 추가적인 작업을 기록하지 않는다. (2) 그러나 자식컴포넌트에서 state를 가지는 것은 가능하다.

일단은 여기까지. 내용는 더 있지만 감당할 수 없어서, 여기까지만 오늘은 공부하고자 한다.

02 코딩 컨벤션

카카오 페이지 웹 역시 기반은 리액트이기에, 컴포넌트 작성시 JSX 문법을 사용한다. 정호일님은 2022년 5월 당시적 상황에서 카카오 페이지 역시 흥행하고 있던 Container-presentational 패턴을 따랐지만, 몇 가지 문제를 맞닥뜨렸고, 그 결과 새로운 대안을 찾아야 했다면서 해당 포스트를 작성하였다.

1) 컴포넌트의 파편화문제

문제의 시작은 디자인시스템 내에서 관리되지 않은 버튼에 대한 이슈였다. 만약 명확한 컴포넌트 설계에 대한 기준이 미비하다면, 관리되지 않은 버튼을 유지보수 하는 부분에 있어서 어려움을 겪게 될 것이다.

2) Atomic design

카카오 페이지팀은 디자인 시스템을 통해 서비스의 고유한 타이포그래피, 컬러 팔레트 등을 고려하여 공통 컴포넌트를 만듦으로 이를 해결하였다. 그리고 이러한 디자인 시스템 방법론을 아토믹 디자인이라고 부른다. 이 개념은 Brad Frost가 제안한 것인데, 그는 디자인 시스템에 대해서 어떤 조직이 디지털 인터페이스를 디자인하고 구축하는 방식이며, 아토믹 디자인은 이러한 디자인 시스템을 만드는 하나의 방법론인 것이다.참고, Brad Frost Brad Frost은 화학적 관점에서 즉 "원자"(atom->Molecule->Organism)에서 영감을 받아 이러한 디자인 시스템을 고안하였다. 그는 컴포넌트에 이 개념을 도입하여 (1) atom (2) molucule (3) organism (4) tempalte (5) page 로 전개되는 5단계 레벨을 세웠다.

(1) Atom

컴포넌트에 있어서 가장 작은 단위이다. label, input, button과 같이 HTML elemnt 태그 혹은 글꼴, 애니메이션, 컬러 팔레트, 레이아웃과 같은 추상적인 요소들이 될 수 있다. 이는 개발환경에서 모든 기본 스타일을 한눈에 보여주는 것임으로 디자인 시스템의 유용한 조각들이 될 수 있다.

(2) Molecule

여러 개의 atoms 을 결함하여 자신만의 고유한 특징을 구성한다. atom[input]atom[button]을 결합하고 이를 atom[form] 안에 구성함으로 하나의 의미있는 단위의 블럭구성을 만들어 낼 수 있다. 이렇게 정의된 Molecule는 재사용성이 만들어진다는 점에서 유용하게 활용될 수 있다. 이를 통해서 UI는 일관성을 가질 수 있게 되는 것이다.

(3) Organism

Organism은 Molecules 의 결합이다. 예를 들어서 이는 Header를 작성하는 것으로 atom[logo]Molecule[navigation]Molecule[search form]으로 구성된 조직을 만들어내는 단위를 말한다.

그러나 이러한 Orgaism은 구체적인 특성을 지니게 되기에 상대적으로 재사용성이 떨어진다는 특징을 가진다.

(4) Template

템플릿은 page를 구성하기 위해 여러개의 Organism+Molecule을 포함한다. 그러나 실제 콘텐츠는 없다. 다만 컴포넌트를 레이아웃하고 구조를 잡은 와이어 프레임의 역할을 수행한다.

(5) Page

페이지는 실제로 유저가 볼 수 있는 콘텐츠를 담은 것이다.

정리해보자.

그러나 아토믹 디자인은 선형(atom->Molecule->Organism)으로만 나아가는 과정이 아니라, UI를 위한 여러 요소들 전체 또는 일부분에 대한 수집을 지향하는 모델이다. 이를 멘탈 모델이라고 한다. 그러나 이를 실제로 구현하는 것은 또다른 문제이다.

3) Atomic design와 카카오 페이지

컴포넌트 구성에 대한 내용은 위에서 언급한 링크를 참조하길 바라며, 이곳에서는 이러한 고민의 결과로 등장한 컴포넌트의 네이밍에 대한 아이디어와 렌더링 이미지만 참고하려 한다.

<Comment>
  <div>
    <Comment.ProfileImage />
    <Comment.Name />
    <Comment.Info />
  </div>
  <Comment.Content />
  <div>
    <Icon type={IconType.Heart} />
    ...
  <div />
</Comment>

아토믹 컴포넌트를 구성하는 원천, 디자이너가 작성한 피그마

카카오 페이지 웹에서는 피그마를 이용하여 UI 모델링을 진행한다. 이를 기반으로 아토믹 컴포넌트로 나아가근데, 이때 아토믹 단위에 대해서 팀원간의 소통을 통해서 그 기준을 하나씩 마련해 나간다고 한다. 그러나 기억할 것은 단 한 번의 모델링으로 이상적인 아토믹 디자인 단위를 나눌 수 없다는 것이다. UI모델링 이외도 지속적인 커뮤니케이션, 긴밀한 피드백을 통해서 이상적인 아토믹 디자인 구조로 나아가야 하는 것이다.

그러나 아토믹 디자인이 하나의 모델이라는 것을 기억해야 한다는 것이 카카오페이지웹의 결론이다. 즉 협업의 자리에서는 이상적인 모델을 차용하되, 수정변경을 통해서 협업에 적합한 모델로 가공하는 것이 필요하다는 것이다. 그러나 이럴 때 더 중요한 것이 네이밍을 어떻게 구성하는가이고, 네이밍은 다시 영어공부와 연결되는 것 같다.

Editor. EDWIN.
data. 23/02/28

profile
신학전공자의 개발자 도전기!!

0개의 댓글