📝 장장 9월 ~ 11월 중순 까지 4명의 팀원들이 매일 최소 3~4시간 씩 쏟아부으며 기획 및 디자인한 애증의(?) DevRace! 🚘
(기능 구현은 11월 중순이 된 이제야 시작하는게 함정...)
백엔드와의 협업은 처음이기에 이번 프로젝트의 기획 과정을 간략하게나마 정리해보고자 한다.
백엔드 1명 (이후 1명 충원)
(1명 충원했다가 탈주하고, 이후 새로 충원된 1명...ㅠㅠ)
프론트엔드 3명
사실 프로젝트를 시작하던 9월 초, 처음에는 해커톤을 참여해보려 했었다.
내일배움캠프 측에서 기획 단계에서의 지원은 물론 예선 통과 시 튜터님 지원도 해준다 하고, 상금도 추가로 준다 하니 안 할 이유가 없었다.
그런데 막상 시작해보니 우리가 생각했던 방향과는 많이 달랐다.
그냥 자유 주제 선택해서 우리 하고 싶은 프로젝트 하면서 해커톤은 그냥 우리 프로젝트에 얹어지는(?) 느낌을 생각했는데...
알고 보니 해커톤에 맞춰야 하는 내용이 너무 많았다.
AI도 반드시 접목해야했고, 사회 문제를 해결하는 주제를 선정해서 기획해야 수상 확률이 올라간다고 했다.
그래서 사회 문제와 AI기술이 포함된 기획을 생각하다보니 우리가 생각한 팀프로젝트와는 점점 멀어졌고..... 우리 팀 담당 매니저님은 계속 기획안 제출을 재촉하시고....
그래서 결국 해커톤은 다음 기회에 참여하기로 하고, 우리가 진짜 하고 싶은 주제와 기능을 가지고 프로젝트를 하자고 결론을 내렸다.
9월 달은 평일 매일 1시간~최대 3시간 정도 회의를 진행했다.
추석 연휴가 길어 회의를 많이 하지 못했음에도 불구하고 지금 생각해보면 꽤 많은 결정들을 했던 것 같다.
아이디어 수집 과정에서 가장 도움됐던 방법은 각자 요즘 제일 관심 있는 것이 무엇있지 생각해보는 것이었다.
'나는 요즘 무엇에 가장 관심이 있더라?' 생각하면서 적다보니 '아, 이런게 필요했지?' 하며 프로젝트 아이디어가 계속 생각났다.
이 외에도 각자 어떤 기능을 가장 구현해보고 싶은지 생각하는 것도 도움되었다.
주제는 4명이 투표로 선정했고, 주제를 정한 후에는 어떤 페이지들이 필요할지 생각하며 디자인은 상관없이 피그마에 페이지들을 만들어보는 과정을 거쳤다.
이 과정에서 우리가 함께 선정한 주제일 지라도 각자 다른 생각을 가지고 있었던 부분들도 캐치하고, 대략적인 페이지 구성과 기능들을 정리할 수 있었다.
프론트끼리 프로젝트를 할 때는 BaaS를 썼기 때문에 주어진 api를 활용하다 보니 비효율적인 통신 혹은 불필요한 데이터까지 함께 가져와 후처리를 하는 등 아쉬울 때가 종종 있었다.
하지만 백엔드가 있으니 확실히 달랐다.
필요한 데이터만 가져와서 쓸 수 있는 것이 크게 매력적으로 다가왔다. 그리고 프로젝트 시작 전에 백엔드와 기능 및 데이터에 대해 최대한 구체적으로 이야기를 나누고 데이터에 대해 최대한 확실하게 논의해야 한다는 것을 배웠다.
다만, 데이터에 대해 최대한 구체적으로 이야기를 먼저 나누다 보니 기획도 함께 바뀌기도 하고, 데이터를 확실히 하면서 넘어가다보니 시간이 많이 지체됐다.
하지만 이 과정도 백엔드와 협업하면 반드시 필요한 시간이기에 큰 배움의 시간이었다.
10월 달 부터는 다들 코딩으로 들어가고 싶은 마음 + 디자인 지옥(?)에서 벗어나고 싶은 마음에 평일 매일 3시간 이상 회의했다.
그럼에도 11월까지 디자인 작업이 이어졌다...😂 디자이너... 소중해...
10월 달 부터는 프론트끼리 주로 회의를 했다.
데이터를 정리하면서 기획이 수정되기도 하고, 우리끼리 기획을 수정하다가 데이터가 변경되어 백엔드 분을 호출하기도 하고, 데이터 정리와 기획 수정이 함께 이루어졌다.
그 과정에서 각 페이지에서 대략적으로 넣어놓았던 기능에 대해 구체적으로 이야기 나누기도 하고, 기능에 대한 논의가 첨예하게 이어지면서 기획 단계가 계속 지체되었다.
(여기서 이 기능을 쓰는 것이 맞을지, 다른 기능으로 바꿀지... 예를 들면 가져온 게시글 목록을 무한 스크롤로 보여줄지, 페이지 네이션을 이용할지 등 이런 논의가 계속 이어졌다.)
10/18 부터는 브랜드 컬러에 대해 논의하기 시작하면서 디자인 작업을 본격적으로 시작했다.
디자인... 프론트도 힘들어하는 디자인... 웬만하면 디자이너 있는게 정신건강에 좋을듯
11/5 드디어... 길고 길었던 디자인 작업이 끝났다. 엄청 길었다고 생각했는데 막상 날짜로 세어보니 12일 밖에 안되네...ㅎㅎ.....
기술적 의사결정, git 컨벤션, 코드 컨벤션을 함께 정하고 github에 이슈 탬플릿, PR 탬플릿도 정했다. 드디어 디자인이 끝나고 기술적인 이야기를 하니 회의 분위기가 좋아진게 웃음벨이었다.🤣
다들 하고 싶은 기능들이 많고 이력서 업데이트에 열정이 있다 보니 역할 분담도 꽤 치열했다. 각자 맡고 싶은 기능들 이야기 한 후 겹치는 기능은 원판 돌리기로 정했고, 이후 페이지를 기준으로도 한 번 더 치열한 논의와 역할 분담을 했다.
프로젝트 초기 세팅은 내가 모르는게 많아 나머지 프론트 팀원 2명에게 많이 배웠다.
1) metadata
메타데이터는 그냥 next.js root layout에 하나만 작성하면 끝이라고 생각했는데, 그렇게 하면 모든 페이지가 같은 메타데이터 정보를 갖게 된다. 그래서 SEO 최적화를 위해서는 페이지 별로 메타데이터가 달라야 하는 경우는 다르게 지정해주기로 했다.
// 📁 app > metadata.ts
import type { Metadata } from "next";
// 예시 메타데이터
export const testMetadata: Metadata = {
title: "testPage",
description: "this is testPage",
};
// 📁 app > test > page.tsx
import React from "react";
import { testMetadata } from "../metadata";
import { Metadata } from "next";
// 메타데이터 가져오기
// (이름은 metadata를 사용해야 next.js가 인식할 수 있다.)
export const metadata: Metadata = testMetadata;
const testPage = () => {
return <div>testPage</div>;
};
export default testPage;
2) global css
/* css 박스 확인할 때 padding, margin값 자동으로 들어가지 않게 막아주는 설정 */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* a태그 css 초기 설정 */
a {
text-decoration: none;
color: inherit;
}
:root {
/* 메인 폰트 컬러 */
--main-font-color: #fff;
/* 브랜드 컬러 */
--main-point-color: #1dd0eb;
--sub-point-color: #ff6000;
--main-color-1: #121212;
--main-color-2: #1e1f21;
--sub-color: #34343c;
}
/* 사용 예시 */
body {
background-color: var(--main-color-1);
color: var(--main-font-color);
}
3) 기본 폰트 설정 - pretendard
// 📁 app / layout.tsx
const pretendard = localFont({
src: "./fonts/Pretendard.woff2",
variable: "--font-pretendard",
weight: "45 920",
});
4) eslint, prettier 설정
이건 하자고 해서 하긴 했지만 솔직히 뭐한건지 아직도 모름...
프로젝트 하다보면 알게 되겠지 😂
( 참고 : https://cpdev.tistory.com/232 )
5) header, footer, 내용물 정렬
flex를 body에 주냐 마냐, header와 footer를 포함해서 div로 wrap을 한 번 하냐 마냐 등 정렬 때문에 또 첨예한 대립...
결론은
// 📁 app > layout.tsx
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="ko">
<Providers>
<body className={`${pretendard.variable}`}>
<Header />
<main>{children}</main>
<Footer />
</body>
</Providers>
</html>
);
}
6) query key 상수화
// 📁 src > queries > queryKeys > queryKeys.ts
export const TEST_QUERY_KEY = {
TEST_LIST: "testList",
TEST_CONTENTS: "testContents",
};
// 📁 app > test > page.tsx
import React from "react";
import { TEST_QUERY_KEY } from "@/queryKeys/queryKeys";
const testPage = () => {
// queryKey 가져오기 예시
const testQueryKey = TEST_QUERY_KEY.TEST_CONTENTS;
return <div>testPage</div>;
};
export default testPage;