티스토리 뷰

리액트에서는 이벤트를 어떻게 처리할까요? -> 합성이벤트 객체로 래핑해서 사용합니다.

📌이벤트 핸들링에 관련된 자세한 내용은 리액트 데브 문서를 읽어보는 것을 추천합니다. 

🔺우선 리액트의 컴포넌트에는 이벤트 설정을 할 수 없습니다. DOM요소(div, form, button 등..)에만 이벤트 설정이 가능하죠.

React 합성 이벤트(Synthetic Event)

  • 브라우저마다 이벤트 이름부터 시작하여 이벤트가 처리되는 방식이 다릅니다. 이를 동일하게 처리하기 위해 React는 Synthetic 이벤트로 브라우저마다 다른 native 이벤트를 묶어서 처리하는데 이를 통해 크로스 브라우징 문제를 해결하였죠. (리액트 합성 이벤트는 래퍼 이벤트 객체라고 생각하면 됩니다.) 
  • 자세한 내용은 최근에 개편된 리액트 docs를 참고해보세요. -> 리액트 데브 문서(합성 이벤트)

리액트 이벤트 전파

모든 이벤트는 React에서 전파되지만 onScroll(JSX 태그에 붙은 onScroll에서만 동작하는 이벤트)만 제외됩니다. 

  • 전파를 막는 방법으로는 event객체의 stopPropagation()을 권하고 있습니다. 

리액트에서 이벤트 캡처링 활용하기

이벤트 캡처링은 거의 사용되지 않지만 자식 요소들의 이벤트를 모두 추적해야할 때가 있습니다. 예를 들어, 모든 클릭 이벤트를 추적해야한다거나 하는 등의 이유가 있습니다(라우터나 분석시 활용). 이럴 때는 이벤트 이름 마지막에 `Capture`를 붙여주면 됩니다. 

<div onClickCapture={() => { /* this runs first */ }}>
  <button onClick={e => e.stopPropagation()} />
  <button onClick={e => e.stopPropagation()} />
</div>

 

이벤트 전파대신 핸들러를 보내는 대안

🔺이벤트 핸들러는 전달되어야 하는 것이지 호출되서는 안됩니다. onClick = {handleClick} (O)
  • 장점: 이벤트 전파에 의존하는 경우보다 핸들러가 왜 실행되는지 추적하기 쉽다.
  • 자식 컴포넌트가 이벤트를 처리하는 동시에 부모 컴포넌트가 몇 가지 추가 동작을 지정할 수 있게 해준다. 전파와 달리 자동이 아니다. 위의 장점에서 말했듯이 이벤트의 결과로 실행되는 전체 코드 체인을 명확하게 따라갈 수 있다. 
  • 자식 핸들러에서 이벤트 핸들러 프로퍼티를 명시적으로 호출하는 것은 전파에 대한 좋은 대안입니다.
function Button({ onClick, children }) {
  return (
    <button onClick={e => {
      e.stopPropagation();
      onClick();
    }}>
      {children}
    </button>
  );
}

-> 이 버튼 컴포넌트는 onClick 함수를 부모 컴포넌트로부터 전달받아 전달받은 온클릭 콜백함수를 버튼의 클릭이벤트 발생 시에 실행하는 코드로 등록합니다. 

 

이벤트 핸들러의 사이드 이펙트(부작용)?

사이드 이펙트를 부작용이라 칭했지만 리액트에서 사이드 이펙트란 "리액트"의 범주를 벗어난 것을 사용할 때 발생하는 모든 것을 말합니다. 예를 들어, localStorage와 같은 web api도 side effect 중 하나입니다. 
🔺보통 side effects 들은 `useEffect` 라는 리액트 훅 내부에서 관리하게 됩니다. 

이벤트 핸들러는 사이드 이펙트가 가장 많이 발생하는 곳입니다. 

렌더링 함수와 달리 이벤트 핸들러는 순수할 필요가 없으므로 입력에 반응하여 입력값을 변경하거나 버튼 누름에 반응하여 목록을 변경하는 등 무언가를 변경하기에 좋은 곳입니다. 하지만 일부 정보를 변경하려면 먼저 정보를 저장할 방법이 필요합니다. React에서는 컴포넌트의 메모리인 state를 사용해 이 작업을 수행합니다. 

 

  • useState 훅은 두 개의 인자를 갖고있는 배열을 반환하는데 state변수와 이 state를 변경하는 세터 함수를 반환합니다. 
  • hook은 리액트가 렌더링하는 동안에만 사용할 수 있는 특수 함수입니다.

리액트 문서에는 이벤트 핸들링을 하는 과정에서 디자인 시스템에 대해서 설명하고 있습니다. 

디자인 시스템을 사용하는 경우 버튼과 같은 컴포넌트에 스타일링은 포함하지만 동작을 지정하지 않는 것이 일반적입니다. 대신 PlayButton 및 UploadButton과 같은 컴포넌트는 이벤트 핸들러를 전달합니다.

이 인용문에서는 디자인 시스템에 관련된 아티클이 링크되어 있습니다.

디자인 시스템이란?

디자인 시스템은 팀이 제품을 설계, 구현 및 개발할 수 있도록 하는 모든 요소를 그룹화하는 단일 소스입니다.
스타일 가이드나 패턴 라이브러리 그 이상은 아닙니다. 
+훌륭한 디자인 시스템의 핵심은 제품 팀이 실제 소프트웨어를 빌드할 때 사용할 수 있는 재사용 가능한 UI 구성 요소 집합이라는 점을 인식해야 합니다.
  • 디자이너와 개발자를 위한 도구, 패턴, 구성 요소, 가이드라인... 등등 이 포함되며 브랜드 가치, 공유된 업무 방식, 사고방식, 공유된 신념과 같은 추상적인 요소도 포함됩니다. 
  • 디자인 시스템의 궁극적인 목적은 팀의 생산성을 높이는 것입니다. 

그러면 스타일 가이드와 패턴 라이브러리의 차이점은?

  • 스타일 가이드 - 스타일 가이드는 이름에서 알 수 있듯이 그래픽 스타일(색상, 글꼴, 일러스트레이션 등)과 그 사용법에 중점을 둡니다.
  • 패턴 라이브러리 - 패턴 라이브러리는 기능 구성 요소와 그 사용법을 통합합니다.

모듈 시스템과 통합 시스템⭐

  • 모듈 시스템(modular system) - 모듈형 시스템은 교체 및 재사용이 가능한 부품으로 구성됩니다. 빠르게 확장해야 하고 다양한 사용자 요구에 맞춰야 하는 프로젝트에 적합합니다. 단점은 함께 잘 작동하면서 독립적인 모듈을 만드는 것이 어려울 수 있기 때문에 실현 비용이 더 많이 든다는 점입니다. 이러한 종류의 시스템은 특히 이커머스, 금융 및 정부 웹사이트와 같은 대규모 제품에 적합합니다. 모듈형 시스템의 경우, 아토믹 디자인을 염두에 두고 작업하는 것이 매우 흥미로울 것입니다.
  • 통합 시스템(integrated system) - 통합 시스템은 하나의 고유한 컨텍스트에 중점을 둡니다. 또한 여러 파트로 구성되지만 이러한 파트를 서로 교환할 수 없습니다. 이러한 종류의 시스템은 반복되는 부분이 거의 없고 강력하고 자주 변경되는 아트 디렉션(포트폴리오, 쇼케이스, 마케팅 캠페인 등)이 필요한 제품에 적합합니다.

아토믹 디자인

  • 아토믹 디자인은 디자인 시스템을 만드는 방법론입니다.
  • 아토믹 디자인은 인터넷을 사용하는 디바이스의 화면이 다양해지면서 이에 따른 반응형 대응을 위해 아주 좋은 대안됩니다. 아톰이라는 최소 단위를 컴포넌트로 쪼개어 이를 여러 view에서 재활용합니다.
  • 아톰으로 디자인할 때는 동일한 컴포넌트가 매우 다른 맥락에서 재사용될 수 있다는 점을 항상 염두해야 합니다.
  • 여전히 반응형 디자인을 특정 중단점(breakpoint)에서 블록을 재구성하는 것으로 생각하는 경향이 있지만, 자체적인 중단점과 유동적인 동작을 가져야하는 것은 컴포넌트 자체이다. (Sketch와 같은 소프트웨어 덕분에 컴포넌트의 다양한 반응형 동작을 테스트하고 유동적으로 만들거나 고정된 상태로 유지해야할 것을 정의할 수 있습니다.

Everything you need to know about Design System

 

Everything you need to know about Design Systems

→ Pour la version en Français, c’est par ici

uxdesign.cc

 

아토믹 디자인 패턴

  • Atom - 더 이상 분해할 수 없는 기본 컴포넌트입니다. label, input과 같이 기본 HTML element 태그 혹은 글꼴, 애니메이션, 컬러팔레트, 레이아웃과 같이 추상적인 요소도 포함될 수 있습니다.
  • Molecule - 여러 개의 atom을 결합하여 자신의 고유한 특성을 가집니다. molecule의 중요한 점은 한 가지 일을 하는 것입니다. SRP(Single Responsibility Principle)원칙으로 인해 키워드 전송 기능이 필요한 곳에서 재사용될 수 있습니다. 재사용성과 UI에서의 일관성, 테스트하기 쉬운 조건이라는 이점을 가집니다. 
  • Organism - 더 복잡하고 서비스에서 표현될 수 있는 명확한 영역과 특정 컨텍스트를 가집니다. 그 예시로 header organism을 들 수 있습니다. 헤더는 로고라는 atom과 nav(Molecule) 그리고 searchBar(Molecule)을 결합한 Organism입니다. 더 구체적으로 표현되고 컨텍스트를 가지기 때문에 상대적으로 재사용성이 낮아지는 특성을 가집니다.
  • Template - 페이지를 만들 수 있도록 여러 개의 organism, molecule 으로 구성할 수 있습니다. 실제 컴포넌트를 레이아웃에 배치하고 구조를 잡는 와이어 프레임입니다. 즉, 실제 콘텐츠가 없는 page 수준의 스켈레톤입니다. 
  • Page  - 페이지는 유저가 볼 수 있는 실제 컨텐츠를 담고 있습니다. template의 인스턴스라고 할 수 있습니다. (모든 게 다 구현된 뒤 유저가 보는 페이지라고 생각하면 될 거 같습니다. 최종 UI)
사이즈 비교: atom < molecule < organism < template(컨텐츠는 없는 뼈대, 레이아웃) < page(실제 컨텐츠가 연결된 애)

카카오 FE팀은 Organism과 Molecule을 아래와 같은 네이밍 규칙으로 나눴다고 합니다. 

ref: 카카오 페이지 FE 기술블로그

또한, 재사용성을 위해 레이아웃과 관련된 스타일은 외부에서 주입했다고 하는데요. 아래와 같이 설명하고 있습니다.

재사용성을 높이기 위해서 마진, 패딩 등과 같은 스타일은 아토믹 컴포넌트에서 정의하지 않고 컴포넌트를 사용하면서 주입하도록 했습니다. 가장 바깥쪽 DOM의 attribute를 인터페이스로 확장하였고 이것을 구조 분해 할당을 이용하여 사용하는 곳에서 레이아웃을 지정할 수 있도록 했습니다. 
// organism/Comment.tsx
interface CommentProps extends HTMLAttributes<HTMLDivElement> {
  name: string;
}

function Comment({ name, children, ...props }: CommentProps) {
  return (
    <div {...props}>
    	<Text>{name}</Text>
      <Text>{children}</Text>
    </div>
  )
}

// pages/Product.tsx
function ProductPage ({
  commentList,
  ...
}) {
  return (
    <div>
      ...
      {
        commentList.map(comment => <Comment style={{margin: '20px 40px', flex: 1}}/>)
      }
    </div>
  )
}

// pages/Comment.tsx
function CommentPage({
  ...
}) {
  return (
    <div>
      ...
      <Comment style={{ width: '80%', margin: '0 auto'}}>
    </div>
  )
}

all ref: FE 기술블로그: 아토믹 디자인을 활용한 디자인 시스템 도입기 - 정호일님-

 

댓글