지난 10월 8일 롯데타워에서 열린 2022 FEConf에 다녀왔다.
정말 오랜만에 열린 오프라인 컨퍼런스 참석이었고, FEConf도 처음 참석해서 그런지 모든 부분이 신기하고 재밌었다. 발표도 깊은 주제로 알찬 내용이 많았었다. 프론트엔드 분야 한정 컨퍼런스인데 생각보다 사람들이 많이 몰려서 놀랐다. 티켓팅은 1분만에 마감이 되었던 것으로 기억을 한다.
컨퍼런스를 다녀오고 나서 관심있는 세션들에 대한 요약 내용을 적어보려고 한다. 모든 세션을 다 정리하지는 못했다. 이날 중반 이후부터 컨디션이 급격히 안 좋아졌는데, 앞부분은 집중해서 들었으나 뒷 부분은 거의 버티면서 겨우겨우 앉아 있었다. 감사하게도 주최측에서 풀버전 녹화 영상을 유튜브에 공유해 주었으니 관심 있으신 분들은 이 영상을 보는 편이 좋겠다. (영상 임베드는 블로그 하단에)
13:30 Track B 디자인 시스템, 형태를 넘어서
연사 : 이소영 Flex 프론트엔드 엔지니어
디자인 시스템에 무엇을 기대하나요?
- 개발자의 관점?
- 디자이너의 관점?
Design System : 형태, 기능, 접근성, 커스텀 네 가지로 구성이 된다.
- 형태 : 컴포넌트가 가지는 컬러나 간격 등의 디자인 스펙을 의미한다.
- 기능 : 컴포넌트가 수행해야 하는 동작
- (SelectBox를 기준으로)
- N개 아이템 선택
- 선택된 아이템 표현
- Option List 여닫기 (마우스/키보드) 등등
- 접근성 : 모든 사용자가 이 컴포넌트를 사용할 수 있도록 지원
- (SelectBox를 기준으로)
- popup 요소에 대한 힌트
- 키보드 탐색 힌트
- 커스텀 : 다양한 니즈에 대응할 수 있어야 한다.
→ 형태와 커스텀을 어떤 비중으로 가져갈 지는 선택
- 형태에 가까울 수록, 커스텀이 힘듦
- 커스텀에 가까울 수록, 매번 형태를 정의해 주어야 하는 비효율
- 형태를 가지지 않는 방식의 라이브러리 : zag, aria
플렉스의 디자인 시스템 : linear
- 디자인 플랫폼 팀
- 이전 버전의 디자인 시스템이 겪은 어려움을 바탕으로 원칙을 만듦
- 기능은 형태와 독립적이다.
- Checkbox / Radio
- 기능 : 옵션을 어떤 방향으로 선택할 것인지
- 형태 : 그 선택 방식을 담는 그릇
- 기능이 특정 형태로 제약이 되어서는 안 된다.
- Trigger Component
- Dropdown, Select 와 같이 일정 영역을 켜고 끄는 컴포넌트
- Checkbox / Radio
- 기본 동작을 보장한다.
- 반복 작업을 줄이고 일관성을 유지해야 한다.
- Scroll
- Select 상단에 고정 영역을 둔다.
- 기본동작이 아닌 것은 정의하지 않는다.
- 직접적인 dataType ❌
- 완성형 set ❌
- 조합형 🟢
- 최소한의 제약만 가진다.
- 자유로운 커스텀
- 커스텀을 전제로 추상화 레벨을 높임
- 기능은 형태와 독립적이다.
참고
- main: Radix
- others : chakra, tamagUI, dasiyUI, …
- accessibility: headlessUI, React Sepectrum, …
14:30 Track B 일백개 패키지 모노레포 우아하게 운영하기
연사 : 오창영 토스 프론트엔드 엔지니어
About Monorepo
- 모노레포란 잘 정의된 관계를 가진, 여러개의 독립적인 프로젝트들이 있는 하나의 레포지토리이다.
- 멀티레포 : Project A와 비슷한 Project B를 생성
- 새로운 Project B 레포지토리를 추가
- ci/cd, lint, test, ts 등등 설정을 새로 해준다.
- Project A에서 재사용하고 싶은 코드가 있는 경우 이를 위한 Library A 레포지토리를 새로 만들어준다.
- 2 반복..
- 멀티레포의 문제점
- 새 프로젝트 생성 비용이 큼
- 프로젝트간 코드 공유가 어려움
- 같은 이슈를 수정하기 위해 각각의 레포지토리에 커밋이 필요
- 히스토리 관리 어려움
- 제각각인 툴링으로 개발자 경험이 일관적이지 않음
- 모노레포가 해결해 주는 것
- 새 프로젝트 생성 비용이 작음
- 프로젝트간 코드 공유가 쉬움
- Atomic commits
- 히스토리 관리 쉬움
- 공통된 툴링으로 일관적인 개발자 경험
- 모던 모노레포 툴들에서 제공하는 기능들
- 속도
- Local computation caching
- Local task orchestration
- Distributed computation caching
- Detecting affected projects / packages
- 관리
- Source code sharing
- Code generation
- Project constraints and visibility
- 속도
Toss Frontend Library
- 기술적 요구사항
- 의존성 관리
- 유령 의존성 (Phantom Dependency) : 명시되어 있지 않은 의존성. 많은 문제를 일으킴
- yarn berry + PnP
- no more hoisting
- .pnp.cjs를 통한 엄격한 의존성 관리
- Zero install
- 빠른 의존성 검색
- Peer dependency : 상속된 의존성
- Peer dependency는 전파된다.
- Peer dependency 오류는 잠재적 런타임 에러이다.
- 꼭 싱글턴으로 존재해야 하는 패키지일 때만 Peer Dependency로 명시해주자
- 버전 관리
- Semver : Semantic Versioning
- Major / Minor / Patches
- 라이브러리에서는 버전을 더 잘 지켜야 한다.
- lerna version
- 코드 품질 관리
- RFC (Request For Comments) : 아이디어 단계에서 PR 전에 기여하고 싶은 부분을 올림
- PR
- 코드 리뷰
- CI가 동작하면서 코드 검증
- peer dependency error check
- unused export check
- pre build check
- canary version check
- 문서화
- 어떻게 사용하는지 문서 중요!
- JSDoc, Docusaurus 로 자동으로 문서화
- https://github.com/toss/slash → 토스 프론트엔드 챕터에서 사용하는 모노레포
- 의존성 관리
15:10 Track A 프론트엔드 DDD를 만나다
연사 : 박세문 라포랩스 프론트엔드 엔지니어
왜 DDD에 대해서 이야기를 하는가
- Complexity : 제품의 복잡성을 해결하는 방향에서의 DDD
- Communications : 개발 과정에서 여러 팀, 사람들간 효율적인 의사 소통을 위한 방향에서의 DDD
- Similarity : 기존 Frontend에서 사용하고 있었던 기술, 패턴이 DDD와 크게 차이가 없음.
Complexity
영화 예매 시스템을 구축한다고 가정
→ 수 많은 요구사항들 (e.g 고객이 예매 가능한 좌석을 알려달라 하면 알려준다 등)
→ 팀 간에 업무를 분배 한다면 어떻게 나눌 수 있을까?
→ 새로운 요구사항에 대해서 수정 범위는 얼마나 되는 걸까?
→ 이러한 궁금증에 대해 DDD가 도움을 줄 수 있다.
단순함은 궁극의 정교함이다. - 레오나르도 다빈치
Communications
Class?
- 디자이너는 css 를 스타일링 하는 클래스로 이해할 것
- 개발자는 객체를 이야기하는 클래스로 이해할 것
→ 같은 개발 직군에서도 소통하는데 혼동할 수 있다.
Product?
- Order Team : 가격이나 재고, 상품의 옵션
- Customer Support Team : 제품의 배송 기간, 별점이나 리뷰
→ 다른 관점으로 바라봄.
→ 모델에 혼용을 줄 수 있다.
→ DDD에서는 모든 구성원들이 공통적으로 쓰는 말을 유비쿼터스 언어라고 지칭한다.
Similarity
Redux vs DDD’s CQRS Pattern : 상당히 비슷
- Event Sourcing Pattern과도 흡사
- 상태를 변경하는 Command를 위한 모델
- 상태를 제공하는 Query를 위한 모델
- 어플리케이션의 상태는 이벤트에 의해 변경될 것.
- 이 이벤트는 변하지 않는 오브젝트, 어플리케이션에 의해 날아옴
- Redux
- Client → UI → (create) → Action → (dispatch) → Reducers → (update) → Store → UI
- CQRS
- Client → UI→ Query → Read DB
- → Command → Write DB → (Event Bus) → Read DB
DDD란 무엇일까?
DDD 두 가지로 나눌 수 있다.
- Strategic Design
- Ubiquitous Language : Bounded Context 안에서 사용되는 공통적인 언어
- 커뮤니케이션 비용 발생 절감에 중점
- Bounded Context : 다양한 도메인에서 같은 용어가 많이 사용이 된다.
- 고객이 바라보는 상품과, 주문에서의 상품은 다르다.
- 모든 도메인에서 사용되는 모델이 아닌, 각각의 도메인에 맞게 모델을 따로따로 만들어야 하는 것이 맞다.
- Ubiquitous Language : Bounded Context 안에서 사용되는 공통적인 언어
- Tactical Design
- 시스템 구현 그 자체에 의미를 둔다.
- 다양한 공간에서 다양한 커뮤니케이션을 하는데 중점.
- 기술적인 리소스가 어떻게 쓰이게 되는지.
- 리소스는 하나의 Bounded Context 안에서 동작
- 다섯 가지 개념
- Entity : 고유한 식별자가 있는 변경 가능한 객체 (e.g. uuid), mutable
- Value Object : 고유한 id가 없고 속성 값으로만 정의, 업데이트 하려면 새로운 인스턴스를 생성해야 함, immutable
- Aggregate : 하나 이상의 Entity의 클러스터, Value Object도 포함할 수 있다.
- Services : 상태를 부여하지 않고 로직을 구현하는 객체
- Domain Service : 도메인 기능 캡슐화, 도메인 종속적 Operation
- 비즈니스 로직
- 도메인 동작
- Application Service : 기술적인 기능(어플리케이션 workflow) 제공. 외부 컨슈머가 시스템과 커뮤니케이션하는 매개체
- 어플리케이션 로직
- Domain Service : 도메인 기능 캡슐화, 도메인 종속적 Operation
- Domain Events
- 변경이 있을 때 시스템의 다른 부분에 이를 알려주는데 사용한다.
어떻게 DDD를 적용할 수 있을까?
어플리케이션이 어떤 형태로 디자인이 되는가?
- Layered 구조
- User Interface
- Application
- 도메인 객체의 직접적인 클라이언트
- 비즈니스 상 필요한 Use Case를 구현한 객체들의 집합
- Domain
- 도메인과 관련된 객체들의 집합
- Entity, Value Object, 그리고 Domain Event가 존재
- Infrastructure
- 다른 계층들을 지탱
- 구현체의 집합
→ 의존성의 방향은 위에서 아래로 (UI → App → Domain → Infra)
- Hexagonal 구조
- User Interface
- Adapter(Port)
- Application
- Domain
- Infrastructure
→ 육각형 모습으로 그린다.
→ 의존성은 바깥에서 안으로만 향함(단방향)
UI → Adapter → Infra → Use Cases → Domain
→ 부분적인 수정이 필요할 때 전체에 대한 수정 필요 없이 Infra 및 Adapter에서만 수정을 해 주면 됨.
- 프레임워크 : UI, Adapter
- 프레임워크에 독립적 : Infra, App, Domain
코드 레벨에서의 이야기
의존성에 맞춰서 폴더 구조 짜볼 수 있다.
src
└───ui
└───adapter
└───infrastructure
└───application
└───domain
└───common-ui
└───utils
- UI Layer는 일반적으로 우리가 생각하는 그 레이어
- Adapter Layer
- 흔히 사용하는 Redux나 Vuex
- 뷰가 참조할 State 정의, selector로 필요한 값을 참조함
- Infrastructure Layer
- 서비스에 대한 구현 그 자체
- 외부 시스템과 커뮤니케이션
- 저수준 모듈의 구현체를 Infra layer에 정의한다.
- Dependency Injection
- Application Layer
- 비즈니스 로직이 들어있는 Use Cases가 존재
- Domain Layer
- 비즈니스 도메인을 지원하는 책임
- Entity, Value Object를 포함
마주칠 수 있는 문제점?
- 여러 도메인이 동일한 프레젠테이션 컴포넌트를 필요로 할 경우
- 여러 도메인이 동일한 API 호출
- 여러 도메인이 동일한 hook이나 helper function을 사용
'Web Frontend Developer' 카테고리의 다른 글
react-hook-form & zod 로 복잡한 오브젝트 관리하기 (feat. immerjs) (0) | 2023.04.21 |
---|---|
[Three.js] 3D 라이브러리를 사용해서 태양계 만들어 보기 (8) | 2023.03.10 |
[Three.js] Transform Objects (1) | 2022.10.17 |
Reflow와 Repaint에 대하여 (0) | 2022.08.17 |
[웹 프론트엔드 인터뷰] #4. useCallback과 useMemo는 언제 어떻게 사용하나요? (0) | 2022.07.20 |