[내배캠 3기] 팀 프로젝트 Newsfeed - 기획 & 초기 설정
TIL 23. 11. 21
▶ 들어가며
새로운 팀 과제가 주어졌다. “리액트를 활용한 뉴스피드 팀 프로젝트”
뉴스피드란 블로그, 커뮤니티, SNS와 같이 내 게시물을 포함한 모든 게시물을 볼 수 있는 공간을 의미한다. 명확한 주제가 정해져 있지 않고 서비스를 기획하고 개발해야 하는 프로젝트였다.
처음에는 막막했지만 회의를 거듭할수록 주제가 결정되고 화면 설계가 이루어지고 기능이 분류되어 업무 분담까지 마쳤다. 프로젝트 초기 설정까지 마치고 나니 하루가 마무리 되었다.
▶ 프로젝트명: 내.베.프 (My Best Project)
-
주제: 내일배움캠프 수강생의 프로젝트 공유 커뮤니티
-
소개: 과제를 수행한 결과물을 커뮤니티에 자랑하고 공유하기!
🚩 프로젝트 기간
23. 11. 22 - 23. 11. 27
👥 팀 소개
- 팀명: 三의 맹세
- 팀원 준혁(팀장), 혜원, 창성, 영륜
💡 필수 구현 기능
Auth
로그인, 로그아웃 기능 구현 / 로그인 상태 관리
- firebase 연동
- Authentication API 이용
- 로그인 (모달창)
- 로그인 Form UI
- 아이디(이메일), 패스워드 로그인
- 소셜 로그인 (구글, 깃헙)
- 회원가입 (모달창)
- 회원가입 Form UI
Layout
레이아웃 구성
- Header
- 로고
- 네비게이션
- 로그인 버튼, 유저 아이콘
- 유저 아이콘 클릭시 드롭다운 - 로그아웃, 마이페이지
- 로그아웃 시 로그인 버튼, 로그인 시 유저 아이콘 표시
- Main
- Footer
메인 페이지
메인 페이지 UI, 게시글/유저 컴포넌트 개발
- 배너
- 과제 게시글 랜덤으로 표시
- 클릭 시 상세 페이지 이동
- 썸네일, 제목, 내용, 유저 정보
- 과제 더보기
- 클릭 시 과제 목록 페이지로 이동
과제 목록 페이지
- 목차
- 주제별 과제 분류
- 과제 게시글
- 유저 정보
- 제목, 내용, 썸네일
- 조회수, 좋아요, 댓글 목록
- 클릭 시 상세 페이지로 이동
과제 게시글 작성 페이지
- 유저 정보
- 제목, 카테고리, 내용, 썸네일, URL (에디터)
- 코드 블록 사용 가능
- 게시글 수정 시 내용 변경하여 호환되도록 구현
과제 상세 페이지
- 유저 정보
- 썸네일, 제목, 내용, URL
- 좋아요, 조회수
- 수정, 삭제
- 수정 버튼 클릭 시 과제 게시글 작성 페이지로 이동
- 삭제 경고
- 자신이 게시한 글만 가능
- 댓글
- CRUD
- 자신이 작성한 댓글만 가능
- 좋아요, 댓글 수
- 목록으로 이동 버튼
마이 페이지
- 내 게시물 보기
- 프로필 수정
기타
- 배포
- Vercel 이용
- 배포 브랜치는 main
- Git 최대한 활용하기
- PR
- Branch 전략
- 코드 리뷰
☀ 역할 분담
- 준혁: 레이아웃, 메인 페이지
- 혜원: 과제 상세 페이지
- 창성: Auth, 프로젝트 초기 설정
- 영륜: 과제 목록 페이지
🔲화면 설계
▶ 프로젝트 초기 설정
💻 개발 환경
- IDE: Visual Studio Code
- OS: windows
- Package Manager: Yarn Classic (v1.22.19)
- React boilerplate: create-react-app
📌 사용 기술
- React - 사용자와 상호작용할 수 있는 UI를 효율적으로 구현
- Styled-components - 자바스크립트로 스타일 관리. 재사용이 쉬운 컴포넌트를 만들고 동적 스타일링 용이
- Redux - 전역 상태 관리 도구
- React-router-dom - 클라이언트 사이드 라우팅. URL에 맞는 컴포넌트 렌더링
⚒ 프로젝트 생성 ➡ 불필요한 파일 삭제
- 프로젝트 생성 -
$ yarn create react-app my-best-project
- 불필요한 파일 삭제 -
index.css, App.css, App.test.js, logo.svg, reportWebVitals.js, setupTests.js
📦 라이브러리 설치
- prettier: 코드 포맷팅 도구
- eslint: 자바스크립트 문법 유효성 검사 도구
- eslint-config-prettier: prettier와 eslint 충돌하는 옵션 off
$ yarn add -D prettier eslint eslint-config-prettier
- styled-components: CSS-in-JS 라이브러리
- react-icons: React 프로젝트에서 사용 가능한 아이콘
- react-router-dom: React 페이지 이동 처리
- firebase: firebase 사용
- redux: 상태 관리 라이브러리
- react-redux: react 컴포넌트 바인딩 라이브러리
$ yarn add styled-components
$ yarn add react-icons
$ yarn add redux react-redux
$ yarn add firebase
$ yarn add react-router-dom
⚙ 프로젝트 초기 설정
-
절대경로 설정
jsconfig.json
파일 생성
{ "compilerOptions": { "baseUrl": "src" }, "include": ["src"] }
-
.gitignore
수정.gitngnore
: 프로젝트에 원하지 않는 백업 파일이나 로그파일 혹은 컴파일 된 파일들을 Git에서 제외할 수 있는 설정 파일- CRA로 프로젝트 생성하면 자동으로 생성되지만 VSCode나 Yarn의 불필요한 파일을 포함해 환경변수
.env
파일을 github에 업로드 하지 않도록 제외 - gitignore.io 에서 Visual Studio Code와 Yarn을 생성해서
.gitignore
파일에 추가
-
Prettier 설정 파일
.prettierrc
-
코드 스타일을 일관성 있게 작성하기 위해
-
VSCode Extension ‘Prettier’ 설치
// .prettierrc 프로젝트 루트 폴더에 생성 { "tabWidth": 2, "semi": true, "singleQuote": true, "trailingComma": "all", "printWidth": 80, "useTabs": false, "endOfLine": "crlf" }
-
-
Eslint 설정 파일
.eslintrc
-
문법적인 오류를 방지하고 다양한 방식으로 구현할 수 있는 코드 방식을 일관성 있게 구현하기 위해
-
VSCode Extension ‘Eslint’ 설치
// .eslintrc 프로젝트 루트 폴더에 생성 { "parserOptions": { "ecmaVersion": 2021, "sourceType": "module", "ecmaFeatures": { "jsx": true } }, "extends": ["react-app", "plugin:react/recommended"], "rules": { "react/prop-types": "off" } }
-
-
Reactjs code snippets
- React 관련 템플릿을 단축키로 작성
- VSCode Extension ‘Reactjs code snippets’ 설치
- 컴포넌트 파일
.jsx
생성할 때 스니펫을 사용하여 컴포넌트 선언 방법 통일 -rfc
🎨 스타일 초기화 및 폰트 적용
웹 폰트는 CDN 링크 사용하여 폰트 정의 후 적용. 스타일 초기화는 styled-componets가 제공하는 createGlobalStyle()
을 이용해 전역 스타일링.
import { createGlobalStyle } from 'styled-components';
const GlobalStyles = createGlobalStyle`
@font-face{
font-family: 'DNFBitBitv2';
font-style: normal;
font-weight: 400;
src: url('//cdn.df.nexon.com/img/common/font/DNFBitBitv2.otf') format('opentype')
}
@font-face {
font-family: 'ChosunGu';
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_20-04@1.0/ChosunGu.woff') format('woff');
font-weight: normal;
font-style: normal;
}
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
height: 100vh;
font-family: 'ChosunGu';
}
ol, ul, li {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
a {
text-decoration: none;
color: inherit;
}
input, button, textarea{
border: none;
background: inherit;
outline: none;
}
* {
box-sizing: border-box;
font-family: 'ChosunGu';
}
`;
export default GlobalStyles;
📰 라우팅
URL에 맞는 컴포넌트 렌더링
/
: 메인 페이지/boards
: 과제 목록 페이지/boards/:id
: 과제 상세 페이지/boards/new
: 게시글 작성 페이지/mypage
: 마이 페이지
// Router.js
import React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Layout from 'components/Layout/Layout';
import { AllBoard, BoardDetail, Home, MyPage, NewBoard } from 'pages';
export default function Router() {
return (
<BrowserRouter>
<Layout>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/boards" element={<AllBoard />} />
<Route path="/boards/:id" element={<BoardDetail />} />
<Route path="/boards/new" element={<NewBoard />} />
<Route path="/mypage" element={<MyPage />} />
</Routes>
</Layout>
</BrowserRouter>
);
}
pages 폴더에서 import 할 때 여러 라인이 생기는 것이 보기에 좋지 않아서 index.js로 컴포넌트 파일 관리
// pages/index.js
import Home from './Home';
import AllBoard from './AllBoard';
import BoardDetail from './BoardDetail';
import MyPage from './MyPage';
import NewBoard from './NewBoard';
export { Home, AllBoard, BoardDetail, NewBoard, MyPage };
📂 디렉토리 구조
📦my-best-project
┣ 📂public
┣ 📂src
┃ ┣ 📂assets
┃ ┣ 📂constants
┃ ┣ 📂components
┃ ┃ ┣ 📂component1
┃ ┃ ┃ ┣📜component1.jsx
┃ ┃ ┃ ┗📜styles.js
┃ ┃ ┣ 📂component2
┃ ┃ ┃ ┣📜component2.jsx
┃ ┃ ┃ ┗📜styles.js
┃ ┣ 📂hooks
┃ ┣ 📂pages
┃ ┣ 📂utils
┃ ┣ 📂redux
┃ ┃ ┣ 📂config
┃ ┃ ┗ 📂modules
┃ ┣ 📜App.jsx
┃ ┗ 📜index.js
┣ 📜.eslintrc
┣ 📜.gitignore
┣ 📜.prettierrc
┣ 📜jsconfig.json
┣ 📜package.json
┣ 📜README.md
┗ 📜yarn.lock
assets/
멀티미디어 파일(이미지, 폰트)constants/
상수 (색상, 공유되는 값 등)components/
재사용 가능한 컴포넌트- 기능 단위로 나누어 하나의 폴더 내에서 컴포넌트를 생성한다. 스타일은
styles.js
파일에 작성하여 컴포넌트에서 import 하여 사용.
- 기능 단위로 나누어 하나의 폴더 내에서 컴포넌트를 생성한다. 스타일은
hooks/
커스텀 훅pages/
라우팅되는 페이지 컴포넌트redux/
리덕스 관련 파일utils/
공통으로 사용하는 함수
▶ 느낀점
많은 것을 한 것 같은데 이제 기획과 세팅을 마친 것이라니.. 프로젝트에 필요한 모든 사항이 결정된 것은 아니지만 프로젝트 기간이 짧은 터라 기능 구현하면서 보완해야 하는 상황이다.
React로 프로젝트 생성하고 설정할 때 항상 예상치 못하게 오류가 발생해서 불안함이 있었다. 프로젝트 초기 설정을 마치고 github에 업로드하고 팀원들이 clone 받아 실행해보았는데 다행히 오류가 없었다. 예전 경험으로는 eslint나 prettier로 인한 오류가 많았어서 이번에는 최소한으로 필요한 부분만 사용했다. 개발하며 필요한 부분은 추가할 예정이다.
이제 본격적인 기능 개발에 들어선다. 계정과 관련된 기능을 맡아 firebase를 이용해 로그인과 로그아웃, 사용자 상태 관리 등을 구현해야 한다. 미숙한 분야라서 걱정도 되지만 꽤 재미있을 것 같다. Auth와 관련된 기록을 꾸준히 남기며 기능 개발 할 예정.
댓글남기기