프로젝트 2주차는 퍼블리싱 기간이었다. 각자 담당 컴포넌트/페이지를 나누어 퍼블리싱 하고, 금요일에 오프라인 미팅을 하면서 진행상황을 공유했다.
금요일 미팅 전 새벽에 코드 일부를 수정하면서 커밋을 날리다가 뭔가 이상한 걸 발견했다.
feature/ 브랜치에서 작업을 하고 있는데, git graph를 보니 develop 브랜치에서 커밋이 뻗어나가고 있었다.
진짜 개깜짝놀라고 이게 무슨일인지 브랜치를 확인해봐도 분명히 feature 브랜치가 맞긴하고 근데 그래프는 와이라노 싶고 아무리 고민해봐도 명확한 답을 찾을 수 없었다.
머지에서 꼬였구나 싶어서 revert 해봤지만 그와중에 기준을 잘못잡아서 충돌이 발생했고, 어쩔수 없이 develop에서 충돌 수정 커밋까지 날리고 작업을 종료했다.
진짜 이쁜 그래프였는데 나 때문에 망친 것 같고 너무 죄스러워서 회의 시작 전에 자수를 했다. 다행히 큰 이슈 없으면 괜찮다고 말해주셔서 마음이 놓였다.
그동안 GitHub Desktop을 사용했기 때문에 그래프를 볼 일이 없었는데, 이번에 git graph를 통해 로그를 시각화해서 보니 작업 상황을 한눈에 파악할 수 있어서 굉장히 편했다. 하지만 이번 실수를 통해 그래프를 보는 것과 로그를 확인하는 것에 더 익숙해질 필요성을 느꼈다.
이번에 발생한 브랜치 오염의 원인이 뭘지 계속 고민해보았다. feature/ 브랜치에서 작업 중 develop 브랜치의 커밋이 포함된 것을 보면, 아마도 merge에서 문제가 발생했을 가능성이 크다고 생각해서 나의 행적을 계속해서 되짚어 보았다. 평소와 다름없이 feature/에서 작업하고 커밋한 후 develop에 머지하는 과정을 반복했으니 그 이전에 문제가 생겼을 것이라 판단했다.
조금 더 고민해 보니, develop 브랜치를 내가 사용 중인 feature/ 브랜치로 머지했던 것이 원인인 것 같았다. 이 때 브랜치 오염이 발생했고, 이후 커밋에 문제가 생긴 것으로 추정된다.
- develop을 feature에 머지한 후 feature 브랜치에서 작업 중이라고 생각했지만, 실질적으로 HEAD가 develop 브랜치를 가리키고 있었을 가능성. 이 경우, 커밋들이 feature가 아닌 develop에 쌓이게 되어, 예상치 못한 그래프가 만들어진다.
- develop을 feature에 머지하는 과정에서 머지 커밋이 정상적으로 생성되지 않았거나, 병합 후에 바로 develop 브랜치로 이동하여 커밋해서 feature에 히스토리가 남지 않았을 경우
- (gpt) feature 브랜치를 develop 브랜치에 머지할 때, --no-ff(fast-forward 병합 비활성화) 옵션을 사용하지 않았다면, Git은 머지를 직선으로 처리하여 feature 브랜치의 커밋들이 develop 브랜치에 병합되었을 때 단일한 선형 히스토리로 이어질 수 있습니다. 이 경우에도 feature 브랜치의 그래프가 따로 그려지지 않고, develop 브랜치에서 일직선으로 이어지는 것처럼 보일 수 있습니다.
사용한 브랜치가 남아있거나, Git 로그를 자세히 분석할 수 있으면 원인을 알 수 있을텐데 아직 그정도로 로그를 파악할 수 없어서 원인을 알 수 없게 되었다. Git이 진짜 파면팔수록 어렵고 헷갈리는 개념이 많은 것 같다.
이번 경험을 계기로 Git의 다양한 명령어(merge, rebase, reset, revert, cherry-pick 등)와 그 사용 방법을 좀 더 깊이 있게 학습해 보는 것이 좋겠다는 생각이 들었다. 공부를 해야 비슷한 상황에서 더 효율적으로 대처할 수 있을 것 같다.
민폐를 끼치지 않는 팀원이 되자
담당 파트 작업을 하면서 컴포넌트 분리에 대한 고민을 많이 하였다. 스프린트1에서 내가 담당한 페이지는 한 페이지인데 이 페이지 하나를 만들기 위해 6개 정도의 파일을 만들었기 때문
- ColorCircle.tsx : 색상 원 하나를 구성하는 컴포넌트
- SelectColor.tsx: 정해진 색상 배열에 따라 ColorCirlce을 생성하여 색상 선택을 지원하는 컴포넌트
- SelectBgImage.tsx: 이미지 Circle을 생성하여 배경 선택을 지원하는 컴포넌트
- SkinOption: 스킨 모양 선택지 하나를 구성하는 컴포넌트
- SelectSkin: 스킨 배열 정보에 따라 스킨 선택지를 생성하는 컴포넌트
- SelectBgOption: 현재 페이지에서 표시할 배경 선택지가 SelectColor인지 SelectBgImage인지 결정하는 컴포넌트
각자 컴포넌트만의 확실한 역할이 있고 컴포넌트 분리하는 것이 유지보수 등의 장점이 있다지만 그래도 너무 과하게 분리한 것이 아닌가 싶어 팀원 중 실력자 분께 여쭤보았다.
팀원 분의 답변을 정리해보자면
내가 컴포넌트를 분리한 이유는 코드가 너무 복잡해지는게 싫어서였다. 너무 긴 코드는 읽기도 불편하고, 또 재사용 하기에도 편하기 때문에 최대한 분리하면서 작업을 하였는데, 팀원분의 말을 들어보니 리렌더링 관리 관점에서도 컴포넌트 분리를 고려할 수 있겠구나 생각이 들었다. 이렇게 한 수 배우고..앞으로는 렌더링 등 다양한 관점에서 고민하며 코드를 작성해봐야겠다.
컴포넌트를 구현하다보니, 생각보다 use client
를 많이 쓰게 되었다. Next.js를 쓰는 이유가 SSR의 장점을 가져오기 위해서인데, 클라이언트 컴포넌트를 많이 쓰면 무슨 의미가 있을까 생각이 들었다.
서버 컴포넌트
- 서버에서 렌더링
- 데이터베이스 쿼리나 API 호출과 같은 데이터 페칭 작업에 적합
- 클라이언트 사이드 자바스크립트가 없어 번들 크기가 작아지고 로드 시간이 빨라짐
- SEO에 유리
클라이언트 컴포넌트
- 클라이언트에서 렌더링되어 사용자와의 상호작용 처리
- 폼, 버튼, 동적 콘텐츠 업데이트와 같은 사용자 상호작용이 필요한 부분에 적합
- 상태 관리
- 상호작용이 중요한 어플리케이션에 유리
폼이 있거나, 상태관리가 필요한 컴포넌트에서는 use client
를 사용해야 한다. 하지만 클라이언트 컴포넌트를 사용하면 기본적으로 Next.js를 사용하는 이점(초기 로드 시간, SEO, 번들 크기 등)이 업식 때문에 이걸 최소화 하는 방법이 필요하다고 느꼈다.
팀원분께서도 같은 생각이셨는지 이 부분을 지적하셨고, 꼭 필요한 컴포넌트가 아니면 최대한 서버 컴포넌트를 유지하기로 했다.
아직은 리액트를 사용한 방식이 익숙하고, 상태 관리도 많은 컴포넌트에서 사용하기 때문에 많은 컴포넌트를 use client
로 사용하고 있다. 그래도 서버 컴포넌트를 최대한 활용하기 위해서 방법을 고민해보았다.
지금은 클라이언트 컴포넌트 사용이 필요할 경우 해당 코드를 별도 컴포넌트로 분리하여 use client
로 사용하고, 상위 컴포넌트는 서버 컴포넌트를 유지하는 방법으로 코드를 작성하고 있다. Next.js에서 제공하는 함수에 익숙해지면 더 효율적으로 서버 컴포넌트를 사용할 수 있을 것 같다. 공식 문서를 열심히 읽기..
간단하게 DB 스키마를 정의하고, 사용할 데이터베이스를 결정했다.
사전직무교육 중 MogoDB를 사용하는 방법을 배웠기 때문에 처음에는 MongoDB를 사용하는 방향으로 결정되는 분위기였다. 하지만 vercel에서 postgresql 관련 기능을 지원하기도 하고, 두 데이터베이스 간 장단점을 알아볼수록 고민이 길어졌다.
MongoDB
- 유연한 스키마: 문서 지향 데이터베이스로, JSON과 유사한 BSON 형식을 사용하여 데이터를 저장한다. 스키마가 유연하여 데이터 구조가 자주 변경되는 어플리케이션에 적합
- 수평 확장성: MongoDB는 수평 확장이 용이하여 대규모 데이터를 처리하는 데 유리
- 빠른 쓰기 성능: 데이터가 비정규화 되어 있어 쓰기 작업이 빠름
- 인증 통합: MongoDB Atlals는 다양한 인증 매커니즘을 지원하며, Next.js와의 통합이 가능
Supabase(postresql)
- 데이터 무결성: Supabase는 PostreSQL을 기반으로 ACID 속성을 준수하며, 데이터 무결성과 일관성을 보장
- 복잡한 쿼리: 복잡한 쿼리와 트랜잭션을 지원하며, 데이터베이스 내에서 다양한 연산을 수행
- 실시간 기능: 실시간 업데이트와 RESTful API를 제공하여 개발자 경험 향상
- 인증 통합: Supabase Auth는 Next.js와 쉽게 통합할 수 있으며, 세션 관리와 사용자 인증을 간편하게 설정 가능
얘기를 하던 중 firebase 얘기가 나왔는데, 여기서 말을 이어가다보니 supabase가 언급되었다. supabase가 postgresql 기반 데이터베이스이고, 요즘 firebase의 대체로 인기가 급상승하고 있는만큼 사용해보면 좋을 것 같기 때문에, supabase를 사용하기로 결정했다!
팀원분이 zustand에 devtools를 적용하는 과정에서 타입 오류가 난다고 하셨다.
저기에 맞는 타입을 찾기 위해 3명이서 한참을 고민했다.
다른 팀원 분이 타입 추론을 통해 타입을 찾아내셨는데 너무 기괴하다.(맞는 타입인지는 모르겠지만)
저 코드를 사용했을 때도 실행이 안되는 오류가 발생해서 결국 any
로 처리하였는데, 이 상황을 겪으면서 타입스크립트의 any
사용에 대해서 좀 진지하게 고민해보게 되었다. 관련해서는 다음에 정리해보도록 하겟음.
지금까지 진행한 작업에 대한 멘토링을 받았다.
멘토님께서 퍼블리싱 코드는 잘 작성했고, 다음 목요일부터 데이터 바인딩을 시작해도 될 것 같다고 말씀하셨다. 코드 관련 지적을 해주실 줄 알았는데, 별다른 언급은 없고 그냥 깔끔하게 잘 짰다고 해주셔서 기분이 좋기도 하고..진짜 잘 짠걸까 싶기도 하고. 🧐
코드보다는 기능 구현 방식에 대한 조언을 많이 해주셨다.
1. 이미지 import 시에는 절대 경로를 사용
2. 프로필 이미지 업로드 개수에 제한을 둘 경우, max에 달할 경우 추가 버튼을 비활성화하는 것이 더 좋은 UI 플로우이다.
다음에는 코드랑 프론트엔드 관련 질문할거 열심히 준비해가야지
스프린트2에서는 퍼블리싱 담당 페이지의 서버 연동과, 랜딩 페이지 작업을 담당하게 되었다. 애니메이션을 사용한 랜딩페이지를 한 번 구현해보고 싶어서 지원했다.
회원가입/로그인도 한 번 맡아보고 싶긴 했는데, 사전직무교육 실습 당시 nextAuth에서 대차게 버그가 발생했던 기억이 나 망설여졌고 지원을 못했다..
팀원 중에 경험 많으신 분이 계시니 코드 관련해서 궁금한점도 물어보고, 자잘한 개발 팁을 배울 수 있어서 너무 만족스러운 팀플이다. 생각치도 못한 supabase도 사용해보게 되었고..앞으로 5주 남았는데 최대한 많은 것을 배우고 좋은 결과물 낼 수 있도록 열심히 해야겟따.
ㄷㄷㄷㄷ 다경황 폼 미쳤따