Skip to main content

2025 Toss 개발 컨퍼런스 후기 정리

· 5 min read
Jeon ilju
Frontend Engineer

Native ESM에 올라탄 마이크로 프론트엔드

토스증권의 마이크로 프론트엔드 아키텍쳐(MFA), 어떻게 구현되었을까요? Navtive ESM과 Import Map을 활용해 매우 큰 규모의 코드에서도 Silo별 독립 배포, 쾌적한 개발 환경, 빠른 사용자 경험을 동시에 달성한 과정을 소개합니다.

기존 1개 프로젝트 문제

  • 배포시 PR 이 여러개 중복
  • 변경 영향도 증가
  • 빌드시간 + 배포시간

마이크로 프론트엔드로 전환

도메인 분할 단위를 어떻게 가져갈 것인가?

⇒ Page 단위가 가장 적합했음

런타임 통합

각 페이지별 넘어가는게 많아서 js를 활용한 런타임 통합

SPA 처럼 동적으로 laze하게 불러오는 느낌으로 함

Native ESM

브라우저 ESM → 실행시점에 모듈을 다운로드

import B from "https://exmaple.com/hello.js"

위와같이 불러와서 처리함

해당 js를 보는 시점에 js 값을 불러옴

Import map

다운로드 될 내용을 직접 적용 가능함

<script type="importmap">
{
"imports": {
"@mfa/app-a": "/app-a.js
}
}
</script>

위와같이 불러옴

결국 import map을 어떻게 제공해주느냐가 문제임

⇒ 토스에서는 HTML 에서 서빙함

라우팅 테이블

해당 페이지로 접근했을때 app 을 동적으로 로드함

host app과 client app 간의 결합은 importmap 을 사용함

페이지 이동

보통은 하나의 앱 내에서 처리하는걸 기본으로 함

다만 이경우엔 페이지 이동이 앱 외부로도 가능해야함

info

이부분은 패스함…ㄷ

이게 노하우일것같은데ㄷㄷ

실제 구현

개별배포가 가능해야함

[이미지 첨부]

각각의 path를 보고 어떤 app을 불러와야하는지를 알 수 있음

라우팅 테이블은 동적으로 HTML을 만들어서 내려줌

배포

  • 걱 app이 배포가 되면 ImportMap값을 업데이트하여 새로운 사용자가 다시 올 수 있도록 처리함
  • 카라니 배포와 프리뷰 배포도 쉽게 처리가 가능함
  • 로컬 환경도 마찬가지로 importmap을 처리하면 가능함
    • localhost:3000을 넣으면 됨

번들 사이즈 최적화

공통으로 사용중인것들은 하나로 합침

info

다른거 하다가 못봤네 ㄷㄷ

언제나, 누구에게나, 평등하게 빠른 웹

‘성능 격차 없는 웹’을 목표로, 다양한 네트워크·디바이스 환경에서도 모든 사용자에게 빠르고 일관된 경험을 제공하기 위한 토스뱅크의 웹 성능 최적화 여정을 소개해요. CDN, Caching, Preload 등 다양한 기술을 활용해 웹의 한계를 극복하려 했던 실전 사례와 그 과정에서의 고민들을 함께 공유합니다.

네트워크 상태나 상황, 기기 등에 따라서 속도 문제가 생김

  • 네트워크 변수
    • 한 유저가 같은 경험을 하는것도 중요함
  • 모두에게 같은 성능 경험
    • 동일 네트워크 + 동일 하드웨어 성능
info

이게 가능한가? 기기가 다르고 네트워크가 다른데…ㄷㄷ

기기에 따라서는 고정변수니 네트워크에 집중함

SSR 방식으로 처리

js를 지연처리하여 화면을 먼저 보여주도록 처리함

마지막에 API dycjd

[나중에 pdf 나오면 캡쳐 넣자 - 크리티컬 랜더링 패스]

클라이언트의 네트워크 통신 상황에 따라 다름

vs 모바일 네이티브랑 비교해서 각각 필요한 리소스를 불러오는데 필요한 값들을 불러오는데 차이가 큼

⇒ 최대한 html, css, js를 가져오는 시간을 줄이자!

CDN 도 그중 하나임

Disk cache를 사용하는것도 괜찮은 방법임

http cache 전략을 잘 사용할것

디자인 시스템은 cdn으로 제공중임. 버전에 따라 다름

JS로직도ㅇㅇ

html에서 캐싱된 리소스를 요청하면 ㅇㅇ

html을 캐싱 안함

⇒ SSR 에서 html을 캐싱하면 문제가 생길 수 있음

클라이언트에서 데이터를 호출하는걸 최소화해서 처리하였음 ⇒ 서버에서 API 데이터까지 불러와서 처리함

stale while revalidate (SWR)

다음 버전의 정보를 미리 백드라운드에서 가져옴

최초 접근일때만 네트워크를 받아옴

info

항상 최초 화면을 보여줘야하는 경우엔 좋은 방법은 아닐 수 있음

payload

service worker 를 활용

⇒ 다양한 서비스를 제공하고 있는 곳에선 좀 어려웠음

App을 통해 Preload 사용

⇒ 어떤 리소스를 preload 를 할지 고민

  • 유입이 많은 페이지?
  • 첫 진입
preloadPages = ["/index", "/???"]

preload list 에 js와 css를 따로 저장함

앱이 원하는 타이밍에 preload list 를 가져와서 미리 캐싱을 해둠.

CDN 요청수가 너무 많음

신규 배포가 없는경우엔 CDN preload 를 하지 않도록 처리함

⇒e-tag

진입 가능성이 있는 유저만 preload 하도록 처리

  • 진입 경험이 있는 사람만 사용

daily preload

wifi 무제한 사용자?

info

이걸 어떻게 알지?

스토리지 사이즈

여러가지 요소를 보고 preload 할지 여부를 확인함

지표

FCP

얼마나 빠르게?

안쓰는 이유

  • 너무 잦은 배포로 preload 시간이 없음
  • CDN 요청 수가 너무 많음

더 나은 UX를 위한 프론트엔드 전략

토스뱅크가 더 나은 UX를 만들기 위해 어떤 노력을 해왔는지 소개하고자 해요. 누구나 할 수 있는 작은 시도들이 모여 어떻게 큰 사용자 경험의 개선으로 이어졌는지, 그리고 그렇게 만들어낸 UX를 꾸준히 지켜가기 위해 선택한 전략까지 함께 공유합니다.

로딩속도 + 안정성

로딩속도

SSR 활용

  1. 네트워크 구간
  2. 스크립트 구간
  3. 데이터 페칭 구간

SSR을 통해 html을 그려서 내려줘서 초기 로딩 속도가 개선되긴 함

어떤 영역을 SSR로 그릴것인가?

⇒ 금액 영역만 보기로 결정함

  • 비즈니스적 측면
    • 금액을 가징 먼저 보고싶음
  • 기술적 측면
    • 거래내역 API 응답까지 너무 오래걸림
    • 브라우저에 내려줄 HTML 사이즈가 너무 커질 수도 있음

거래내역은 클라이언트사이드 캐싱을 하기로함

localstorage 에 저장함.

두번쨰 진입부터 차이남

localstorage 에서 먼저 가져오고, ㅇㅇ

번들 사이즈

js 평가 시간을 줄이기 위한 노력임

  • 미사용 의존성 제거
  • 용량 큰 라이브러리는 작은 라이브러리로 대체
  • 같은 라이브러리지만 버전이 다른것을 정리
info

이거 옛날에 slash21 에 있는 js bundle 다이어트 참고

API waterfall 개선

API가 하나씩 feching

suspense 를 통한 처리

useSuspenseQuery 를 잘못하용하면 직렬로 API 를 호출하게 됨

⇒ useSuspenseQueries 를 사용하는게 나음

화면 안정성

천천히 보면 보이는 것들이 있음

  1. 금액이 다 보이고 깜빡임

    • 서버에서는 금액이 다 보임
    • 애니메이션이 진행되면서 안보였다가 fade in
  2. 카드 아이콘이 깜빡임

    • 클라에서 이미지를 결정했음.
    • 서버사이드에서 이미지를 내려주도록 처리
  3. 보내기 버튼 깜빡임

    • 송금 가능 여부에 따라서 enable / disable 처리를 하는중
    • 데이터를 가져오면서…ㅇㅇ
    • ⇒ 송금 가능한 사람이 더 많으니 enable 을 기본값으로 처리
    info

이건 트레이드 오프인듯

:::

  1. 광고배너의 레이아웃 시프트

    • 광고배너는 클라이언트 랜더링
    • 시간이 지나먼 바뀌어야하기에 cache 처리 불가 → 사용 내역보다 빠르게 노출이 불가능함
    • ⇒ 디자인적으로 해결
    info

이거 뭘 해결했다는거지?ㄷㄷ

이해를 못함

:::

LCP 최적화

LCP는 로딩 끝났다고 느끼는 시점

  1. 특정 API가 느린 문제

    ⇒ 동기적으로 호출하는게 문제임

  2. API 응답 시간이 느렸음

    • API 병렬 호출 제한
    • http 1.0 을 사용했음
  3. SSE을 활용 못했음

성능 개선 전략

aggregation API 도입함

⇒ 호출 갯수를

서버 fetching 실패하면 client 에서 refetch 하도록 처리하고 있음

상단 노출되는 부분만 SSR 하고, 아래쪽은 CSR 을 사용함

info

이정도로까지 해야되는구나;;

이후 대응

변경 이력 관리

  • 잦은 실험으로 인해 ㅇㅇ

계속해서 기록을 남기고 어떻게 되었는지 확인함

LCP 를 기준으로 ㅇㅇ

자동화된 LCP 모니터링

매주 LCP 성능 체크 하고 알림 시스템

이상 발생 시 즉시 분석하여 원인 파악