스테이폴리오를 모티브로 한 프로젝트
개발에만 집중할 수 있도록 기존 웹의 기획과 디자인을 참고하여 하나의 사이트를 완성해보는 프로젝트
스테이 폴리오는 ‘파인 스테이 큐레이션 플랫폼’ 이다. 좋은 질의 숙소를 소개해주어 소수의 여행가들만 누리던 서비스를 많은 여행가가 이용할 수 있도록 숙소 호스트와 고객을 연결해주는 서비스이다.
Teck stack
- Front-end: React.js, React hook, Sass, Router, Git&GitHub
- Back-end: Express, Prisma, Mysql, Bcypt, JWT, Git&GitHub
첫번째 프로젝트의 대상으로 스테이폴리오를 선택한 이유
이번 프로젝트에서 처음 알게된 서비스이다. 여행이라는 컨텐츠에도 큰 관심이 없다. 그럼에도 스테이폴리오를 선택한 이유는 예쁜 화면이었다. 팀원의 절반 이상이 프론트엔드 직군을 마음에 두고 있었기 때문에 예쁜 화면이 선택에 있어 결정적인 요소였다. 개인적으로는 다양한 슬라이드를 만들어 보고 싶었어서, 슬라이드가 다양한 스테이폴리오를 클론코딩하면 좋을 것 같아 선택했다.
프론트 [listpage 담당]
- listpage 여행지/숙소 검색, 인원, 가격범위, 스테이유형, 리셋버튼 구현
- listpage 숙소 리스트
- listpage 스테이 유형 카테고리 선택시 query 파라미터로 전달 후 해당하는 숙소리스트 받기
- listpage api 연결
- Main page api연결
백
- dormitory 전체 가져오는 List API
- dormitory image 가져오는 API
- city 리스트 가져오는 API
- rooms Image 가져오는 API
프로젝트에서 가장 기대한 것은 '성장'이었다. Foundation기간에도 그전에는 상상도 못할 엄청난 성장을 하긴 했으나, 진짜를 만들어보는 건 처음이니 그 과정에서 비교하기 힘든 성장을 할 것이라 기대했다. 성장에 대한 기대는 새로운 것과 어려운 것을 도전할 수 있게 했다. 그러나 프로젝트를 끝까지 해내게 한 것에는 팀프로젝트라는데서 오는 책임감과 팀원들분들의 열정, 그리고 데드라인이었다.
scrum으로 진행해서 아침 10시 30분에 하는 회의때 하루에 할 수 있는 적정량과 전체 계획을 고려해 내 계획을 말하고, 내가 한 계획을 지키기 위해서 열심히 개발하고, 오후 6시에 '아침에 말한 바를 다 해내진 못했지만 내일 오전 정도면 다 할 수 있을 것 같다.'라고 정확히 내 상황을 알리는 것 자체가 굉장히 동기부여가 많이 되었다. 내가 속한 팀 자체가 의사소통이 활발하며 상황공유가 빨랐고, 가감없이 문제상황을 알렸기 덕분에 나도 부끄러움 없이 내가 못한것, 내가 해낸것, 모르는 것 등등을 물어볼 수 있었다. 이렇게 의견공유가 자유롭고 개발에 열정있는 분들이 있는 회사에 들어가면 정말 편할 것 같다는 생각이 든다.
식스센스 팀의 팀워크를 보여주는 노션 한번 만 봐주십쇼!
내 담당 api가 일찍 끝나서, main page에 프론트와 백을 연결하는 부분을 맡았다. 여행지/숙소 옆 모달같이 다른 분이 개발하신 컴포넌트를 재사용하기도 했다. 그러다보니 다른 분들의 코드를 읽고 이해하고 연결이 쉽도록 손보는 일을 해볼 수 있었다. 자연스럽게 좋은 코드란 무엇인지에 대해서 고민하게 되었고 나름 정의를 내려보기도 했다.
- SoC(관심사 분리)
SoC가 좋다,좋다 말만 들었지 정말로 왜 좋은지는 몰랐는데 이번 기회에 알게 되었다. 한 함수에 한 가지의 기능만 있거나, 같은 기능을 하는 함수끼리 묶여있으면 읽는 사람이 자연스럽게 내용을 분리해서 읽게 된다. 슬라이드 로직 부분은 이 함수에 있고, 슬라이드 데이터를 받는 부분은 이곳이구나, 혹은 컴포넌트 재사용시 이 부분은 기능에 핵심이니 건들지말고 이 부분은 커스텀해도 되겠구나 하는 이해가 시작되면 재사용이 쉬워지고 보수하기도 쉬워진다.- 변수, 함수이름이 명확함
프로그래밍 언어 안에서 사람의 언어로 표현할 수 있는 부분은 변수나 함수의 이름같다. 명확한 이름을 가지고 있으면 확실히 이해가 쉬워진다.
이번 프로젝트가 끝나고보니 가장 후회가 되는 것은 프로젝트의 목표자체가 프론트엔드에 치우쳤다는 점이다. 프론트쪽에서는 다양한 도전을 했지만, 백은 전체를 조회하는 정도 이상을 만들어보지 못한게 아쉽다. 예약기능이나, 별점기능, 하트버튼 기능 등을 구현 못한 것이 아쉽다.
공식문서를 읽지 않고 시작한 것도 아쉽다. 읽어보고 충분히 공부하고 들어갔으면 개발이 좀 편했을 hook들이 있었다. 개발하는 동안에는 너무 정신이 없어서 공부할 시간이 없었지만 지금은 필요성을 느꼈으니 조금씩 어디서 사용하는지 정도는 공부해둬야겠다.
랜덤으로 담당페이지를 정하게 되어서 원하는 슬라이드는 하지 못했지만, 다양한 UI를 개발해보았다.
스테이폴리오 사이트에서 여행지 숙소, 도시 선택, 인원, 가격범위, 스테이유형, 리셋버튼을 선택하여 구현해보았다. 그 중에서 공들인 부분은 인원, 가격범위, 스테이 유형 세 버튼임으로 이 세 부분을 중점으로 공유하고 싶은 코드, 숨기고 싶은 코드, 깨달은 점을 이야기해보고자 한다.
function historyHandler() {
const temptArr = [];
let query = `category=`;
names.forEach(name => {
if (name === '펜션') {
temptArr.push('pension');
}
if (name === '게스트하우스') {
temptArr.push('guest');
}
if (name === '호텔') {
temptArr.push('hotel');
}
if (name === '렌탈 하우스') {
temptArr.push('rental');
}
});
let subquery = '';
temptArr.forEach(data => {
subquery += `${data},`;
});
query += subquery;
navigate(`/list?${query}`);
}
카테고리 체크 된 것을 쿼리파라미터로 보내기 위해서 router url을 만들고, navigate로 url을 변경하는 코드이다. 깔끔하게 정리된 상태는 아니지만 공유하고 싶은 이유는, 이 코드를 위해서 이틀동안 엄청나게 검색을 했기 때문이다.
처음 이 코드를 쓸때만해도 url과 Uri의 차이, 쿼리파라미터 등 백엔드에게 정보를 전달하는 방법을 전혀 이해하지 못했다. 그렇기에 방법을 찾아보려고 쿼리파리미터에 대해 검색을 하고, 다른 분들께 질문하고 해서 끝내 해냈기에 기억에 남는다.
useEffect(() => {
if (location.search === '') {
fetch('http://localhost:8000/dormitories/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then(res => res.json())
.then(result => {
setProducts(result.data);
});
}
if (location.search !== '') {
fetch(`http://localhost:8000/dormitories/search/${location.search}`, {
method: 'GET',
})
.then(res => res.json())
.then(result => {
result.searchedDormitories && setProducts(result.searchedDormitories);
});
}
}, [location]);
위와 이어서, 백과 통신하는 부분이다. use.location()을 사용하여서 uri에 쿼리파라미터 정보를 포함하여 보냈다. 화면에 성공적으로 원하는 카테고리만 뜰때 얼마나 기뻤는지 모른다. (Wework에서 백 담당분이랑 정말 기뻐했다...)
function closeModal(e) {
const parentStyleVisible =
e.target.parentElement.parentElement.style.visibility;
let judge = false;
if (parentStyleVisible === 'visible') {
judge = true;
}
e.target.parentElement.parentElement.style.visibility = judge && 'hidden';
}
각 작은 창에 달린 X버튼을 닫는 코드이다. 더 상위인 창을 닫기 위해서 무한으로 parentElement를 써서 올라갔다. 그리고 단축평가를 써보겠다고 Judge 라는 변수를 추가했다.
새로배운 것을 한번 쓰고 싶은 마음에 코드가 더욱 복잡해졌다. 더 간단한 방법으로 if문을 써도 되는 것을 알면서도 말이다. 앞으로도 새로운 것, 새롭게 알게된 것을 써보고 싶은 유혹 앞에 멈춰서 '새롭게 알게 된 것이 항상 좋은 것인가?' 고민을 해야할 것 같다.
가장 상위 page였던 list Page에 만든 창이 닫히는 setState를 prop으로 자식에게 보내었다. closModal() 함수 전체가 필요없어 삭제하고 버튼 onclick 이벤트에 setState를 이용해 visibility 값을 'hidden' 주었다.
├LayOutFirst.js
<BlackButton
content="적용하기"
onClick={() => {
onClickHandler();
onHidden('hidden');
}}/>
├LayOutSecond.js
<BlackButton
content="적용하기"
onClick={e => {
putTitle(e);
onHidden('hidden');
}}/>
├LayOutThird.js
<BlackButton
content="적용하기"
onClick={e => {
checkedCatogories();
changetitle();
onHidden('hidden');
historyHandler();
resetcheckedCategoriesArr();
}}/>
따로 다뤄보고 싶어서 작성한 부분: 코드리뷰
사람마다 회사를 보는 기준은 다를 수밖에 없다. 어떤 사람은 자신이 관심있는 서비스여야하고, 다른 사람은 이제 막 시작되어 급속으로 성장하는 곳을 선호할 수도 있다. 이 교육과정의 목표는 배움이기도 하지만 동시에 취업이기도 하다. 그렇기에 프로젝트를 하는 순간마다 '나는 어떤 곳에 취업해야하나(할 수 있을까/ 하고 싶을까)?'하는 고민이 들었다.
서비스 자체는 1순위에 두지 않는다. 그러나 선택할 수 있다면 책을 좋아하기에 전자책 서비스를 다루는 곳을 가고 싶다. 또는 3년정도 초중고 수학 학원강사 일을 해봐서 가르치는 일에 관심이 많아 교육관련 서비스도 좋겠다. 전공을 살려서 자기계발이나 상담 쪽 서비스도 좋다. 이런 분야라면 기본 지식과 경험이 있으니 서비스 전체를 객관적으로 바라보는 시각이 생길 것 같다.
1순위에 두는 것은 '내가 성장할 수 있는 곳인가?'이다. 내가 성장할 수 있는 곳이라하면 그것또한 조건이 다양할 수 있다. 내가 생각하는 이상적인 조건은 팀 분위기이다. 질문할 사람도 있고, 나에게 질문할 사람도 있는 분위기가 좋다. 데드라인이나 계획이 확고한 팀이면 더 좋겠다.