Published on

FECONF - 바퀴 대신 로켓 만들기

Authors

FECONF 2024 - 바퀴 대신 로켓 만들기

소개

  • 발표자 양의현
    • 리액트, interface, 협업, 영감을 주는 주제에 관심
    • 토스 페이먼츠의 FE 개발자
    • 어드민 프로덕트 팀 ~ 어드민 개발 주력

문제

맥락

  • 데이콤 -> LG U+ PG -> 토스페이먼츠
    • 팀은 신생이나, 긴 기간 동안의 유산...
      • 레거시, jsp, euc-kr
      • 결제 시장의 혁신 해볼까 했으나, 레거시들이 발목을 잡는 사태
    • 레거시 청산..!
      • 400개 이상의 페이지, 6개월 안에, 4명의 개발자, 10년 이상 지속 가능
      • 불가능해 보이는 과제
        • 디자인 프로토 타입, 서버 준비, 요구사항 분석
        • 어드민 화면을 바로 개발하기 어려운 상황
        • 커뮤니케이션을 많이 할 수록, 시간적 자원 요구

FE 개발자가 접할 병목 3가지 (디자인 프로토타입 / 서버 API / 요구사항 분석)

디자이너와의 병목을 어떻게 끊을까

  • 6개월 동안 400개 화면에 대해 최적화된 유저 경험을 고려한 디자인 프로토타입을 만들어주세요
    • 이걸 누가 어떻게...
  • 디자인 비효율을 줄일 도구 -> 디자인 시스템
    • BUT 토스 디자인 시스템은 범위가 너무 넓어 (토스의 모든 프로덕트)
    • 토스 페이먼츠만을 위한 디자인 최적화가 불가능
  • 디자인 시스템 특)
    • 장점이 많은 좋은 도구
      • 아토믹한 형태 제공, 다양한 기능 조합해서 활용 가능
      • 유연하고 재사용 가능
    • 단점
      • 반복되는 코드
      • 작성하는 사람마다 다른 구현체
      • 화면을 구성하는 제품의 코드가 늘어날 수록 구현 의도를 이해하기 어려움
  • 페이먼츠만을 위한 시스템
    • 강점
      • 반복되는 기능과 형태를 패턴으로 정의
      • 동일한 패턴은 동일한 구현체를 사용
      • 닫힌 인터페이스로 패턴과 일치하지 않은 상황에서 사용 방지
      • 가장 작은 단위부터 큰 영역까지 다양한 레이어에 대응
    • 단점
      • 상대적으로 떨어지는 유연성과 재사용성
      • 상대적으로 한정적인 기능
      • 패턴에 대한 학습 비용
    • 예시: DateRangePicker|300
      • 한 눈에 들어오는 인터페이스로 개선
    • 예시: Select
      • 작성하는 사람마다 서로 다른 구현체
        • 누구는 prop으로 옵션 내리고, 누구는 합성으로 옵션 처리
        • 취향 차이고 정답은 없어
        • 다만, 다르다는게 문제
      • 일관성 있는 단일 구현체를 제공해, 다른 구현체 만들 필요 없게함|300
    • 특정 라이브러리 (훅 폼) 과 UI 요소와의 결합으로 군더더기 없는 코드 구현
    • 유지 보수의 어려움
      • 화면의 역할이 무엇인지 직관적으로 확인 어렵
      • 영역이 적절히 분리되어 있지 않아 오류 발생 시 원인 파악에 오랜 시간
      • 화면의 공통 변경사항 반영 시 N 번의 수정을 반복해야 함
      • 아토믹 단위 말고, 다양한 레이어의 구현체
        • 해당 페이지가 무슨 역할인지 한 눈에 보이게
  • 결론 (W/프로덕트 패턴)
    • 아토믹한 구조를 추구하기 보다도, 구체적인 맥락이 들어가더라도 반복 사용하기 좋은 형태
    • 서로 다른 인터페이스로 구현할 가능성 방지
    • 명확한 역할의 컴포넌트를 정의하여 가독성과 유지보수성 향상
    • 개발자가 패턴을 이해하고 있다면 디자이너이 도움 없이 화면 구현 가능

백엔드 개발자와의 의존성 끊기

  • 서버 API가 완성될 때 까지 기다려야 할까?
    • 우리가 서버에 필요한 것은 서버에 대한 구체적인 구현이 아닌 인터페이스 (엔드포인트, 메서드, request params, 응답 데이터)
      • API Spec ~ 스웨거 등의 스펙을 이용하는 것에도 비효율
        • 스펙을 확인 -> TS 코드로 이관 -> 메서드 호출 -> 스펙 호출
        • 이 과정의 끝 없는 반복
  • OpenAPI Code Generator
    • 유용하지 그런데, api client 없이 스펙 정보만 자동 생성 가능? zod로 요청 파라미터와 응답 데이터 파싱 가능? 커스텀 transform 조건 쉽게 주입 가능? 학습비용 없이, zero config로도 결과물 생성 가능? -> 이러한 요구사항 백프로 충족하는 도구 없어
    • 그럼 우리가 필요한 도구를 직접 만들자
  • TossPayments Codegen
    • OpenAPISpec 읽기, 원하는 형식으로 코드 다듬기(TS, zod), 파일 쓰기
    • Resource
      • 하나의 파일에서 관리 가능한 api 명세 객체
      • API에 대한 정보가 소스코드 전역에 퍼지는 현상 방지
      • 필요에 따라 리소스에 정의한 스키마 파서로 데이터 정합성 확인 가능
      • 리소스 이름을 기준으로 필요한 파라미터와 응답 데이터 추론 기능 제공
    • 사용된 도구 |300
    • CodeGen 구현
      • |300
      • |300
      • 스웨거에서 json 뽑아오고 이걸 다듬어서 자동으로 스키마 파일 생성
      • paths 의 경우에도 똑같이 자동으로 resource의 형태로 자동 생성
    • CodeGen 의 효과
      • 구현 시간 1주일
      • 2,000개 이상의 endpoints 자동화
      • 10초 남짓의 시간으로 자동 생성
      • 재사용 가능한 타입과 스키마
      • 스펙 싱크 신경쓰지 않아도
      • 기존의 스펙과의 지지부진한 관계를 벗어버리고, codegen 실행 -> 메소드 호출 간단한 과정으로 축소
  • 결론
    • 개발자가 api 문서 보고 한땀한땀 코드를 옮길 필요 없음
    • API 오류 발생시, 옮기는 과정의 실수인지 잘못된 구현인지 추적할 필요 없음
    • 우리의 유즈 케이스에 맞게 가공 가능한, 100% 제어 가능한 도구
    • API가 반환하는 인터페이스가 바뀌어도 변경 사항을 즉시 싱크할 수 있음

제품 요구사항과의 의존성은 끊어낼 수 없어 -> 그럼 개발 자체의 비효율을 줄여볼까?

  • 개발 생태계가 너무 풍부해서 생기는 비효율
    • 좋은 라이브러리로 만들어내는 결과물들은 개발자마다 달라
    • 다른 결과물들을 만드는 것은 바퀴를 만드는 행위의 반복
    • 이것 보다는 일관성 있고 지속 가능한 코드를 생산하는 기반이 필요
  • 코드를 하나의 방식으로 통일할 Pramework 가 필요
    • Refine 이라는 툴 사용
      • 오픈소스 리액트 어드민 툴
      • headless: 특정 UI와 결합되지 않음
      • resource: API 명세를 한 곳에서 객체로 관리
      • provider: 필요한 기능들을 provider에 주입 가능
  • 어드민 제품 만들 때 가장 많이 반복되는 행위 (Data Fetching / Form Control / Table / Loggin)
    • Data Fetching
      • api에 대한 맥락을 한 곳에서 제어 (resource)
      • 리소스와 api client를 react context로 주입
      • 행위에 대한 훅을 제공하여 보다 선언적인 방식으로 데이터 사용
      • 리소스 이름을 기준으로 필요한 요청 파라미터와 반환되는 응답을 추론|300
    • Form Controls
      • 리소스에 정의한 api 호출하고, default Values 로 주입
      • 쿼리 파아미터 파싱하여 default Values 로 주입
      • form 제출, 초기화를 쿼리 파라미터 업데이트 방식으로 실행|300
    • Table
      • 리소스에 정의한 api 호출, 테이블 형태로 렌더링
      • jsx 반복 작성하는 대신 테이블 모델 주입하여 가독성 향상
      • 페이지네이션, 열 번호, 체크박스와 같은 요구사항 처리|300
      • 복잡하고 읽기 힘든 트리 방식을 제고 -> 반복되는 구현을 공통 옵션으로 제공
    • Logging
      • Log Client 를 컨텍스트로 주입
      • Logger 로 wrapping한 TDS 컴포넌트를 사용하여 별도 처리 없이 로깅 실행|300
  • 결과
    • 몇 명의 개발자가 구현해도 일관성 있고 유지보수 가능한 서비스를 만드는 FE로 진화

결과

  • 서로 다른 어드민 제품, 400 페이지 이상의 메뉴를 연차에 따라 편차 없이 화면 구현 시간을 하루에서 한 시간으로 단축..!
  • 업무 중 비효율 적인 부분을 발견한다면, 작은 단위에서부터 변화를 꾸려라