[오늘 프로젝트] 레이아웃 만들기(상세 페이지)

비얌·2022년 10월 21일
1
post-thumbnail

개요

이번 주는 각자 페이지 레이아웃을 만드는 기간이다. 디두 님은 메인 페이지의 레이아웃, 나는 상세 페이지의 레이아웃을 제작하면 된다.

이번 포스팅에서는 상세 페이지(todo 페이지)를 만드는 과정, 삽질 기록 등등을 기록해보았다.



상세 페이지 만들기

<목차>
1. 라우팅이 뭐예요?🤣
2. 컴포넌트 분리 계획해보기
3. html + css로 화면 구성하기(+네이밍 컨벤션)(+처음 써보는 tailwindcss)
4. 컴포넌트 분리하기

1. 라우팅이 뭐예요?🤣

우리는 아래 사진과 같이 주 페이지를 두 개 가지고 있다. 메인 페이지에서 '오늘의 할일 적으러 가기'를 클릭하면 '오늘의 할 일'이 적힌 상세 페이지로 이동해야 한다.

이때 사용되는 것이 라우팅이라는 것을 직감적으로 알 수 있었다. 왜냐하면 이전에 개발동아리에서 리액트 라우팅을 잠시 배웠기 때문이다. 하지만 이때 너무 어려워 이해하지 못하고 넘어간 기억이 있다.

일단 지금은 todo 페이지만 구현하면 되지만 지금 라우팅을 이해하지 이해하지 못하면 이 프로젝트를 완전히 이해하지 못할 것 같다는 두려움이 들었고, 그래서 간단히라도 이해해보기로 했다!(아래처럼 페이지가 두 개로 나뉘는게 이해가 가지 않았다.)

인터넷에서 검색한 대로 라우팅 기능을 구현해보려고 했다. 하지만 정확히 알고 쓰지 못해서 아래와 같은 엄청난 오류가 났고, 겁에 질려버렸다..>_<

이때 오류메시지의 내용은 Router 안에 Router가 들어갈 수 없다는 것이었는데, Routes가 Switch 대신 쓰이는 것인 줄 몰랐기 때문에(버전이 올라가면서 바뀜) 구글링에서 찾은대로 react-router-dom을 버전 6에서 5로 마이그레이션 시켜버렸다(...)(그래도 되는 줄 알았음) 버전 5와 버전 6이 뭐가 다른지도 몰랐기 때문에 버전 6의 문법을 버전 5에 쓰면서 또다시 엄청난 오류가 발생했고... 결국 도움을 받아 오류를 해결했다.

오류는 단 두 개를 고쳤더니 해결됐다.

  1. 일단 다시 버전 6으로 업데이트하기
  2. App.js에서 BrowserRouterRoutes로 바꾸기

가장 최신 버전인 버전 6으로 업그레이드를 했고, App.js에서 모든 Route 태그를 감싸는 태그로 BrowserRouter가 아니라 Routes를 써줬다.

그이유는 아래에서 잘 설명하고 있다.

  • BrowserRouter는 HTML5의 History API(pushState, replaceState, popstate event)를 사용하여 URL과 UI를 동기해주는 <Router>이다.

  • 이는 페이지를 새로고침하지 않고도 주소를 변경할 수 있도록 해주고, 현재 주소에 관련된 정보를 props로 조회 및 사용이 가능하도록 한다.

  • BrowserRouter는 리액트 라우터 돔을 적용하고 싶은 컴포넌트의 최상위 컴포넌트를 감싸주는 래퍼 컴포넌트이기 때문에, App 컴포넌트를 감싸주면 된다.

BrowserRouter는 index.js에서 App 컴포넌트를 감쌀 때만 사용해야 한다. 나는 모든 곳에 다 쓰이는 건 줄 알고 App.js에서 Route를 감싸줬으므로 오류나 났던 것이다.(정말 라우팅에 대해 모르는데 일만 무작정 만들어봐서 그랬다..)

결론은 BrowserRouterRoutes로 바꿔줘서 해결했다.

// src/index.js
import { BrowserRouter } from "react-router-dom";
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);
// App.js
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Main from "./pages/Main/Main";
import Todo from "./pages/Todo/Todo";
const App = () => {
  return (
      <Routes>
        <Route path="/" element={<Main />} />
        <Route path="/todo" element={<Todo />} />
      </Routes>
  );
};

export default App;


2. 컴포넌트 분리 계획해보기

페이지 레이아웃을 짜기 위해, 아래와 같이 상세 페이지에서 컴포넌트를 분리해보기로 했다.



3. html+tailwindcss로 화면 구성하기

3-1. 네이밍 컨벤션 - BEM

className을 짓다가 이름을 짓는 어떤 규칙이 있을 것 같아서 찾아봤다. (이걸 네이밍 컨벤션이라고 한다고 함)

BEM방식을 추천하는 글을 많이 봐서, 이 규칙을 배워보기로 했다.

공식 사이트에서는 element는 __로 연결하고, modifier는 --로 연결하고, block은 -로 연결하라고 한다. 하지만 이것만으로는 이해가 안 가서 더 찾아봤고, 어떤 외국 기사에서 쉽게 설명하고 있어서 설명을 가져왔다.

아래의 코드를 보면 소문자로 작성하고, 일반적인 이름을 나눌 때는 -을 사용하고(여기 나와있지는 않음), 앞선 단어에 의존하는(앞선 단어의 특징을 얘기하는 듯) 요소는 __로 분리하고, 앞선 단어의 스타일을 변경하는 특징은 --로 구분한다는 것 같다.

/* Block component */
.btn {}

/* Element that depends upon the block */ 
.btn__price {}

/* Modifier that changes the style of the block */
.btn--orange {} 
.btn--big {}

3-2. html만 제작

일단 html만을 작성하여 기본적인 뼈대를 만들어보았다.

import React from 'react';

const Todo = () => {
  return (
    <div>
      <div className="big-container">
        <div className="small-container">
          <div className="title">
            <h1>오늘의 할 일</h1>
            <div className="filter">
              <button className="filter__all">전체</button>/
              <button className="filter__done">완료</button>/
              <button className="filter__yet">미완료</button>
            </div>
          </div>
          <div className="smallContainer">
            <form>
              <div className="input">
                <input 
                  className='input__text' 
                  type='text' 
                  placeholder='일감 입력하기'
                />
                <input 
                  className='input__submit' 
                  type='submit' 
                  value='제출'
                />
                </div>
              <div className="lists">
                <div className="list">
                  <input
                    className="list__checkbox" 
                    type='checkbox'
                  />
                  <span className="list__content">강아지 산책</span>
                  <button 
                    type='button'
                    className="list__edit-btn" 
                  >수정</button>
                  <button 
                    type='button' 
                    className='list__delete-btn'
                  >삭제</button>
                </div>
              </div>
            </form>
            </div>
        </div>
        <div className="share">
          <input
            className="shareBtn"
            type="submit"
            value="SNS 공유"
          />
        </div>
      </div>
    </div>
  );
};

export default Todo;

이렇게 하면 꽤 많이 설정했다고 생각했는데도 아래와 같은 결과가 나온다. 당연하다 css 설정을 안 했음.. 우리는 tailwind css를 사용하기로 했으므로 이제 tailwind도 유튜브를 보고 배워야겠다


3-3. html + css(tailwind css) 제작

하..아니 조금 배워보니까 tailwindcss를 사용할 거면 className에 list input 이런 이름을 안 써도 됐었음!!! 그니까 네이밍 커벤션도 배울 필요가 없었던 것!!! 당연히 유용한 정보 얻어가서 좋았지만 tailwindcss에는 그런 게 아예 안 쓰인다는게 너무 신기하다.

의미 기반이 아닌 시각적 기능에 기반한 이름을 짓는다는 것 자체가 너무 신기한 것 같다. (이를 Atomic CSS라고 한다고 함. 미리 만들어둔 시각적인 이름을 바탕으로 HTML에서 필요한 스타일을 적용하는 방식) 별도의 파일 없이 html에서 모든 걸 표현할 수 있다는 것도 좋은 것 같다.


👉🏻 이렇게 신기한 tailwindcss가 왜 등장했는지, 그리고 왜 기존의 일반 css와 다르게 쓰는 건지 아래의 글에서 잘 알 수 있었다. tailwindcss에 대해 꾸준히 제기되었던 문제점과 그런데도 쓰는 이유도 함께 알 수 있었다!

👉 카카오 Tech 페이지 (css의 역사를 등장 배경과 함께 쉽게 설명하고 있다.)


하여튼 존에 시맨틱한 className은 다 지워야 한다🤣 그래도 이게 어떤 기능인지 시맨틱한 이름으로 다 지어뒀으니까 오히려 tailwindcss를 작성할 때 알아보기 더 편한 것 같다.)

tailwindcss를 적용하여 어느 정도 레이아웃을 완성했다.



4. 컴포넌트 분리하기

이제 컴포넌트를 분리해보자. 컴포넌트는 미리 그려봤던 대로 나눴다. 아래처럼 나눴는데, Title 컴포넌트는 굳이 필요하지 않을 것 같아서 만들지 않았다.


아래처럼 각 컴포넌트에 나눴으며 나누기 전과 같이 정상적으로 화면이 출력된다!



🐹 회고

이번 주에 맡은 역할인 상세 페이지(todo 페이지)를 만들어보았다.

tailwindcss를 처음 써봐서 많이 헤맸지만 그래도 tailwind로 기본적인 css를 구현해서 다행이다! 이번에 처음으로 공식 문서(taiwind)를 보면서 공부했는데, 공식 문서라도 엄청 쉽고 자세히 나와 있어서 무리 없이 읽었다. 공식 문서가 어렵다는 편견이 조금 깨진 것 같다.

이제 디두 님이랑 회의하면서 잘했는지, 수정할 사항이나 겹치는 컴포넌트 혹은 추가해야 할 컴포넌트는 없는지 확인해봐야겠다!

profile
🐹강화하고 싶은 기억을 기록하고 공유하자🐹

0개의 댓글