2주 전부터 옥소폴리틱스 사의 인턴십에 합격하여 2명의 팀원과 함께 인턴십을 진행하고 있다. 나는 이제 막 HTML/CSS/JS 기초를 뗀 쌩 입문자였기 때문에 1주일동안 리액트를 마스터 해야하는 미션이 주어졌었다. 일주일만에 리액트 정복하기(1)
[React] 일주일만에 리액트 정복하기! (1)
나에게는 아주 안 좋은 습관이 있다. 덧셈 뺄셈을 배우던 초등학생 시절부터 거의 병적으로 손으로 필기하기를 싫어했다. 필기가 필수인 대학 수업 때도 PPT 제공 없는 교수님의 수업까지도 필사
youngst.tistory.com
어찌저찌(?) 리액트를 한 주만에 익히고 그 다음 미션이 옥소폴리틱스 사의 메인페이지를 클론 코딩 해보기였다. 옥소 사의 문화 자체가 위에서 해야할 일을 지시하는 위계 조직이 아닌 팀에서 스스로 해야할 일을 찾아서 정리하고 모르는 게 있을 때 도움을 요청하는 역할 조직을 지향하고 있었기 때문에 처음 이틀간은 코딩보다는 협업할 때의 룰, 컨벤션 등을 정리하였다.
협업 방법
- 협업은 Git-hub으로 하며 각 개인의 작업은 main 레포지토리를 Fork하여 작업한다.
- 작은 프로젝트인만큼 dev 브랜치는 생략하며, 본인의 작업을 merge하였을 때는 반드시 팀에 알린다.
- 팀원이 작업을 merge하였을 때는 conflict를 방지하기 위해 반드시 원본 repo를 pull한 후 다시 작업한다.
- conflict를 최대한 막기 위해 각 작업은 될 수 있으면 본인이 맡은 컨포넌트에 한해서 작업한다.
코딩 컨벤션
- String은 홑 따옴표('string')를 사용하며, 들여쓰기는 2칸으로 한다.
- this를 쓰지 않는 경우 되도록 화살표 함수를 사용한다.
- 모든 변수와 HTML class name은 camelCase를 사용하여 명명한다.
사용 툴
- 텍스트 에디터는 VS Code를 사용하며 ESLint와 Prettier를 연동하여 사용한다.
- Prettier 설정은 동일하게 맞춘다.
- 빌더는 바벨을 사용하는 CRA 대신 ESbuild를 사용하는 Vite를 사용한다.
- CSS는 스타일드 컴포넌트(Styled-Components)를 사용한다.
팀원 모두 개발 공부를 시작하고 처음 해보는 팀 프로젝트였기 때문에 처음엔 Git으로 Pull Request 날리는 것부터 애를 조금 먹었지만, 매일 아침부터 저녁까지 공부하고 소통하며 충돌 없이 병합하는 방법들을 익혀갔다.
충돌을 피하기 위해 홈페이지를 다음과 같이 3개의 컴포넌트로 나누어 작업하였다. (Comunity 컨테이너는 나중에 추가 하였다.)
내가 팀원 중 가장 배운 기간이 짧았기 때문에(나는 제로베이스 4기였고, 2명의 팀원 분들은 3기였다) 제일 구현하기 쉬운 Side 영역을 맡기로 하였다. 만약 구현하고 시간이 남는다면 다른 팀원의 영역을 같이 진행하기로 하였다.
Side 영역 구현하기
우선 사이드 영역을 다음과 같은 컴포넌트로 쪼개었다.
이번 클론 코딩을 진행하며 깨달은 점인데 나는 큰 컴포넌트에서 시작하여 점점 작게 쪼개어 가는 Top-down 방식을 선호한다. 우선 영역을 잘게 쪼갠 후 작은 영역부터 구현해 가며 위치를 잡아가는 방식이 나에게 편리했다. 우선 제일 작은 컴포넌트 단위인 Group을 먼저 구현하였다.
Group 컴포넌트 구현하기
이번 클론 코딩은 fetch나 axios로 직접 서버에서 JSON을 받는 대신 회사 측에서 JSON 데이터를 파일 형태로 제공해주셨다.
JSON 파일은 아래와 같이 구성되었다.
객체 속에 data key값을 이용하여 각 그룹의 정보를 담은 객체들을 받아올 수 있었다. 하지만 그룹들은 마지막 게시글 순서대로 정렬되어야 했고 나는 lastGroupPost~라는 정보를 이용하여 그룹을 sorting 해야했다. 지금까지 연습한 JSON 데이터는 모두 배열 형태로 받아올 수 있었기 때문에 map이나 sort를 자연스럽게 사용할 수 있었지만 객체에 이들 함수를 사용하거나 for문을 사용하면 Iterable하지 않다는 에러를 뱉어내었다. 조금 더 찾아보니 객체는 for-in 구문을 이용해 key 값들을 순회할 수 있다는 것을 알게 되었고 이를 이용해 key 값을 id로 갖는 배열로 다시 만들기로 하였다. 사실 JSON 파일은 그냥 import하여 사용하면 그만이었지만 나중을 위해 fetchJsonToArray라는 함수를 구현하여 데이터를 받아왔다.
function fetchJsonToArray(rawJson) {
const array = [];
const jsonData = rawJson.data;
for (const key in jsonData) {
jsonData[key] = { ...jsonData[key], id: key };
array.push(jsonData[key]);
}
return array;
}
위 함수는 Comunity 영역에도 동일하게 적용할 수 있어서 public 폴더에 따로 분리하여 재사용하였다. public과 src 폴더의 용도가 정확히 어떻게 다른지는 더 공부가 필요하다.
이렇게 만든 배열을 map 메서드를 통해 GroupContainer에 렌더링할 수 있었다. 그룹 사이의 구분선은 스타일드 컴포넌트로 만들어 삼항 연산자를 통해 렌더링해주었다.
return (
<Container>
<GroupsTitle>
<h2>그룹</h2>
<div>{'>'}</div>
</GroupsTitle>
<ListContainer>
{groupsArray.map((elem, idx) => (
<li key={elem.id}>
<Group
key={elem.id}
title={elem.title}
description={elem.description}
imgLink={elem.photos}
followers={randomFollowers()}
lastGroupPostCreatedAt={elem.lastGroupPostCreatedAt}
/>
{idx != props.length - 1 ? <HrLine /> : null}
</li>
))}
</ListContainer>
</Container>
);
마지막 게시글 작성일은 'n 시간 전', 'n일 전'과 같이 구현해야했기 때문에 이것은 Group 컴포넌트 내부에서 처리했다.
const getDateString = (date) => {
const now = new Date();
const HOUR_MILLI_SEC = 3600 * 1000;
let time = now - date;
time /= HOUR_MILLI_SEC;
if (time < 1) {
return `${Math.round(time * 60)}분 전`;
} else if (time < 23.5) {
return `${Math.round(time)}시간 전`;
} else if (time < 7 * 24 - 0.5) {
return `${Math.round(time / 24)}일 전`;
} else if (time < 24 * 10) {
return '1주 전';
} else {
const thisDate = new Date(date);
return `${thisDate.getFullYear()}.${
thisDate.getMonth() + 1
}.${thisDate.getDate()}`;
}
};
내가 생각했을 때 최선의 방법으로 구현하였는데, 혹시 더 나은 방법이 있는지 공부해 볼 생각이다.
그룹 설명은 overflow:hidden을 이용할까 하다가 그냥 silce를 이용해 간단하게 잘라주었다.
const groupdescription =
description.length > 14 ? description.slice(0, 13) + '...' : description;
남은 건 귀찮은 CSS 작업과 Footer 작업 뿐이었기에 그룹 사이드바는 빠르게 마무리할 수 있었고, 커뮤니티의 댓글 항목 또한 내가 작업하기로 하였다.
(2)에서 계속!