프론트엔드 라이브러리 프로젝트 운영
- 100명이 넘는 모든 사내 프론트엔드 개발자가 사용하는 라이브러리 프로젝트의 운영에 적극적으로 참여했습니다. 입사 후 가장 먼저 목표한 것은 토스의 프론트엔드가 만들어지는 모든 기반 환경을 전부 파악하는 일이었고, 가장 흥미있게 본 것이 공용 라이브러리 프로젝트였던 것이 시작점이었습니다.
- 크고 작은 기여를 정말 많이 하게 되면서 모듈 시스템, 번들링, 모노레포 등 Node.js 라이브러리 개발과 운영에 대해 깊이 이해하게 되었고, 또한 라이브러리 프로젝트에 대한 거의 모든 질문과 이슈에 답하고 대응할 수 있을 정도로 주요한 기여자가 되었습니다. 이런 이해도를 바탕으로 거대 오픈소스의 내부 구현으로부터 근본적인 원인을 찾아내 문제를 해결해드리기도 했습니다.
- 그러다보니 프로젝트의 운영에 비효율이 보이기도 했는데, 이미 새로운 기능을 다 구현하고 올린 PR에서 해당 기능의 필요성에 대해 논의하는 등, 사전에 논의를 했다면 시간을 아꼈을 것으로 보이는 일이 많았습니다. 따라서 실제로 작업을 해서 PR을 올리기 전, 작업의 필요성과 구현체의 인터페이스 등을 Issue로 올려 미리 논의하는 PoC 프로세스를 도입하여 메인 리뷰어로 활동했습니다.
- 라이브러리 프로젝트 일부를 오픈소스화한 Slash 프로젝트의 메인테이너로 활동하기도 했습니다.
웹 네비게이션 바 프로젝트 리딩
- 토스 웹뷰 제품의 상단 네비게이션 바는 네이티브 단에서 렌더링됩니다. 하지만 디자인 요구사항에 따라 네비게이션 바의 스타일을 복잡하게 수정해야 하는 경우가 많았습니다.
- 이미 그것을 가능하게 해주는 네이티브단의 구현체가 존재하긴 했지만, 사용하지도 못할 만큼 동작에 버그가 너무 많았고, 코드레벨에서만 제어할 수 있는게 아니라 어드민 웹에서도 설정이 가능한 예측 불가능한 구조로 이루어져 있었습니다. 또한 프론트엔드 단 구현체는 불필요하게 여러 라이브러리와 강결합 되어있었습니다. 결국 개발자들이 본인의 작업 보다는 상단 네비게이션 바의 동작을 디버깅하는 것에 더 많은 시간을 쏟게 되는 일이 빈번했습니다.
- 개선 작업을 위해 이 문제에 접근한 방식은 기존 구현체의 동작이 너무 복잡해지고 불안정해진 근본적인 시작점을 찾는 것이었습니다. 애초에 네이티브에서 웹 제품의 UI 일부를 책임지려고 했던 것 자체가 유연하지 못한 설계였습니다. 기존 구현체의 버그를 하나씩 고쳐나가는 일은 여전히 네이티브와 웹이 UI 책임을 나눠갖게 하는 방식이므로, 이 문제를 근본적으로 제거하려면 웹뷰를 디바이스 스크린 전체에 렌더링하여 모든 UI 책임을 웹뷰가 갖도록 하는 새로운 구현체를 만들어야 했습니다.
- 그 결론에 초점을 맞추어 iOS, 안드로이드 개발자 분들과 긴밀히 협업하였고, 강결합 없이 완전히 독립적으로 동작하며 서비스 코드 한 곳에서만 제어되는 새로운 웹 네비게이션 바 라이브러리를 만들어 기존에 불편을 겪고 있던 수많은 서비스에 안정적으로 적용하였습니다.
날짜, 시간 데이터 교환시 타임존 도입
- 토스 서버에서는 API에서는 날짜, 시간 데이터에 타임존을 명시하고 있지 않았습니다. 토스의 물리 서버는 모두 한국에 위치해 있다는 이유 때문이었습니다. 기본적으로 UTC를 기준으로 하는 Unix Timestamp로 관리하는 것도 아니었습니다. 결국 프론트엔드 개발자가 직접 서버가 내려준 ISO 8601 문자열에
+09:00을 임의로 붙여서 사용하는, 유연하지 못하고 암묵적이며 비직관적인 구현을 해야했습니다.
- 또한 이런 암묵적인 규칙을 모든 프론트엔드 개발자가 알고 있는 것도 아니었습니다. 따라서 해외로 출국하여 토스앱을 사용하게된 유저들의 문의가 들어와 장애 대응을하는 일이 밤낮을 가리지 않고 빈번했습니다. 개발자 경험 뿐만 아니라 유저에게까지 악영향을 주고 있음에도 누구도 해결하려 나서지 않는 심각한 문제였습니다.
- 바로 타임존의 필요성에 대한 글을 작성하여 사내 개발자 전체가 즉시 확인할 수 있는 채널에 공유하여 정식으로 공론화했습니다. 이는 토스가 실제로 글로벌 사업을 시작하게 되면서 아주 중요한 기반이 되었습니다.
대용량 3D 리소스 용량 92% 절감
- 카드 디자인을 선택하는 화면에서 리소스를 효율적으로 로딩하도록 리팩토링을 하던 중, 3D 리소스의 크기 자체가 근본적으로 너무 크다는 문제를 발견하게 되었습니다. 유저가 5가지 디자인을 모두 둘러보는 경우 다운로드 받는 리소스 용량의 총합은 21.5MB였습니다.
- 카드는 모서리가 둥근 직사각형이라는 아주 단순한 형태를 가지며 색상 또한 복잡하지 않은 조합으로 이루어져 있었으므로, 용량이 큰 이유를 그저 3D 리소스이기 때문이라고 치부하기엔 근거가 부족했습니다. 분명히 최적화할 수 있는 부분이 아주 많이 존재할 것으로 보였습니다.
- 그래픽 디자이너 분과 함께 용량을 많이 차지할만한 부분을 제거해가며 리소스를 다시 뽑아내는 것은 좋은 해결책이 아니며, 그걸 알아서 다 해주는 최적화 도구가 분명히 있을 것이라고 판단하였고, 구글에서 개발한 3D 리소스 압축기인 Draco를 찾아 사용하게 되었습니다.
- 무리해서 압축을 하면 리소스 외관이 손상되는 문제가 있어서 리소스 별로 여러번 테스트를 거쳐 손상이 없는 최소 용량으로 압축했고, 모든 리소스 용량의 총합을 1.8MB까지 대폭 줄일 수 있었습니다. 이는 기존의 21.5MB에서 92%나 개선된 수치입니다.
- 카드 디자인 선택 화면은 하루에도 수천명 단위의 신규 유저가 유입되는 곳이므로, 유저 네트워크 비용 뿐만 아니라 CDN 인프라 비용도 크게 개선할 수 있었습니다.
저금통 대표 이미지 생성과 마이그레이션
- 팀에서 청소년이 목표를 설정하여 저축을 할 수 있는 저금통 제품을 운영하고 있었는데, 토스앱 홈에서 유저가 가지고 있는 저금통 목록을 보여줘야 하는 요구사항이 생겼습니다.
- 홈은 Server Driven UI로 이루어져 있었는데, 그곳에 정의된 리스트 아이템 컴포넌트는 대표 이미지 파일을 요구하고 있었습니다. 하지만 저금통 제품에서는 유니코드 이모지 하나와 배경색 색상 코드를 각각 문자열로 가지고 있을 뿐, 그걸 하나의 이미지 파일로써 가지고 있진 않았습니다.
- 여기서 선택지는 두 가지였습니다. 홈 팀에서 저금통의 기존 데이터 형식에 따라 새로운 컴포넌트를 정의하고 네이티브에서 대응한 뒤 버전 분기를 만들거나, 저희 팀에서 저금통이 대표 이미지를 갖도록 마이그레이션을 진행하거나.
- 전자로 진행하면 홈 팀의 iOS, 안드로이드, 서버 개발자 세 분과 소통해야하며 결과물에 최소 버전이 생기기 때문에, 작업의 요구사항은 "저금통 목록을 보여준다"로 간단한 것에 비해 과정이 복잡하다고 생각했습니다. 반면 후자로 진행하면 저와 저희 팀의 서버 개발자 분만 작업하면 되었고, 무엇보다 유저 경험에 결정권이 있는 동료분이 버전 분기 없이 전체 반영이 되길 희망하셨기에 후자를 선택했습니다.
- 대표 이미지를 생성하는 코드 구현 자체는 간단했습니다. 이모지를 유니코드로 변환하는 방법을 공부하여 토스페이스 이미지 파일을 불러왔고, sharp 라이브러리를 사용해 불러온 이미지 뒤에 배경색을 입혔습니다.
- 고민이 되었던 지점은 저금통의 대표 이미지를 요청이 왔을 때 실시간으로 생성하여 영구 캐싱할지, 미리 모든 경우의 수에 대해 대표 이미지를 생성 해둘지를 결정하는 것이었습니다. 저금통을 생성할 때 선택할 수 있는 이모지는 약 3000개이고 배경색이 8종류로 제한되어 있었기 때문에, CDN 앞에 새로운 인프라 구성을 필요로 하고 캐시 적중률도 높지 않을 전자에 비해 작업 비용과 인프라 비용 모두 저렴했던 후자를 선택했습니다.
- 다른 방식을 선택했다면 타 팀과 소통하며 개발에 일주일 이상, 모든 유저에게 노출되기까지 3주 이상이 걸렸을 일이었지만, 위 방식대로 진행하여 단 2일만에 마무리할 수 있었습니다.