넥스터즈 24기 어나더미 개발 회고

스탁벅스·2024년 5월 13일
11
post-thumbnail

지난 1월부터 3월까지 넥스터즈에서 만든 서비스, 어나더미 개발에 대해 회고해 보겠습니다.
넥스터즈 활동하면서 개발할 당시에는, 간단한 사이드 프로젝트이고 개인적으로 기술적 도전을 시도한 것들이 많지 않아서 따로 회고하거나 개발 내용을 문서화하지 않았는데요, 오랜만에 이력서를 뜯어 고치면서 어나더미때 무엇을 했나~ 다시 살펴보니, 그와중에 나름 노력하고 고민했던 것들이 보이더라고요. 그래서 늦게나마 이번 글을 통해 흐릿해진 기억과 노력들을 기록해보고자 합니다.

아래 내용은 서비스에서 제가 맡아 개발한 내용 위주로 작성했습니다 :)

새로운 시도: UI 라이브러리, shadcn/ui

넥스터즈에서는 8주만에 하나의 서비스를 완성시켜야합니다. 이 8주라는 시간이 얼마나 짧은지 시작 전에는 몰랐습니다. 그냥 적당히 시간 많이 투자하면 되겠지~라는 매우 안일한 생각을 하였는데요, 다행히 지난 기수에 8일 같은 8주를 미리 경험한 같은 프론트엔드 팀원 형이 먼저 shadcn 으로 UI를 만들자고 제안을 해줬습니다.

이미 월클 라이브러리인 shadcn이라 아마 많은 분들이 아시겠지만, shadcn은 매우 인기있는 Headless UI 라이브러리인 Radix와, Tailwind-css를 이용해 만들어진 UI 라이브러리입니다.

shadcn이 독특한 것은 좀 색다른 방법은 설치 방식인데요, 라이브러리 전체를 다운받고 컴포넌트를 골라 사용하는 것이 아닌, 컴포넌트가 구현된 raw한 코드를 다운받는 방식입니다. 즉, 프로젝트에 shadcn이 디펜던시로 종속되지 않습니다.

예를 들어, CLI에

pnpm dlx shadcn-ui@latest add button

를 입력하면, 프로젝트에 자동으로 아래와 같은 소스코드가 추가됩니다.

const buttonVariants = cva(
    'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
    {
        variants: {
            variant: {
                default: 'bg-primary text-primary-foreground hover:bg-primary/90',
                destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
                outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
                secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
                ghost: 'hover:bg-accent hover:text-accent-foreground',
                link: 'text-primary underline-offset-4 hover:underline',
            },
            size: {
                default: 'h-10 px-4 py-2',
                sm: 'h-9 rounded-md px-3',
                lg: 'h-11 rounded-md px-8',
                icon: 'h-10 w-10',
            },
        },
        defaultVariants: {
            variant: 'default',
            size: 'default',
        },
    },
);

export interface ButtonProps
    extends React.ButtonHTMLAttributes<HTMLButtonElement>,
        VariantProps<typeof buttonVariants> {
    asChild?: boolean;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
    ({ className, variant, size, asChild = false, ...props }, ref) => {
        const Comp = asChild ? Slot : 'button';
        return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />;
    },
);
Button.displayName = 'Button';

export { Button, buttonVariants };

사실 제가 shadcn을 UI 라이브러리라고 표현했지만, 이러한 이유 때문에 shadcn의 공식문서에서는 본인을 라이브러리가 아니라고 표현합니다.

This is NOT a component library. It's a collection of re-usable components that you can copy and paste into your apps.

(라이브러리라고 해서 죄송합니다🙏)
아무튼 tailwind와 shadcn을 이용한 덕분에 UI 개발에 큰 시간을 쏟지 않을 수 있었습니다. 또한, 잘 만들어진 컴포넌트를 가져와 사용하면서 어깨 너머 좋은 컴포넌트 설계를 엿볼 수 있었습니다.
특히, Radix가 asChild prop을 이용해 polymorphic한 컴포넌트를 제공하는 방식이 흥미로웠던 것 같습니다. 회사에서 사용하는 디자인 시스템과 비교도 하며, 컴포넌트 설계에 대한 다양한 방식을 이해할 수 있는 기회가 되기도 했습니다.

물론, shadcn이 은색 탄환이 되지는 못했습니다. 몇몇 shadcn의 컴포넌트들은 저희 디자이너가 원하는 스타일과 너무 괴리가 커서, Radix를 직접 이용해 직접 만들기도 했으며, 어쨋든 shadcn이 제공한 컴포넌트의 세부 스타일 수정이 필수적이었습니다. 또한, Radix에서 설정한 디폴트 이벤트들로 인해 원치 않은 동작들이 발생하여 난감할 때도 있었습니다.

퍼널 구현하기

제가 어나더미에서 가장, 매우, 압도적으로 시간과 노력을 많이 쏟은 파트가 있었는데요. 바로 캐릭터를 생성하는 퍼널이었습니다.
저희 천재 PM님 서비스의 이용률을 높이고자, 로그인이나 회원가입을 하지 않아도 캐릭터를 생성할 수 있게 하자! 는 도전적인 아이디어를 주셨습니다. 따라서, 생전 처음 저희 서비스를 이용하는 사람도 캐릭터 생성을 할 수 있게 만들었고, 그렇기 때문에 캐릭터 생성 과정에서 좋은 유저 경험을 주는 것이 필수적이었습니다.

웹앱에서의 퍼널 구현은 생각했던 것 보다 난이도가 있었습니다. 레퍼런스를 찾아봐도 딱히 인상적인 구현을 찾지 못해서 직접 만들어 보았습니다.

shadcn의 carousel의 도움을 받아 구현했습니다. 캐러셀의 페이지가 현재 url 경로에 의존하게 하여 퍼널의 다음 스텝으로 넘어가면 경로가 바뀌고 그에 따라 캐러셀의 페이지가 바뀌도록 하였습니다. 또한 퍼널을 입력값들을 하나의 Context로 관리하였는데요, 입력값들을 상태가 아닌 useRef로 관리하여 퍼널 전체가 리렌더링 되는 일이 없도록 신경썼습니다.

애니메이션 & 인터렉션

게이믹한 우리 서비스의 특성상 다양한 애니메이션의 도움을 받을 필요가 있었습니다.
대부분의 애니메이션들을 Framer-motion을 이용해 구현했습니다. Framer-motion은 쉽고 선언적인 api를 제공한다는 점이 매력적인 것 같습니다.

정말 애니메이션이 있다면 조금이라도 낫겠다 싶은 곳에 전부 애니메이션을 넣었습니다.
위 캐릭터 생성 퍼널만 해도, 퍼널의 페이지 전환 시 애니메이션이 있고, 자세히 보면 stepper에도 레이아웃 애니메이션이 적용되어 있습니다.

아래는 그 외 애니메이션을 활용한 몇가지 예시들입니다.

디자이너와 애니메이션 세부 스펙을 하나하나 짚고 넘어가기에는 리소스가 턱없이 부족해서, 대부분 제가 알잘딱으로 구현했습니다.

두 번째 예시 같은 경우는, 캐릭터의 경험치가 올라갈 때 워낙 소리소문 없이 올라가다 보니까 조금 더 재미와 임팩트를 주고 싶었고, 프로그레스바가 실시간으로 올라가는 애니메이션을 주자는 아이디어와 함께 구현을 해봤습니다.

이러한 시도들 덕분에 서비스가 조금 더 생동감이 생긴 것 같아서 뿌듯했습니다.

Next.js 14

Next.js 14 버전을 겁 없이 사용해보았고 서버컴포넌트를 최대한 활용하려고 노력했습니다.

결론은.... 그리 좋은 선택은 아니었던 것 같습니다. 번들 사이즈 걱정할만한 프로젝트도 아니었고 검색엔진 최적화도 별로 중요하지 않은 서비스이다 보니 오버엔지니어링을 한 느낌도 없지 않아 있습니다. Server Action은 사용할 필요도 못느꼈습니다. 리액트 쿼리와 함께 사용했는데, 둘의 궁합도 그다지 좋지 않다는 것을 제가 작성한 이전 글 관련 학습하면서 느꼈습니다.

저도 악명 높은 Next.js 14의 버그들을 몇 가지 피해가지 못했는데, 가장 짜증났던 버그는 Vercel 배포 시, 빌드가 안되는 이슈가 있었습니다.

에러 메시지만 봤을 때는 정규표현식 문제인가? 싶었는데 많은 사람들이 겪은 버그더라고요. 다행히 최신 버전에서 저 버그는 고쳐졌다네요 🥲

최근에 Remix가 DX가 좋다는 이야기를 많이 들어서 다음에는 사용해보고 싶다는 생각이 듭니다.

프로젝트를 마치며...

최근에 했던 넥스터즈 25기 모집 홍보 인터뷰에서도 말했듯이, 이번 프로젝트를 통해 기술적인 성장도 있었지만, 인격적인 성장을 많이 한 것 같습니다. 최근 회사에서도 소프트한 스킬의 중요성을 많이 느끼는데, 그런면에서 저에게 많은 깨달음을 준 프로젝트였다고 생각합니다.
다음에는 어떤 재밌는 사이드 프로젝트를 할지 두근거리는 마음을 가지고 이 글을 마칩니다.

profile
환영합니다. 스탁벅스입니다.

4개의 댓글

comment-user-thumbnail
2024년 5월 13일

멋지네요 :)

어나더미 사용해보았는데 사용자의 눈을 즐겁게하는 애니메이션들이 인상 깊더라구요.

특히, 좋아요를 클릭했을 때 발생하는 Lottie가 가장 인상깊었습니다.

스탁벅스님의 다음 행보가 기대되는 글입니다. 좋은 글 감사합니다.

1개의 답글
comment-user-thumbnail
2024년 8월 28일

코드아티스트 스탁벅스..그는 그저 GOD...🔥

1개의 답글