티스토리 뷰
2023년 6월, 원티드 프리온보딩 프론트엔드 챌린지 요약
Atomic Design Pattern
아토믹 디자인 패턴을 위해서는 '인터페이스'가 가장 중요하다.
그렇다면, 인터페이스는 무엇일까? 타입스크립트의 인터페이스일까?
인터페이스는 '대시보드'일 수도 있고, '깜빡이'일 수도, '사이드미러'일 수도 있다.
더 쉽게 말하자면, 애플의 USB 케이블(충전기, 포트)일 수도 있을 것이며, 가위바위보, 더 복잡해지면 묵찌바일 수도 있다.
아토믹 디자인 패턴은, 원자와 분자를 이루는 인터페이스를 만드는 방법이다.
- 'Atom'은 인터페이스를 구성하는 가장 작은 단위이며, 조합이 없다.
- 'Molecule'은 Atom을 조합하여 만든 더 복잡한 컴포넌트이며, 여기서부터는 조합이 있다.
- 'Organism'은 Molecule을 조합하여 만든 더 복잡한 컴포넌트이며 조합이 있다.
- 'Template'은 Organism, Atom과 Molecule을 조합하여 만든 레이아웃
- 'Page'은 여러 Template과 Organism을 조합하여 만든 페이지
아토믹 디자인 패턴은 정답은 아닐 수 있다. 그러나, 개발을 배우며 학습하는 관점에서는 정말 좋은 예시이자 방법론이다.
아토믹 디자인 방법론을 구성하는 기본 단위인 인터페이스는 정답이 있다고 할 수 있을까? 의문을 가질 필요가 있다.
여기서 더 어려운 점은 리액트스럽게 생각하는 것, 회사의 도메인 컨텍스트를 생각하는 것을 보면 아토믹 디자인 방법론을 지킬 수 있을까?
리액트스럽게 컴포넌트 생각하는 것은 무엇일까?
- React는 디자인을 바라보는 방식과 앱을 빌드하는 방식
- React로 사용자 인터페이스를 빌드하는 방법
- 컴포넌트라고 하는 조각으로 분해
- 각 컴포넌트에 대해 서로 생김새가 다른 상태를 정의
- 컴포넌트를 서로 연결해 데이터가 흐르도록 만듬
결론은 우리는 리액트 컴포넌트를 만들 때, 아토믹 디자인 패턴을 도입하는 게 아닐까?
아토믹 디자인 패턴을 구성하는 기준과 리액트스러운 컴포넌트를 조합하는 게 아토믹 디자인 패턴이라고 말할 수 있겠다.
여기서 +@ 회사에서 추구하는 비즈니스 가치와 도메인 컨텍스트(예. 사장 친화적)를 고려해야 할 것이다.
시간(Time), 프로젝트(Project), 상황(Occasion)을 고려해야 할 것이다.
아토믹 디자인 패턴이 어려운 이유는, 개인마다 정의하는 것이 다르기 때문이다.
상향식 컴포넌트 개발과 하양식 컴포넌트 개발
컴포넌트 주도 개발을 하겠다는 것이 'CDD'이다.
하양식 컴포넌트 개발 (Top => Down)
"하양식 컴포넌트 개발"은 (Top -> Down) 전체 시스템의 큰 구성요소들을 먼저 개발하는 것이다.
이후에 중복되는 작은 컴포넌트를 분리하거나 공통 혹은 교차되는 컴포넌트를 분리한다. 전체 시스템의 디자인과 구조를 먼저 구성하고, 이를 바탕으로 세부적인 요소들을 개발한다.
그러나, 문제는 '르블랑의 법칙'으로 한 번 작성한 레거시 코드(쓰레기 코드)는 나중에 수정하는 일은 결코 없다는 것이다.
예시. Next.js Page => 작고 하찮을정도로 귀여운 컴포넌트
- Page(페이지) => Template(템플릿) => Organism(유기체) => Molecule(분자) => Atom(원자)
정리를 하자면, 하양식 컴포넌트 개발할 때 고려해야 할 점은 다음과 같다.
- 이미 만들어진 페이지 혹은 큰 단위부터 만들어 놓은 경우
- 그것들을 하나하나 분리하여 계층을 구성
- 컴포넌트를 만들 때, 'pnpm dev' 즉! 사용자가 보는 동일한 환경으로 개발
- 개발자가 아닌 정말 출시된 사용자를 위해 개발을 하며 컴포넌트를 분리
상향식 컴포넌트 개발 (Bottom => Top)
"상향식 컴포넌트 개발"은 (Bottom -> Up) 가장 작은 단위의 하위 컴포넌트들을 먼저 개발하는 것이다.
이런 작은 하위 컴포넌트들을 조합하여 전체적인 컴포넌트를 완성한다. 이는, 아토믹 디자인 개발의 가장 적합한 방법일 것이다.
그리고 사용자뿐만 아니라 개발자도 사용할 수 있는 것을 고려해야 한다.
숙련도가 부족하다면 야근에 빠지기 쉽다.
예시. 작고 하찮을정도로 귀여운 컴포넌트 => Next.js Page
- Atom(원자) => Molecule(분자) => Organism(유기체) => Template(템플릿) => Page(페이지)
정리를 하자면, 상향식 컴포넌트 개발할 때 고려해야 할 점은 다음과 같다.
- 하나의 세트를 구성 => 사용'될' 컴포넌트 + CSS 스타일링, 사용'될' 스토리
- 사용될 컴포넌트를 내보내고 스토리에서 사용될 컴포넌트를 가져오기
- 컴포넌트(Componenet.jsx) ♥ 스토리(Component.stories.js)
- 사용될 컴포넌트들은 Storybook이 무엇인지 모르게 만들어주는 게 좋음
- 다른 개발자에게 나의 컴포넌트가 어떻게 사용될 지 상상하며 개발하게 되는 자세
그렇다면, 아토믹 디자인 패턴은 정답일까?
아토믹 디자인 패턴은 정답은 아니다.
하지만, 개발을 배우며 학습하는 관점에서는 정말 좋은 예이자 방법론이다.
아토믹 디자인 방법론을 구성하는 기본 단위(인터페이스)는 딱 정확하게 말할 수는 없다.
그러나, 더 어려운 것은 리액트스럽게 생각하고, 회사의 도메인 컨텍스트를 생각한 채 아토믹 디자인 방법론을 지킬 수 있느냐인 것이다.
리액트스러운 컴포넌트를 생각하는 방법
React는 디자인을 바라보는 방식과 앱을 빌드하는 방식을 가지고 있다.
React로 사용자 인터페이스를 빌드하는 방법은 다음과 같다.
- 컴포넌트로 조각으로 분해하기
- 각 컴포넌트에 대해 서로 생김새가 다른 상태로 정의
- 컴포넌트를 서로 연결하여 데이터가 이어지도록 구현
결론은 리액트 컴포넌트를 만들 때, 아토믹 디자인 패턴을 도입하는 것이라고 생각한다.
그렇다면, 아토믹 디자인 패턴을 구성하는 기준과 리액트스러운 컴포넌트를 조합하는 방법을 생각하는 것이 좋다.
또한, 회사에서 추구하는 비즈니스 가치와 도메인 컨텍스트를 고려해야 한다는 것도 잊으면 안 된다.
- TPO (Time, Project, Occasion)
제어 컴포넌트와 비제어 컴포넌트
제어 컴포넌트와 비제어 컴포넌트는 굉장히 중요하다.
제어 컴포넌트는 'Push & Single Source of Truth(단일 진실의 원천)'이다.
- React에 값이 완전히 제어되는 Input Element
- React 상태로 계속 업데이트가 된다.
- State를 값으로 넘기고 그 State을 다룰 수 있는 핸들러를 콜백으로 넘긴다.
- 값을 __으로 받는다.
- 내가 제어하고 내가 푸시하고 진실의 상태가 계속 유지가 된다.
<input value={value} onChange={handleChange} />
제어 컴포넌트를 쉽게 이해하자면, 부모님의 잔소리가 많은 것, 사사건건 개입하는 것, 용돈을 주는 것과 같다.
그리고 Push해야되기 때문에 이벤트 핸들러를 항상 작성해야 한다.
렌더링 시점마다 고유의 값을 가진다.
비제어 컴포넌트는 'Pull & get State'이다.
- 전통적인 HTML 처럼 DOM에 제어되는 Input Element
- 오직 사용자만 값과 상호작용
- 값을 __로 사용한다.
- 내가 제어하는 것이 아닌 필요할 때 상태를 꺼내온다.
<input onChange={handleChange} ref={inputRef} />
제어 컴포넌트와의 코드 차이는 'ref={inputRef}'가 붙는 것과 아닌 것의 차이이다. 이는, 렌더링과 연관이 있다.
'Ref'는 고유한 값이 유지되지 않는다. 그렇기 때문에 원하는 대로 되지 않고, 'Get'해주는 코드로 해주어야 된다.
그리고, 이벤트 핸들러를 통해 값을 변경하지 않으며, 항상 쓸 필요는 없다. 비제어 컴포넌트는 필요한 시점에 트리거(Pull)하기 때문이다.
렌더링 시 원하는 값을 볼 수 없다. 개발자가 직접 트리거해야 한다. 트리거는 (방아쇠)를 당기다를 의미한다.
비제어 컴포넌트를 쉽게 이해하자면, 알아서 살도록 하는 것, 아르바이트를 하는 것, 살아있는지 확인하는 것과 같을 수 있다.
제어 컴포넌트와 비제어 컴포넌트를 알아야 하는 이유는 'CDD(컴포넌트 주도 개발'에 엄청난 영향을 끼치기 때문이다. 컴포넌트를 만들고 구성하는데 영향을 준다.
비교
제어 컴포넌트(Controlled) | 비제어 컴포넌트(Uncontrolled) | |
지향점 | Push | Pull |
사용성 | 항상 진실의 원천 유지 | 값을 담아내는 방법 필요 값을 가져오는 트리거 포인트 필요 이 모든 것을 관리하는 코드를 직접 작성 |
성능 | 잦은 리렌더링 | 구현하는 방법에 따라 성능에 이점 발생 |
동적 핸들링 | 상태를 중심으로 개발하여 상태 변경에 따른 핸들링 용이 | DOM을 직접 조작하여 핸들링이 어렵고, 값 비싼 비용 지불 |
유효성 검사 | 상태 변경 => UI를 자동으로 업데이트 자동 업데이트로 인해 개발자가 별도의 업데이트 코드를 작성할 필요 없음 |
DOM을 직접 조작하여 핸들링이 어렵고, 값 비싼 비용 지불 |
스토리북 상호작용 테스트
전통적인 TDD는 다음과 같이 나뉜다.
- UI
- Service
- Unit
UI는 느리지만, 비싸다. Service는 중간의 속도와 중간의 비용이 든다. Unit은 빠르고, 비용이 적다.
프론트엔드는 값비싼 UI를 TDD한다.
테스트를 하는 이유는 올바른 테스트 전략을 선택해야 하고, 벽을 칠하기 위한 붓(도구)을 선택하는 것이기 때문이다.
테스트 트로피
- End to End
- Integration
- Unit
- Static
트로피에 페인트를 칠한다는 것은 결국 대부분을 칠할 수 있지만, 붓을 들고 올라가지 않는 한 꼭대기는 절대 칠할 수 없다는 것이다. 이 예시는 기본적으로 "올바른 테스트 전략을 선택하는 것"이 "벽을 칠하기 위한 붓을 선택하는 것"과 같은 종류의 선택인 것이다.
벽 전체에 미세한 붓을 사용하는 것은 작업 시간이 오래 걸리고 표면이 그다지 고르지 못할 것이다.
그렇다면, 롤러로 모든 것을 칠할 수 있을까? 오래되고 설치된 모든 것들을?
아마 어려울 것이다. 그렇기 때문에 사용 사례에 따라 브러시가 다르며 테스트에도 똑같이 적용이 되는 것이다.
테스트 트로피의 테스트 종류
실질적으로 테스트가 어떤 의미를 가지고 있고, 테스트 비용을 최대한 활용하기 위해 무엇을 최적화를 할 수 있을까?
- End to End
- 사용자 입장에서 앱이 제대로 작동하는지 전체적으로 테스트
- 일반적으로 전체 앱(프론트엔드 & 백엔드)을 실행, 테스트는 실제 사용자가 사용하는 것처럼 앱과 상호 작용
- Integration
- 여러 단위가 함께 상호 작용
- 실제 데이터베이스, 브라우저 없이 큰 규모의 기능이나 하나의 페이지가 제대로 작동하는지 테스트
- Unit
- 기능의 개별적인 단위나 하나의 컴포넌트를 테스트
- Static
- 코드 작성 레벨에서 오타와 타입 에러를 확인
- 구문 오류, 나쁜 코드 스타일, 잘못된 API 사용 등을 Lint
올바른 테스트 전략 - Redux
회사 또는 프로젝트에서 Redux에 모든 비즈니스 중요한 코드가 있다고 가정할 시, 당연히 Redux만 테스트해도 안전한 앱을 만들 수 있지 않는가? 에 대한 고민은 테스트 전략의 예시일 수 있다.
또한, 전략을 세울 때, Redux만 테스트하더라도 모든 것을 다 테스트하는 것이 아닌 단위를 나누어서 테스트를 진행할 수 있을 것이다.
테스트 도구
- Jest: 거의 모든 기능과 플랫폼을 지원하는 자바스크립트 테스팅 프레임워크
- Vitest: 빠른 속도를 지향하는 단위 테스트 프레임워크 (Jest API 호환, HMR, TS, JSX, ESM 지원)
- React Testing Library: BDD 방법론에 어울리며, 간결하면서도 꼭 필요한 API 지원 & Jest와 Jsdom 기반 브라우저 DOM Testing
- Enzyme: React Virtual Dom Testing
- Storybook + Chromatic: 컴포넌트 주도의 독립적인 개발 환경 제공 & 스냅샷 테스트 지원 & 테스트에 용이한 Addon 지원
- Cypress, Playwright: E2E | 통합 테스트
- Flow, TypeScript: 정적 타입 지원
'여러가지 활동 > 프리온보딩 프론트엔드 챌린지' 카테고리의 다른 글
컬러 시스템과 기본적인 디자인 요소 (0) | 2023.08.08 |
---|---|
React 최적화 (0) | 2023.08.08 |
프론트엔드 변수 상태 관리와 테스트 (0) | 2023.08.05 |
디자인의 간격 요소와 반응형을 위한 그리드 그리고 텍스트 (0) | 2023.08.02 |
UI/UX와 디자인 시스템 정의, 사례 (0) | 2023.08.01 |
- Total
- Today
- Yesterday
- 설명회느낌점
- DB Error MongooseServerSelectionError
- 개발 이력서 지원 팁
- 포스텍애플디벨로퍼아카데미
- LottieFiles
- 그룹인터뷰후기
- 최종추가합격
- Frontend
- Singleton
- React
- 자바스크립트
- 고민한 부분
- 원티드 프리온보딩 챌린지
- 개발자이력서꿀팁
- 원티드 프리온보딩
- Express
- PostechAppleDeveloperAcademy
- 코딩테스트 대비
- Default Branch
- 프론트엔드 챌린지
- 스프링
- node
- if(kakao)dev2022
- 포스텍애플아카데미
- #포스텍애플디벨로퍼아카데미
- 신입개발자가 준비해야 할 것들
- javascript
- 조코딩과함께
- 깃허브 Merge
- 싱글톤
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |