행복을 담는 블로그

[TIL] 240201(목) 개인과제 "그룹 아티스트 팬레터함" 만들기 (1) 본문

TIL

[TIL] 240201(목) 개인과제 "그룹 아티스트 팬레터함" 만들기 (1)

hyun0zin 2024. 2. 2. 01:37

벌써 2월이라니... 시간이 너무 빨리 지나가는 것 같다.

하는거라곤 매일 앉아서 12시간씩 코딩하는 것 밖에 없는데 말이야...

시간 제발 멈춰봐 아직 해야 할 게 너무 많이 남았는데 왜 벌써 목요일이신지... 하하하...

아무튼 간에 이번주는 React 숙련 주차로 react hook과 context api, 그리고 redux 까지 엄청난 강의를 들으며 또다시 새로운 기술들을 배우고 익히고,

이를 적용한 "그룹 아티스트 팬레터 만들기"를 진행하는 중이다.

한 번에 모든 코드 리뷰 쓰려면 엄청 힘들듯 하여, 오늘부터 조금씩 작성해보고자 한다.



1. 프로젝트 셋업

1) CRA 로 프로젝트 생성

npx create-react-app fan-letter

이 명령어를 이용하여 프로젝트를 생성하였다.

 

2) pages/ , components/ , shared/ , assets/ 폴더 작성 및 필요 컴포넌트 작성

필요한 컴포넌트만 처음에 만들고 계속 진행하면서 추가를 했다.

++ 필요없는 파일 정리하기 (reportWebVitals.js / setupTests.js / App.test.js / logo 파일 등등)

(물론 앞으로도 수없이 많은 리팩토링을 거치겠지...)

  • assets : image와 json 파일을 따로 만들어 관리한다.
  • component : layout과 letters 폴더를 만들어 각각에 맞는 컴포넌트를 넣어주고, MainPage와 DetailPage는 따로 관리하였다.
  • pages : 이동해야하는 페이지를 멤버별로 분리하여 만들었다.
  • shared : Router.js 파일을 관리하는 폴더이다.

 

3) styled-components, react-router-dom 설치

이번 과제에서는 styled-component를 이용하여 css 작업을 하는 것이었다.

yarn add styled-components

또한 react-router-dom을 사용하여 페이지간 이동을 할 수 있게 하였다.

yarn add react-router-dom

 

4) title 변경 (index.html)

React App -> BLACKPINK FAN PAGE로 변경해주었다.

 

5) jsconfig.json (src 폴더 기준 절대경로 설정)

{
    "compilerOptions": {
        "baseUrl": "src"
    },
    "include": ["src"]
}



2. “props-drilling” 브랜치 생성 및 이동

🚨 Remind: props-drilling 브랜치에서는 context 나 redux는 사용하지 않습니다!

그말은 즉슨 이번 과제는 props-drilling으로 삽질을 열심히 하는 방법을 연습하고 이후 context와 redux을 이용해 리팩토링 하는 방법을 익히는 것이었다..

(아직 기능 구현도 다 못해서 context는 사용도 못하고 있음... 쉽지 않다 휴🥹)

git checkout -b props-drilling

git checkout -b 명령어를 사용하여 새 브랜치를 만들어줬다.

git switch-c 브랜치이름 으로도 새 브랜치 생성 및 이동을 할 수 있는 명령어이다.



3. Router 셋업

: react-router-dom 을 이용하여 홈화면과 상세화면에 대한 라우터 설정을 한다.

이거 삽질하다가 시간 엄청 잡아먹었다..
왜냐면... router 컴포넌트를 엉뚱한 걸 부르고 있었기 때문이지.. 하하
https://hyun0zinlog.tistory.com/68

그렇게 내가 연결한 Router는 이러하다.

import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";

const Router = () => {
  return (
    <BrowserRouter>
      <Layout>
        <Routes>
          <Route path="/" element={<MainPage />} />
          <Route path="/JENNIE" element={<JENNIE />} />
          <Route path="/JISOO" element={<JISOO />} />
          <Route path="/ROSE" element={<ROSE />} />
          <Route path="/LISA" element={<LISA />} />
          <Route path="*" element={<Navigate replace to="/" />} />
        </Routes>
      </Layout>
    </BrowserRouter>
  );
};

export default Router;

▶️ Mainpage를 Home(path : "/")으로 설정하고, 각각 멤버별로 DetailPage로 이동하도록 만들었다.

 

🚨  <Route path="*" element={<Navigate replace to="/" />} />

▶️ path="*"으로 설정하면, / 뒤에 없는 숫자가 왔다는 의미이고, 그때 Navigate를 이용하여 / 뒤의 값을 "/" 로 replace하여 HOME으로 돌아가도록 설정한다.

 

🚨  path="/JENNIE/:id"

▶️ path parameter(혹은 params) 라고 부른다. path 뒤에 /:를 붙여 원하는 값을 가지고 이동하도록 한다.

useParams() 로 id 값 넘기기

function JENNIE() {
  const params = useParams();
  // console.log(params);

return (
    <div>{id}</div>
  );
}

▶️ params를 console.log 찍어보면, 해당 id 값만 찍히는 것을 알 수 있다.

useParams() : /: 뒤에 붙는 값으로 path parameter 또는 params를 넘겨받는 역할을 한다.



4. 전역스타일링 적용

- styled-components 를 이용
- reset.css 코드 및 box-sizing 적용

GlobalStyle.jsx 파일에서 전역스타일링을 적용했다. 폰트랑 블랙핑크의 핑크 컬러도 여기에 저장했다.

하지만 안타깝게도 styled-component는 root에 변수로 지정한 컬러는 자동입력 기능은 제공하지 않았다..🥹

import { createGlobalStyle } from "styled-components";

const GlobalStyle = createGlobalStyle`

:root{
    --color-blackpink: #f7a7bb;
}

body{
    font-family: "Helvetica", "Arial", sans-serif;
    line-height: 1.5;
}
`;

export default GlobalStyle;



5. 홈 화면 UI

: Header 및 배너 UI 구현

홈 화면 UI로 크게는 Header - Nav - Form - List - Footer로 구현하였다.

- 처음에는 어떤 식으로 UI를 구현할 지 손으로 와이어프레임을 작성해 보았다.

- 이를 토대로 **draw.io**라는 사이트에서 조금 더 구체적으로 구상해보았다.

https://www.drawio.com/



6. 홈 화면 UI

: Dummy Data(fakeData.json)를 이용한 리스트 UI 구현

fakeData.json을 이용해서 하단에 fake letter를 list 형태로 만들어 뿌려준다.
처음에는 json 파일을 LetterList 에서 데이터를 불러와서 LetterItem을 map 함수를 이용해 letter를 만들어주면 된다고 생각을 했다.

근데 또 다른 부분을 작업하다보니 이 json 파일의 데이터가 Nav 컴포넌트에서도 사용되고, LetterForm 컴포넌트에서도 사용되는 것을 알게되었다.

하위 컴포넌트에서 상위 컴포넌트로는 props를 넘겨줄 수 없기에 최상위 컴포넌트인 MainPage 컴포넌트에서 각각의 하위 컴포넌트로 props drilling을 통해 props를 넘겨주는 방식을 선택해야했다.

 

1) useState를 통해 fakeData.json 파일 내에 있는 배열을 사용한다.

/* MainPage */
const [letters, setLetters] = useState([]);

  useEffect(() => {
    setLetters([...fakeData]);
  }, []);
  console.log(letters);

return (
    <>
      <Nav letters={letters} />
      <LetterForm addLetterSubmit={addLetterSubmit} />
      <LetterList letters={letters} />
    </>
  );

이후 LetterList 에 letters={letters}를 props로 넘겨준다.

 

2) LetterList에서 LetterItem을 map 함수로 돌려 카드 형태로 나타나도로 한다.

/* LetterList */
function LetterList({ letters }) {
  return (
    <div>
      {letters.map((item) => {
        return <LetterItem key={item.id} item={item} />;
      })}
    </div>
  );
}

 

3) LetterItem에서 item을 props로 받고, 필요한 값을 구조분해할당을 이용하여 쪼개준 뒤 필요 위치에서 사용한다.

function LetterItem({ item }) {
  const { avatar, content, createdAt, nickname } = item;

return (
    <StMainContainer>
      <StMain>
        <StImgContainer>
          <StImg src={avatar} alt="프로필 사진" />
        </StImgContainer>
        <StDiv style={{ flexDirection: "column", width: "500px" }}>
          <StDiv style={{ justifyContent: "space-evenly" }}>
            <StSpan>{nickname}</StSpan>
            <StSpan>{formattedData}</StSpan>
          </StDiv>
          <StDiv>
            <StP>{content}</StP>
          </StDiv>
        </StDiv>
      </StMain>
    </StMainContainer>
  );
}

이렇게하면 기존에 json 파일에 저장되어 있던 데이터가 list 형태로 화면에 나타난다.