2022년 마지막 프로젝트의 회고 1

Lazy loading과 Suspense를 적용하며 컴포넌트 분리와 아키텍처의 필요성을 배운 프로젝트 회고.

Design Pattern, Frontend, React, Next.js

Prologue

Lazy loading과 Suspense라는 개념은 뭐고, 다른 사람의 React.js 프로젝트의 컴포넌트에서는 라이브러리를 왜 불러서 쓰는 것이며, 이걸 왜 React.js 라이브러리에서 지원하는 걸까? 같은 의문을 계속 가지고 있었지만 프로젝트와 취업 준비라면서 바쁘다는 핑계로 차일피일 미루다가, 이번 Next.js 프로젝트를 진행하며 배우고 다루게 되어서 많은 부분이 해소가 되었다.

Lazy loading & Suspence

Lazy loading은, 사용자가 보는 화면의 이미지만 미리 로드하고, 이후의 이미지는 필요한 때에 로드하는 기술이라고 한다. JS의 Intersection Observer API나 다른 서드 파티 라이브러리를 사용할 수도 있지만, Next.js는 프레임워크 내의 ‘next/dynamic’에서 dynamic 함수를 통해 ssr, suspense, loading 등의 다양한 옵션과 함께 제공해 준다.

Suspense는 비동기 작업을 진행하는 컴포넌트를 자식 컴포넌트로 가지며, 그 자식 컴포넌트가 비동기 작업을 진행하는 동안 fallback 속성에 할당받은 특정 컴포넌트를 렌더링 해서 보여준다. 쉽게 말하자면, 로딩 컴포넌트나 스켈레톤 컴포넌트를 사용하기 위한 기술이라고도 이야기할 수도 있다.

Suspense를 쓰지 않으면, waterfall 현상, 즉 상위 컴포넌트의 데이터 로딩과 렌더링이 끝나야만 하위 컴포넌트의 데이터 로드와 렌더링이 시작되는데, 통신 속도가 느리거나 통신 상태가 불안정한 경우, 웹 애플리케이션이 데이터를 로드하기 위한 시간이 길어져도 그동안 아무런 변화나 반응이 없기 때문에 사용자는 답답함과 불쾌함을 갖게 되고 사이트를 떠날 가능성이 커진다.

이를테면 어떤, 나 같은 경우에는 API 통신을 통해서 JSON 데이터를 받아오는 과정 중, 서버에서 데이터를 받아오는 동안 그 데이터를 보여줄 컴포넌트는 데이터가 없기에 아직 로드되지 않는다. 이럴 때 Suspense 기술을 통해 스켈레톤 컴포넌트나, 로딩 컴포넌트를 보여준다면, 사용자에게 일단 ‘무언가 동작하고 있구나’, ‘데이터를 기다리는 중이구나’ 라는 어느정도의 인터랙션은 보여줄 수 있다.

Trigger

이번에 진행한 프로젝트의 메인 기술이라고 할 수 있는 프레임워크는 Next.js다. Next.js는 프로젝트의 디렉터리 구조가 어느 정도 정해져 있다. pages 폴더와 그 폴더 내부의 api 폴더를 통한 API 라우팅, 그 밖의 컴포넌트나 유틸리티, 미들웨어 등.

하지만 마크업을 만들 때부터 통째로 코드를 만들었기에 참 사서 고생을 했다. 마크업을 만들어놓고, 그 마크업에 데이터를 연동하는 방식으로 프로젝트를 쌓아 올리다 보니 이미 데이터와 연결된 거대한 마크업 덩어리는 코드의 리팩터링과 최적화 과정을 모조리 어렵고 복잡하게 만들었다.

사용자 경험 향상을 시도하기 위해, 위의 기술의 채택과 적용에 있어, 코드를 더럽게 짜는 것에 신경을 끄고 당장의 사용자에게 비치는 클라이언트에만 올인할 게 아니라면, 컴포넌트를 더욱 잘게 쪼개야만 했고, 이미 복잡해지고 비대해진 코드 베이스는 정말 머리가 깨져가면서 해체와 재조립이라는, 선택이 아닌 필수적인 코스를 밟게 되었다.

Aftereffects

지금은 당연히 그런 컴포넌트를 분리하고, 프로젝트를 마쳐서 이런 회고를 쓸 수 있는 거겠지만, 체계적이고 구체적인 계획, 기준이나 아키텍처의 고려 없이 강제로 분리시키고 보니 직관적이지 않고 가독성도 나쁜 듯하다. 아무리 팀 프로젝트가 아닌 개인 프로젝트이고, 나는 프론트엔드 파트를 지향하였기에 디자인이나 백엔드적인 면모나 능력치가 상대적으로 어느 정도는 부족할 수 있다지만, 당장 아키텍처라는 추상적이고 거대한 개념부터 컴포넌트의 마크업 구조나, 레이아웃을 조금 더 치밀하게 설계하고 일관성 있게 개발하며, 이것보다 더 잘게 쪼개어 분리를 시켜야 할 필요성도 느꼈다.

그래야만, 당장 이 프로젝트는 단발성의 프로젝트로 끝날 확률이 높지만, 이후에 다른 스케일이 큰 프로젝트를 진행하거나, 실무에서 거대한 프로젝트의 유지와 보수를 맡을 때, 유지, 보수, 확장 모두 유연하고 간단해질 수 있다고 생각한다. 더구나 코드의 직관성도 올라가 다른 팀원이 볼 때도 지금처럼 굳이 복잡한 주석을 달지 않아도 보기 좋아질거라고 생각한다.

Decontextualize

‘남들 하니까’, ‘많이 사용해서’, ‘트렌드니까’ 하는 기술을 배우고, 그렇게 기술 스택을 늘리는 것은 조금 지양하는 편이 좋다고 생각하지만, 이제 와보니 그게 내가 스스로 그렇게 지향하고 있지 않았나 싶다.

그리고서는 욕심에, 이번엔 조금 더 규모가 크고 이것저것 디테일을 챙기는 프로젝트를 만들어보고 싶다면서, 이것저것, 이미 꽤 지나와서 그 이유는 기억나지 않지만, 어떤 문제가 생겨서 그 문제를 해결하는 데 상태 관리 라이브러리였던 Recoil을 사용하면 풀릴 거라는 가설 하에 기존의 지식 경험을 거슬러 올라가기도 했고 — 사실 이 부분은 잊고 있었던 Recoil을 복습하는 계기가 되기도 했지만 — , 다양한 인터랙션을 보다 쉽게 구현할 수 있어 좋아하던 라이브러리이면서 복습을 겸하기 위해 Framer-motion 같은 라이브러리를 채택할 계획 등을 세우기도 했다.

지금 생각하면 정말 실질적인 스텝 업을 할 수 있는 기회보다 화려하게 보이고 싶던, 그런 조금 부끄러운 계획과 고민이라고 생각한다.

이번에 배운 것은 겨우 Lazy loading, Suspense라는 단순한 개념과 기술에 불과하지만, 알게 된 부분은 그와 비교도 안되게 큰 것 같다. 더 큰 프로젝트와, 프로젝트의 유지와 보수, 확장, 그리고 협업과 언제나 혼자 개발하지는 않을 것이라는 사실 등. 그리고 그런 것들을 위한 아키텍처 구조의 고려와 더 보기 좋은 코드, 기술의 뚜렷한 사용 목적…

In Consequence

이전에 영화 & TV 시리즈 탐색 웹 애플리케이션의 React.js 프로젝트를 할 때는 리디 유튜브에서 소개한, 리디의 만타에서 사용하는 아토믹 디자인 기반의 아키텍처를 보고, 꽤 깔끔하고 정리가 잘 되어 있다는 생각이 들어서, 아토믹 디자인 시스템이라는 아키텍처 내지는 시스템 자체는 영 잘 모른 채로 그대로 적용을 시켰고, 상태나 함수를 포함한 로직과 컴포넌트 및 페이지를 크게 나누었던 경험이 있다. 그때는 Lazy loading이나 Suspense의 개념은 몰랐지만.

그래서, 이번 프로젝트는 아토믹 디자인 시스템이라는 아키텍처를 보다 제대로 알고 배워서, 체계적으로 적용시켜보기로 했다.

References

리액트 어플리케이션 구조 - 아토믹 디자인


원문: Medium