뭐? 땔감 주제에 Next.js 사이트를 만들 줄 안다고? 이새끼 정신나간거 아니냐?

그래. 정신 나갔다. 마침 이 글 쓰려고 하는 찰나 벨로그도 Next.js 로 교체하는 것도 모자라 앱라우터로 바꿨다며?

벨로그 v3 업데이트 소식

게다가 이 사이트 소스를 오픈한 줄은 몰랐다.

velog-io/velog

난 그것도 모르고 dev.to 처럼 임베딩할 수 있는것도 별로 없고 소스코드 강조 기능에 지원 언어도 부족하고 이것저것 부족한 게 많아서 어따가 불만을 토로해야 할 지 이 벨로그에 어따가 올려야 할지 막막했는데 더 막막해졌다(?).

삼천포 또 빠질라칸다. 이제 본문 시작하겠다.

서버 컴포넌트는 구세주다.

node.js 프로젝트 생태계는 씨잘대기 없이 많은 종속성을 달고 살아야 한다.
내가 자바충이라서 그런지 쓸데없는 종속성까지 들고 이걸 활용한다는 것은 "나 이거 쓴다 잘났지" 정도로밖에 안보인다.

내게는 심플 이즈 베스트다. 종속성은 최소로 할 수 있으면 하는게 최선이라는 게 내 신좁니다.

올리고 나니 존나 많네 파편화된 aws와 radix-ui가 아주 뻥튀기 만들어놨네.
자, 여기서 너희들이 궁금한 거 몇가지가 있을 거다.

  • 비동기 통신 어쩔티비? 왜 React-query 안 써?
  • 전역 상태관리 안 쓰냐? Redux나 Recoil 등은 어디갔냐? 네가 찬양하던 Zustand 는?
  • 잠깐, TailwindCSS를 쓴다고? Emotion이나 Styled 같은 모듈형을 안 쓰는 비정상적인 리액트 개발자가 있어?

그래. 그게 나다.
아마 너희들이 국룰이라고 생각하는 Next.js 의 종속성은 아래와 같을 거다.
아래는 오픈으로 푼 Velog의 Next.js 프로젝트 종속성이다.

캬아. React-query, GraphQL, Axios... 대한민국 Next.js 의 국물이 다 들어있다. 시원~하지?
근데 얘도 전역상태관리 따로 없네? 얘도 뭘 좀 아는군 (흐뭇)

자, 이제 서버 컴포넌트가 왜 내게 구세주인지 알려주겠다.
만약 서버 컴포넌트가 없다면 니네들 말이 맞다. React-query가 없으면 데이터 가져오기에 대한 상태관리가 매우 불편하다. 그게 리액트 특이다.
하지만, 서버 컴포넌트가 있으면 이런 고민 싹 없애준다.

이 소스는 파트너 회원관리 페이지 소스 중 일부다. 물론 일부라기엔 사실상 저게 다다.
그냥 DB든 외부 API든 가져와서 리턴하는 게 전부고, 여기서 서버 컴포넌트를 더 껴서 관련된 정보를 가져오는데 다 저런 패턴이고, 잘 작동한다. 복잡하게 react-query 같은거 필요없다.

게다가 서버 컴포넌트 아래 서버 컴포넌트 깔아놔도, 검색조건 등 필요한 조건 바뀌면 알아서 잘만 불러와준다.
걱정일랑 안해도 된다. 최소한의 서버 컴포넌트가 껴도, 렌더링 조건이 바뀌면 작은 서버 컴포넌트만 바뀌지 페이지 자체는 가만히 있다.
Next.js 가 서버 컴포넌트 표준을 위해 얼마나 공을 들였는지 알 수 있는 대목이라 하겠다.

따라서, 서버 컴포넌트가 있으면, react-query 따위 저리가라가 가능하다.
단, 예외가 있는데, Next.js 로 정적 사이트 배포할 생각이라면, react-query 깔아라. 뭣도 모르고 서버 컴포넌트 썼다가 빌드 시점 이후 데이터만 똑같이 나오는 꼬라지 보고 후회하지 말고.
지금 이건 서버 렌더링 모드다. 알고 진행해야 한다.

캐시는 각자도생

하지만 평소에 리액트를 써오던 개발자들에게 서버 컴포넌트는 뭔가 부족해도 너무 부족하게 느껴질 것이다.

첫번째, 컴포넌트간 데이터 연동할 수 있는 방법이라고는 속성(Props)밖에 없다.
두번째, Context 등의 컴포넌트 간 연계되는 시스템을 지원하지 않는다.
세번째, use*** 같은 훅 함수 자체를 지원하지 않는다 (useId만 되고, 추후 use 함수는 지원 예정)

이렇게 돌아가면 결국 서버 컴포넌트마다 같은 API를 불러와야 하는 상황이 필연적으로 생기기 마련인데,
이대로 두면 같은 API를 여러번 호출하게 되어 API 트래픽을 비효율적으로 많이 사용하게 되는 상황이 당연히 생기는 법.
그래서 Vercel이 이런 서버 컴포넌트의 비효율성을 막고 효율적으로 서버 컴포넌트의 데이터 관리를 위하 선택한 최선의 방법이 바로 캐시다.

이런 백그라운드 때문에, Next.js 의 캐시는 기본적으로 켜져 있고, 엄격하며, 완전히 끄는 방법이 없다.
말고 많고, 탈도 많다. 조건도 빡세고, 캐시 관리까지 신경써야 하니 귀차니즘이 더 늘게 만든다.

나도 처음엔 불편했다. Next.js 팀도 불편한 걸 인지하고 있고, 캐시에서 나오는 버그들이 많다 보니,
버전업이 상당히 빠르다. 그래도 캐시 문제에 대한 대응을 차근차근 하고 있으니 이건 칭찬할 만 하다.
지금? 그냥 적응했다. 어쩔 수 없다. 서버 컴포넌트 간 통신이 가능한 더 효율적인 방법이 없는 한은...
물론 세션 방식의 Context 가 있다면 좋겠지만, 그걸 적용하려면 먼저 Vercel이 지들 클라우드부터 맞춰줘야 하니 말이지.

만약 page 라우팅 방식이라면, 기존 그대로 쓰면 된다. 어자피 서버단 코드 자체의 최종 소비지가 페이지 컴포넌트 뿐이니.
하지만 app 라우팅 방식을 쓰면, 페이지 컴포넌트, 레이아웃 뿐 만 아니라 누구나 서버 컴포넌트가 될 수 있다.
오히려, 클라이언트 컴포넌트가 'use client' 지시어를 넣어 클라이언트 컴포넌트임을 알려야 한다.

자, 뭐 됐고, 만약 수정이 일어났다, 예를 들면, 로그인 및 로그아웃에 대한 사용자 정보 처리라든가,
게시판에 글을 쓴 뒤 목록으로 돌아가면서 최신 목록으로 새로고침을 하려면 어떻게 해야 하느냐,

Next.js 는 크게 3가지 캐시 새로고침 방법을 지원한다.

  • revalidatePath(path) - 서버 전용, 특정 라우팅 경로 및 하위 경로 내 캐시를 무효화 한다.
  • revalidateTag(...tags) - 서버 전용, 서버단 내에 사용한 fetch 함수 옵션으로 사용한 태그에 해당하는 캐시를 무효화 한다.
  • useRouter().refresh() - 클라이언트 전용 훅, 현재 페이지의 캐시를 무시하고 다시 데이터를 불러오도록 유도한다.

여기서 내가 주로 쓰는 건 아무래도 3번이고, 로그인 로그아웃 등 광역으로 영향받을 시에 1번 방법을 주로 쓴다.
현재 버전 기준으로, 캐시 때문에 데이터가 똑같이 나온다는 등으로 콤플레인이나 오류 보고를 받은 적은 없다.
음... 납품을 내가 10월 4일날 했으니 오픈일도 10월 4일이고, 지금 한 9일 됐네.

그래, 캐시 관리 신경 써야 하는 게 불편하지만, 그 불편함만 감내하면, 그 혜택이 꽤 크다.
react-query 같은 거대한 상태관리 프레임워크를 쓸 필요가 없으니 말이지.

Tailwind를 쓴 이유.

간단하다. 서버 컴포넌트를 위해서다. 내가 익숙해서기도 하고 말이지.

너네들이 주로 쓰는 모듈형 스타일링 라이브러리들 근황 알아보도록 할까?

  • Emotion: #2928 - 지원은 가능하나 클라이언트만 한정.
  • style-components: #927 - 마찬가지.

결론: CSS-in-JS: Next.js
대부분의 모듈형 스타일링 라이브러리들은 클라이언트 컴포넌트에만 적용 가능하다.
공식에서 말하길 서버 컴포넌트의 스타일링을 원하면, 리액트가 자체 지원하는 CSS-in-JS 모듈 쓰든가, CSS 파일을 별도로 관리하거나, 아니면 tailwind 쓰든가.

Emotion 사용자에게는 그나마 좋은 소식을 기대할 수 있는데, Next.js 팀과 협력해서 서버단 컴포넌트 지원을 진행 중이라고 하니, 기다려 보거나 pages 라우터를 쓰면 되겠다.

잠깐, 데이터 변경은?

현재 Next.js 에서 공식 지원 중이지만 알파 단계이며, 곧 지원 예정인 서버 액션은, 당연히 불안정한 상황에서 무작정 서비스할 프로젝트에 적용하기 곤란해지니 사용하지 않았다. 내가 이거 때문에 잠깐 SvelteKit 를 쓸까 잠깐 좀 깊은 고민에 빠졌었는데, 후술할 이유로 그냥 Next.js 그것도 앱 라우터로 강행했다. 그래서 결론이 뭐냐, 그냥 클라이언트 DOM 이벤트에 fetch 함수로 퉁쳤다.

이때, 주의사항이 있는데, 나처럼 이벤트 함수를 절대 async 함수로 만들지 않길 권한다. 크롬 오류 드럽게 쏟아진다. 애초에 권장하지도 않고, 절대 안좋은 방법이다.
왜냐면, async 함수를 통해 return 한 것도 어자피 Promise 라 씹는데, 심지어 본문처럼 비동기를 통해 호출한 event.preventDefault() 같은 이벤트 처리 함수도 씹힌다. 이건 이벤트 함수 자체가 fetch 같이 특별히 비동기 이벤트를 지원하지 않는 이상, 이벤트 호출 스택에서만 이벤트 처리가 동작하도록 구성했기 때문이다. 즉, 레거시에서 시작된 한계인 것이다.

그밖에, 별다른 라이브러리 없이 위와 같이 구현했다. 물론 IE 호환성을 원한다면 Axios 쓰면 된다.
더 좋은 방법은, API를 기반으로 한 SDK를 만들거나 생성 툴 등을 사용하는 것이다. 근데 시간이 넉넉치 못해 쌩으로 썼다.
너희들은 그러지 마라.

그래, 일부 니네들이 말하는 것처럼 땔감 대가리의 한계라 생각한다면 그리 생각하라. 네가 한번 1주일만에 DB, 사이트, 회원관리, 파트너, 권한, 코드 등등 만들어봐야 내 고충을 이해하려나...

결론

그래, 그렇게 총 2주에 걸쳐 개발한 끝에, 오픈 했고, 회원 수도 생기고, 뭐 그러하다고 한다.
운영하면서 생기는 사소한 오류는 뭐... 범위 크지 않으면 서비스 차원으로 수정해 주고 있다.

그래. 지금 이 이미지가 실제 사이트다. 내가 놋북 폰 목업에다가 웹페이지 스샷 박아놓았다.
살제로 돌아가는 사이트 보고 싶으면 알아서 구글이나 네이버 검색 해서 들어가 봐라. 귀찮다.

...
실제 이 사이트 납품 전에 쇼케이스로 비슷한 사이트를 만든 적이 있었다. 심지어 주제도 비슷했었다.
그걸 Next.js 앱 라우터로 개발했고, 데이터까지 구성은 하지 못했지만, 그럴싸하게 개발했었다.
비록 협상에 실패해서 버려질 뻔 한 템플릿이 이렇게 쓰일 줄은 몰랐지.
버려질 뻔한 템플릿 개발하면서 긍정적으로 검토하고 컨펌해준 선배님께 고맙다는 인사 한번 해야겠다.

이게 내 마지막 프로젝트가 아니길

무슨 소리냐고?

다음주부터 나는 레거시 프로젝트에 투입한다. 불황에다가 곧 겨울이니 일단 몸을 추스리기 위해서다.
심지어 인터넷도 안되는 곳이니, 최신 기술동향 정보를 보고 싶으면 밤에 집에서 확인하는 수밖에 없겠지.
다시 나는 SI의 국룰인 자바와 어느 RIA 플랫폼이 깃든 프로젝트에 갑질당하러 간다.
그래. 이게 땔감 운명이고, 이게 땔감 국룰이지. 자바 두명 타요.

다시 봄이 되면, 지금 내 이 경험도 봄날이 다시 오길 바란다.
물론 너희들도 내년에 다시 봄날에 함께하자.

물론 AI 공부 중인 건 계속 할거니까 나도 화성 가야지. (경기도) 화성 (S 대기업) 갈끄니께~

끗.

profile
지옥에서 온 개발자

5개의 댓글

comment-user-thumbnail
2023년 11월 4일

캬아. React-query, GraphQL, Axios... 대한민국 Next.js 의 국물이 다 들어있다. 시원~하지?
근데 얘도 전역상태관리 따로 없네? 얘도 뭘 좀 아는군 (흐뭇)

sangte가 전역상태관리 라이브러리에요 아저씨.
아저씨처럼 꽉막힌 사람이랑은 절대 같이 일하고 싶지 않네요. 프리시니 절대 만날 일은 없을테니 다행입니다.

3개의 답글
comment-user-thumbnail
2023년 11월 18일

논리와 주장은 모두 틀렸고 근거가 절대로 없는 자신이 모든 개발자의 진리인듯한 가장 시건방지고 여기 불법 도박 스팸글보다 더 악질인 이새끼 글이 홈에 나타나는 행위야 말로 스팸을 방치하는 것보다 더 최악이며 벨로그는 불법 도박 스팸글과 함께 이새끼 글은 노출하지 않아야 개발자들이 양질의 지식과 정보를 공유하는 최고의 길이라 한다. 따라서 이 글을 본 개발자들이 있다면 바로 눈을 씻고 이 글을 잊고, 이새끼 아이디와 동일한 깃헙 및 여러 동일한 ‘컴포지트’ 닉네임을 거르고 봐야 올바른 개발자 생활을 영위하는 것이다.
양욱진, 땔감 프리랜서, 경력 뻥튀기, 공문서 위조, 사기, 그리고 지식은 커녕 신념도 없는 코더. 이런 새끼한테 개발을 맡기는 고객이나 보도방, 개발사들은 당신이 누구에게 회사의 앞날을 밑기는지 손을 얹고 다시한번 생각해보기 바란다.

답글 달기