웹 서비스의 기획 단계부터 참여 및 배포 경험
- 실제로 서비스되는 웹서비스를 기획단계부터 배포까지 함께했습니다.
- 디자인, 마케팅, 운영팀 등 다른 팀과 많은 커뮤니케이션을 진행했습니다.
문제 상황에 대한 빠른 상황 판단과 해결 경험
함께 성장하는 것을 좋아합니다.
📮 email : [email protected]
📚 개발 블로그
deli-ght (minju) - velog
💻 github
deli-ght - Overview
Project
VESSL Blog
새로운 기술이나 회사의 소식을 공유하는 베슬 블로그 및 어드민 페이지
https://blog.vessl.ai/
사용 스택
Nextjs 14, TypeScript, PandaCss, Prisma, MDX-editor, Vercel postgres, Vercel Blob, NextAuth.js, Vercel
누구나 쉽게 사용할 수 있는 admin 페이지
- 편리하고 커스텀 가능한 에디터를 위해 Novel, Quill, MDX editor 등 여러가지 라이브러리를 시도해 보고, Wysiwyg 방식과 커스텀이 가능한 MDX editor를 선택했습니다.
다양한 SEO 방법을 적용
- Google Search Manager를 활용해, 검색률을 높이고 SEO상태를 관리했습니다.
- sitemap.xml/route.ts 파일을 작성해, 글이 업로드될 때마다 자동으로 Sitemap에 추가되도록 했습니다.
Next 14 PoC 진행
- Route group 을 이용해 어드민 페이지와 실프로덕트를 모노레포로 작업했습니다.
- Server component에서 사용 가능한 CSS-in-JS 인 Panda CSS를 Product 도입 전 PoC 개념으로 사용해보았습니다.
- RSC에서 겪을 수 있는 다양한 문제들을 직접 경험해보고, Website v2에 녹여냈습니다.
- 블로그 개발에 대한 사내 발표를 진행해, 관련 경험을 팀원들과 공유했습니다.
백엔드 작업의 러닝커브를 줄이기 위한 Vercel products 사용
- 백엔드 작업을 짧은 시간 내에 구현하기 위해 vercel에서 제공하는 prostgres와 blob을 사용해 데이터를 저장했습니다.
VESSL AI Product
회사에서 제공하는 메인 서비스입니다. AI 개발에 필요한 모델 선택, 학습, 배포, 운영 등의 서비스를 GUI 형태로 제공합니다.
https://vessl.ai/
사용 스택
Nextjs, Typescript, Tanstack query, Storybook, Vanilla extract, Evergreen, Recoil
라이브러리 정리 및 코드 리팩토링
- 기존에 적용되던 MUI 의존성을 없애고, 회사 내부의 디자인 시스템을 사용하도록 리팩토링하였습니다. 이 과정에서 Deprecated된 함수나 컴포넌트를 사용하고 있던 경우, 새롭게 대체되는 컴포넌트로 교체해주었습니다.
- React 18 마이그레이션 진행 및 관련 코드 업데이트를 진행했습니다. 업데이트 중 렌더링 방식 변화에 따른 문제를 겪었고, React 18의 automatic batching에 대해 공부하며 해당 이슈를 해결했습니다. 또한 React 18 변경사항에 의존적인 라이브러리들을 함께 업데이트하며, 남용되고 있던 라이브러리를 정리해 하나의 라이브러리만 사용하도록 정리했습니다.
Middleware를 활용한 유저 인증 상태에 따른 뷰 구현
- 탈퇴 후 회원이 재 로그인된 경우, 미들웨어를 사용해 접근을 제한하였습니다.
- 제품 사용중 소속된 Organization이 없어지거나, Default organization이 없어지는 경우 항상 생성 페이지로 이동시키기 위해 미들웨어를 사용해 redirect 시켰습니다.
자동화 스크립트를 통한 안전한 Docs 연결
- 리뉴얼되는 Docs에서 사라진 문서를 유저에게 보여주는 경우를 막기 위해, Docs 사이트의 sitemap을 긁어와 링크를 상수로 만들어주는 스크립트를 작성했습니다. Docs 링크를 참조하는 경우 해당 상수를 가져와 사용하여 빌드타임에 링크가 없는 경우를 발견하고자 했습니다.
VESSL Design System
새롭게 리뉴얼 될 웹사이트에서 사용되는 디자인 시스템
재사용성을 고려한 디자인 시스템 구조
- Composition 컴포넌트와 Core 컴포넌트로 구분해 피그마상에서 대응할 수 없는 컴포넌트 개발에 대비했습니다. Core는 Radix에 기본 스타일이 적용된 주로 Compound 형식의 컴포넌트이며, Composition은 피그마와 Props가 정확하게 일치하는 컴포넌트로 나누어 개발상의 편리함과 디자이너와의 일관성을 모두 가져가고자 했습니다.
효율적이고 안정적인 컴포넌트 제작
- Storybook에 해당하는 컴포넌트와 props에 따른 Variants를 한 눈에 볼 수 있도록 해, 안전하게 UI 변경사항을 확인 할 수 있습니다.
- Radix를 이용해 예상치 못한 에러 발생 확률을 줄이고, 접근성을 고려했습니다.
- 디자이너와의 커뮤니케이션을 통해 개발과 디자인에서 사용되는 언어를 일원화시켰습니다.
타입 안정성 기반으로 DX 개선
- String literal과 Tagged union을 이용해 컴포넌트 타입에 따라 해당하는 props만 입력 가능하도록 제작했습니다.
- Radix와 vanilla-extract에서 제공하는 타입을 이용해 안전하게 타입을 사용하도록 했습니다.
RSC에서 사용 가능한 컴포넌트
- 처음에 Panda CSS 도입을 검토했으나, PoC 결과 해당 라이브러리는 static time generation 에서 스타일이 생성되는 이슈로 dynamic 스타일링이 어려워 디자인 컴포넌트에서 사용은 어렵다는 판단을 내려 vanilla extract을 도입했습니다.
- RSC는 상태를 갖지 않는 컴포넌트기 때문에, 디자인 시스템 컴포넌트 내 상태 사용을 지양했으며 필요에 따라 ‘use client’를 상단에 명시해 RSC에서의 사용에 대비했습니다.
VESSL Hub
오픈소스 머신러닝 모델들을 살펴보고, YAML 파일을 이용해 빠르게 학습 및 실행하는 서비스
https://vessl.ai/hub
VESSL Run
생성형 AI 모델 학습, 배포, 운영을 인터페이스로 쉽게 제공하는 서비스
UX를 고려한 YAML-Form 싱크 구현
- 복잡한 YAML을 유저가 직관적으로 작성할 수 있도록 Form 입력시 우측에 Yaml로 전환되는 UI를 제공했습니다. React-hook-form을 사용하였으며, zod를 이용해 validation을 진행했습니다.
- Sync 과정에서 Race condition이 발생해 이를 해결하기 위해 상태 Flag를 만들어 의도되지 않은 상태 변화를 방지하였습니다.
커스텀 훅을 이용한 복잡한 로직 분리
- Chart 뷰를 구성하기 위한 Dashboard 페이지에서 커스텀 훅을 이용해 복잡하고 공통된 로직들을 한데묶어 사용해 일관성을 높였습니다.
VESSL Serve
빠른 AI 모델 배포를 위한 서비스
다중 모델, 다중 포트 생성이 가능하고, 로드 밸런싱과 오토스케일링을 지원해 효율적으로 리소스 사용이 가능하도록 합니다. 또한 모델 성능과 GPU 사용량을 실시간으로 모니터링 할 수 있습니다.
사용자 실수 대응을 위한 안전망 구축과 피드백 시스템 구현
- Localstorage를 이용한 임시저장 기능 구현해 복잡한 폼 작성 중 유저가 실수로 폼을 닫아도 가장 최근에 작성하던 저장되지 않은 폼을 다시 작성할 수 있도록 구현했습니다.
- 폼 특성상 모든 폼 에러 메세지를 보여주지 않고 있어, 폼 제출이 불가능한 경우 <FormReportButton/>을 생성해 폼 상단에서 모든 에러를 확인하고 유저가 보고할 수 있도록 했습니다. 또한 유저가 보고 버튼을 누르는 경우, Sentry로 알람이 전송되어 바로 확인할 수 있습니다.
Landing pages
VESSL 제품 소개를 위한 Landing page
사용 스택
React, TypeScript, Emotion
Tailwind 코드에서 Emotion으로 migration
- 피그마와 동일한 언어를 사용하기 위해, 기존에 tailwind로 작성되던 코드를 emotion으로 마이그레이션했습니다.엔지니어가 작업을 수행하기 위해 배워야 하는 또 다른 레이어를 추가하고 싶지 않았습니다.
- CSS가 아닌 CSS-in-JS 를 사용하므로써, 한 파일 내에서 다양한 인터렉션에 대한 흐름을 쉽게 읽을 수 있도록 했습니다.
다양한 디자인 요구사항 구현
- 타임라인 기반의 애니메이션 라이브러리인 GSAP을 이용해 스크롤에 따른 타이핑 애니메이션을 구현했습니다.
- 배경에 SVG 요소를 넣어야 하는 요구사항을 구현하던 중, 모바일 사파리에서 깨지는 것을 발견하였고 이를 하나의 컴포넌트가 아닌 background요소로 변경해 CSSOM 단계에서 렌더링이 되도록 해 문제를 해결하였습니다.
- 지속적인 그로쓰, 디자인 팀과의 커뮤니케이션을 통해 완성도 높은 랜딩페이지를 만들고자 했습니다.
HTTP 프록시 미들웨어를 활용한 Google Spreadsheet 연동
- http-proxy-middleware를 이용해 랜딩에서 유저가 제출한 waitlist를 growth팀의 google spread sheet에 보내 목록을 한군데에서 받아 볼 수 있도록 했습니다.