2023. 11. 27. 20:38ㆍ프레임워크(Framework)/React
미니 프로젝트를 마치며
서론
멋사에서 마지막 미니 프로젝트로 팀이 빌딩되었다.
프로젝트 주제 등 모든 것이 자유였다.
동아리의 마지막 마무리..!
[팀 구성]
팀명 : 안녕 1팀
디자니어 1명
프론트엔드 2명
백엔드 3명
총 6명으로 이루어졌고, 나는 그 중 프론트엔드로 참여하게 되었고, 프론트엔드장 역할을 맡게 되었다.
[프로젝트 기간]
23.9.4~23.11.19
한 학기 세션을 프로젝트로 대체하기로 하였고 중간에 중간고사 기간도 겹쳤기에 프로젝트 기간이 매우 길었다.
[적용 기술 및 협업 툴]
- Frontend : Html, Css, Javascript, React
- Backend : Django
- Collaboration Tool : Github, Figma, notion
[프로젝트 진행]
전체 회의는 대면과 비대면을 병행하여 진행
기획 초반 노션으로 브레인 스토밍을 통해 얘기를 나누었고, 그 결과 많은 사람들이 실사용을 했으면 좋겠다는 의견이 대부분이었다.
한 팀원이 MBTI와 관련된 유형 테스트에 대해 의견을 냈고, 그것을 바탕으로 나의 성향과 맞는 개발자 유형 테스트를 하기로 결정이 되었다.
그리고 비전공자들도 가볍게 테스트를 할 수 있도록 전문적인 용어의 사용은 지양하는 것으로 정했다.
이후 프론트엔드에서는 회의를 통해 각자 맡은 파트를 나누었고, 그 이외로는 매주 진척 상황 공유, 전체적인 컨벤션 정리, eslint&prettier 그리고 scss의 사용 정도를 정했다.
개발자 유형 테스트이기 때문에 서비스명은 'MBIT'로 정했다.
이때 파트는 크게 시작/테스트/결과 총 3가지로 나누었는데, 이 중 나는 테스트 부분을 맡게 되었다.
[개발]
[questions.jsx]
const questions = [
{
question: '대학생이라면 가장 듣고싶은 교양 과목은?',
answer: [
{
text: '유튜버 영상 트렌드 분석 및 추천 AI 연구',
field: ['데이터'],
},
{
text: '쉽게 배우는 프로그래밍 언어',
field: ['백'],
},
{
text: '2023 패션 트렌드',
field: ['프론트'],
},
{
text: 'Esport 배워보기',
field: ['게임'],
},
{
text: '핀테크와 블록체인',
field: ['보안'],
},
],
},
{
question: '당신만의 서비스를 개발하여 출시한다면 어떤 요소에 가장 많은 시간과 재정을 투자하고 싶나요 ?',
answer: [
{
text: '다른 서비스들과 다른 환상적인 디자인과 레이아웃',
field: ['프론트'],
},
{
text: '무엇보다도 안전이 최고. 고객들의 개인정보를 안전하게 보관하는 신뢰성의 구축',
field: ['보안'],
},
{
text: '느려서는 안돼 ! 늘 빠르고 신속한 서비스의 제공',
field: ['백'],
},
{
text: '서비스 이용자 분석 하에 제공되는 맞춤형 서비스로의 이용자 지속적 확대',
field: ['데이터'],
},
{
text: '재미 요소 추가하기 !',
field: ['게임'],
},
],
},
{
question: '당신은 바다 앞 해변에서 모래성을 지으려고 합니다. 당신이 생각하는 가장 중점을 둬야할 점은 무엇인가요 ?',
answer: [
{
text: '무너져도 좋으니 무조건 이쁘게 짓는다 ! ',
field: ['프론트'],
},
{
text: '아니야. 약간 투박하더라도 좋으니 무엇보다도 튼튼하게 지어야 해.',
field: ['보안', '백'],
},
{
text: '어떻게 짓든 무너질텐데.. 그래도 천천히 구상부터 해볼까 ?',
field: ['보안', '백'],
},
{
text: '대충 짓고, 다른 사람 모래성이나 부수러 다니자 !',
field: ['게임'],
},
{
text: '갯벌 진흙으로 지으면 튼튼할거야 ! ',
field: ['데이터'],
},
],
},
{
question: '당신은 로봇 청소기를 구매하려고 합니다. 이 중 당신이 구매하고 싶은 로봇 청소기는?',
answer: [
{
text: '디자인이 이쁜 로봇 청소기',
field: ['프론트'],
},
{
text: '청소가 진짜 잘되는 로봇 청소기',
field: ['백'],
},
{
text: 'cctv 기능이 있어 집 보안에 도움이 되는 로봇 청소기',
field: ['보안'],
},
{
text: '집 구조를 파악해서 쉽게 더러워지는 곳을 집중적으로 청소하는 로봇 청소기',
field: ['데이터'],
},
{
text: '음성 인식을 할 수 있어 재밌게 대화할 수 있는 청소기',
field: ['게임'],
},
],
},
{
question:
'요즘들어 부쩍 헬스장에 다니는 사람들이 많아진 것을 느낀 당신. 자신도 헬스에 도전해 보려고 한다. 헬스장에 가기 전 가장 먼저 해야 할 일은?',
answer: [
{
text: '초심자 티가 나면 부끄러우니 이쁘고 멋있는 헬스복을 구매한다. ',
field: ['프론트'],
},
{
text: '운동하다가 다치면 헬스장에 못가 비용이 아까우니 헬스에 필요한 여러 보조 도구를 구매한다.',
field: ['백'],
},
{
text: '처음 운동을 할 때 제대로 배워야 하기 때문에 pt를 몇 회 받아본다.',
field: ['데이터'],
},
{
text: '혼자 하면 재미가 없으니 운동 메이트를 구해 같이 운동한다.',
field: ['게임'],
},
{
text: '운동할 때 자신의 물건이 들어있는 캐비넷 열쇠가 없어질 수도 있으니 팔에 끼고 운동한다.',
field: ['보안'],
},
],
},
{
question: '여름, 가을이 지나가고 제법 날씨가\n추워졌다.당신이 구매할 겨울 옷은? ',
answer: [
{
text: '얼어 죽어도 무조건 디자인이 이쁜 옷',
field: ['프론트'],
},
{
text: '요즘 트렌드를 분석한 최신 패션 옷',
field: ['데이터'],
},
{
text: '따듯한게 최고! 보온성 갑인 옷',
field: ['백'],
},
{
text: '재밌는 프린팅이 들어간 옷',
field: ['게임'],
},
{
text: '나의 소중한 물건들을 수납할 수 있는 주머니가 많은 옷',
field: ['보안'],
},
],
},
{
question:
'이성 친구를 사귀게 된 당신. 데이트 비용이 용돈으로 감당되지 않아서 아르바이트를 구하려 한다. 가장 하고 싶은 알바는?',
answer: [
{
text: '화장품 가게 알바',
field: ['프론트'],
},
{
text: '보드게임 카페 알바',
field: ['게임'],
},
{
text: '경비 알바',
field: ['보안'],
},
{
text: '공부도 할 수 있고 돈도 버는 독서실 알바',
field: ['백'],
},
{
text: '자택 근무 가능한 데이터 라벨링 알바',
field: ['데이터'],
},
],
},
{
question:
'만약 당신이 손흥민 선수의 팀인 토트넘에 입단하여 같이 경기를 뛸 수 있다고 가정 할 때, 가장 뛰고 싶은 포지션은?',
answer: [
{
text: '팀의 골문을 지키는 골키퍼',
field: ['보안'],
},
{
text: '경기 중 돋보일 수 있는 측면 공격수',
field: ['프론트'],
},
{
text: '공격과 수비를 연결하는 중심적인 역할',
field: ['백'],
},
{
text: '팀의 여러 코치진들에게 의견을 물어봐서 정한다.',
field: ['데이터'],
},
{
text: '뛰는건 싫어. 축구 게임이나 하자 ',
field: ['게임'],
},
],
},
{
question: '당신은 오늘 이성 친구와 데이트를 하기로 했다. 가장 하고 싶은 데이트는?',
answer: [
{
text: '쇼핑하면서 서로 꾸며주기',
field: ['프론트'],
},
{
text: '이성 친구가 피곤한 것 같으니 집에서 놀기',
field: ['백'],
},
{
text: '방탈출 하러 가기',
field: ['보안'],
},
{
text: '카페에서 커플 문답 책 작성하기',
field: ['데이터'],
},
{
text: 'pc방에서 같이 게임하기',
field: ['게임'],
},
],
},
{
question: '나의 책상 위 상태는?',
answer: [
{
text: '아기자기하게 예쁘게 꾸며져 있다.',
field: ['프론트'],
},
{
text: '이것저것 올라가 있지만 나름대로 나의 기준이 있다.',
field: ['백'],
},
{
text: '나만 열 수 있는 작은 수납장이 있다.',
field: ['보안'],
},
{
text: '아무것도 올려져 있지 않다.',
field: ['데이터'],
},
{
text: '닌텐도 스위치와 같은 휴대용 게임기가 있다.',
field: ['게임'],
},
],
},
];
export default questions;
[score.jsx]
const score = [
{
프론트: 0,
백: 0,
보안: 0,
데이터: 0,
게임: 0,
},
{
maxField: '',
maxScore: 0,
},
];
export default score;
[TestPage.jsx]
import { useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import questions from './contents/questions';
import score from './contents/score';
import classes from './TestPage.module.scss';
import logo from '../assets/images/logo.png';
import SelectBtn from '../components/SelectBtn';
import backArrow from '../assets/images/backArrow.png';
function TestPage() {
const navigate = useNavigate();
const num = useParams().id;
const [quiz, setQuiz] = useState({});
const [id, setId] = useState(0);
const [type, setType] = useState('');
useEffect(() => {
const numAsInt = parseInt(num, 10);
if (questions) {
setQuiz(questions[numAsInt - 1]);
setId(numAsInt + 1);
}
}, [num]);
const getScore = (arr) => {
let scoreNum = 5;
arr.map((field) => {
score[0][field] = +score[0][field] + scoreNum;
scoreNum -= 1;
if (score[0][field] > +score[1].maxScore) {
score[1].maxScore = score[0][field];
score[1].maxField = field;
}
});
if (score[1].maxField === '프론트') {
setType('front');
} else if (score[1].maxField === '백') {
setType('back');
} else if (score[1].maxField === '데이터') {
setType('data');
} else if (score[1].maxField === '보안') {
setType('security');
} else if (score[1].maxField === '게임') {
setType('game');
}
};
return (
<div className={classes.background}>
<div className={classes.container}>
<div className={classes.top} />
<div className={classes.logos}>
<img className={classes.logo} src={logo} alt='logo' />
</div>
<div className={classes.bottom}>
<img className={classes.backArrow} src={backArrow} alt='back-arrow' />
<div className={classes.progress}>
{num}
/10
</div>
<div className={classes.question}>
{(quiz.question || '').split('\n').map((line) => {
return (
<>
{line}
<br />
</>
);
})}
</div>
<br />
{num < 10 && (
<div className={classes.answers}>
{quiz.answer &&
quiz.answer.map((item, index) => (
<div key={index}>
<SelectBtn
handleOnClick={() => {
getScore(item.field);
navigate(`/test/${id}`);
}}
>
{item.text}
</SelectBtn>
</div>
))}
</div>
)}
{num == 10 && (
<div className={classes.answers}>
{quiz.answer &&
quiz.answer.map((item, index) => (
<div key={index}>
<SelectBtn
handleOnClick={() => {
getScore(item.field);
navigate(`/result/${type}`);
}}
>
{item.text}
</SelectBtn>
</div>
))}
</div>
)}
</div>
</div>
</div>
);
}
export default TestPage;
개발을 할 때 내가 가장 노력했던 부분은 최대한 적은 양의 코드를 짜는 것이었다.
처음 시작할 때 문항 수만큼 페이지를 만들어야되나 하고 고민했지만 그렇게 하지 않기 위해 따로 문항 데이터를 저장해서 출력이 되도록 하였다. 그리고 코드 리팩토링도 하려고 노력했다.
[결과물]
시작 페이지
테스트 페이지
결과 페이지
[느낀 점]
내가 개발하려는 것이 남들과 차별화를 꾀하려면 엄청난 노력과 아이디어가 필요한 것 같다.
이 과정이 힘들다고 해서 기획을 튼튼하게 세우지 않은 채 개발 단계로 넘어가게 되면 그 과정에서 막히는 부분이 많이 발생한다고 생각했다.
이 부분에서 최근 학교 수업에서 배운 '폭포수 모델'이 생각이 났다.
그리고 프로젝트 개발 중에는 중간중간 변경해야 되는 사항이 발생해서 '애자일 기법'도 생각이 났다.
간단하다고 생각되는 프로젝트에서도 이러한 기법이 필요하다고 생각되는 것을 보니, 소프트웨어 공학과 관련된 부분에 대해 더 열심히 공부하고 앞으로 내가 개발할 때 어느 부분을 적용하면 도움이 될지에 대해 고민하는 시간이 필요할 것 같다.
그리고 개발과 관련되어서는 내가 부족한 점이 많다는 것을 느꼈다.
우선 html, css와 같은 기본적인 부분에서 시간을 많이 잡아먹었기에 이 부분에서 나의 기초가 튼튼하지 못하다는 것을 느꼈다.
하지만 그래서인지 오히려 찾아보면서 고민을 많이 하는 시간이 되었던 것 같다.
이것은 js와 react도 마찬가지이다.
그리고 개발 계획을 세우지 않고 시간이 날 때마다 해서 시간을 효율적으로 사용하지 못한 것 같다고 생각이 든다.
앞으로 개발을 할 때에는 기간 별로 계획을 짜서 시간을 밀도있게 사용하고 싶다.
마지막으로 팀원과의 소통이 적극적으로 안 된 부분이 가장 아쉽다. 다들 학기 중이라 바빴던 것 같다. 쩝
그래도 이번 프로젝트를 하면서 배운 점이 많았기에 다음 프로젝트를 할 때에는 더 나은 내가 되었으면 좋겠다.
깃허브 주소
https://github.com/danii0110/mbit-react
피드백이 있다면 댓글 남겨주세요!
'프레임워크(Framework) > React' 카테고리의 다른 글
[애플스토어 클론 코딩/techit] (0) | 2023.03.28 |
---|---|
react-query (0) | 2023.03.12 |
React 기본 파일(index.js, App.js, index.html) (0) | 2023.03.10 |
[React Query] 리액트 쿼리 시작하기 (useQuery) (0) | 2023.03.06 |
React Hooks란? (0) | 2023.03.05 |