2023.05.01 TIL

0

TIL

목록 보기
21/37
post-thumbnail

오늘의 나는 무엇을 잘했을까?

능동적으로 공부한 하루였다. 이번 주 페어 프로그래밍 과제를 대비하여 피그마로 간단한 기획 및 디자인까지 완료하였다. react-switch라는 패키지를 통해 토글 스위치를 만드는 법까지 찾아서 배웠고, 다크모드, 라이트모드를 구현하는 것 까지 배웠다. 이렇게 구현할 필요가 있어서 능동적으로 배우는 경우 특히 기억에 더 남고 내 것이 되는 것 같다.

오늘의 나는 무엇을 배웠을까?

리액트 라우터

React-router-dom v6에 대해서 알아본다.

구성 컴포넌트는 크게 다음과 같다.

 /* 페이지를 나누는 컴포넌트 */
 <Router />   // 리액트 라우터에 쓰이는 데이터들(현재 주소 등)을 모두 가지는 컴포넌트
 						 // 내부적으로는 ContextProvider이다.
 <Routes />   // path의 switch문 같은 역할
 <Route />    // switch문의 case같은 역할
 
 /* 페이지를 이동시키기 위한 컴포넌트 */
 <Link />
  • NavLink 컴포넌트

    메뉴에서 사용하는 링크. Link와 같이 사용할 수 있지만 스타일이라는 prop으로 함수를 내려줄 수 있다. 이 함수는 isActive라는 프로퍼티가 있는 객체를 파라미터로 받는데, isActive는 현재 라우트가 to프롭으로 받은 라우트이면 true이기 때문에, 이것을 이용해서 지금 선택된 라우트로 가는 NavLink를 스타일링 할 수 있다.

    import React from "react";
    import { NavLink } from "react-router-dom";
    
    const Nav = () => {
      const underline = ({ isActive }) => {
        return {
          textDecoration: isActive ? "underline" : undefined,
        };
      };
    
      return (
        <nav>
          <ul>
            <li>
              <NavLink to="/catalog" style={underline}>
                카탈로그
              </NavLink>
            </li>
            <li>
              <NavLink to="/community" style={underline}>
                커뮤니티
              </NavLink>
            </li>
          </ul>
        </nav>
      );
    };
    
    export default Nav;
  • useParams훅을 이용한 동적 경로 활용하기

    <Route path="courses">
      <Route index element={<CourseListPage />} />
      <Route path=":courseSlug" element={<CoursePage />} />
    </Route>

    위 코드처럼 path에 ‘:’을 쓰면 path를 변수처럼 사용할 수 있다. 그리고 해당 path의 페이지에서 useParams훅을 사용하여 path를 참조할 수 있다. 리액트에서 경로에서 쓰이는 동적인 값들은 파라미터라고 부르며, useParams는 이 파라미터들을 리턴한다. 파라미터값을 쓰려면 Route에서 ‘:’뒤에 작명해준 값을 구조분해해서 사용하면 된다.

    function CoursePage() {
      const { courseSlug } = useParams();
      const course = getCourseBySlug(courseSlug);
    	...
    }
  • Navigate로 리다이렉트 하기

    Navigate컴포넌트는 다음과 같이 사용할 수 있다. 아래 예제는 사용자가 잘못된 쿼리 파라미터를 입력했을 때 다시 이전 페이지인 courses페이지로 리다이렉트 시키는 데 Navigate컴포넌트를 사용한 예시이다.

    function CoursePage() {
      const { courseSlug } = useParams();
      const course = getCourseBySlug(courseSlug);
      const courseColor = getCourseColor(course?.code);
    
      if (!course) {   // course가 없다면 (잘못된 쿼리 파라미터 입력)
        return <Navigate to="/courses" />;
      }
    	...
    }
  • useSearchParams 훅을 이용한 검색 쿼리 스트링 조작하기

    useSearchParams는 현재 경로의 쿼리스트링값을 참조하고 변경시키는 데 사용한다. 사용법은 useState와 비슷하지만, state에 해당하는 부분의 값은 get메서드가 있어서 key를 넘겨주면 값을 리턴한다.

    useParams의 리턴과 마찬가지로 객체를 리턴한다.

    검색 폼이 있는 페이지와 함께 사용할 때 시너지가 좋다. 우리가 사용할 검색 키워드의 키값을 ‘keyword’라고 지정했을 때, 우선 해당 검색 페이지에 오면 useSearchParam을 이용해서 keyword값을 가져온다. 만약 처음 들어온 상태라면 그 값이 없을 것이고, 그러면 페이지의 keyword라는 스테이트를 빈 문자열로 만들어준다. 그 후 검색폼에 사용자가 치는 값을 setKeyword해주고, 서브밋을 누르면 setSearchParam({keyword});를 실행해 검색 쿼리스트링을 직접 바꿔주어 라우팅되게 한다.

    function CourseListPage() {
      const [searchParam, setSearchParam] = useSearchParams();
      const initKeyword = searchParam.get('keyword');
      const [keyword, setKeyword] = useState(initKeyword || '');
      const courses = getCourses(initKeyword);
    
      const handleKeywordChange = (e) => setKeyword(e.target.value);
    
      const handleSubmit = (e) => {
        e.preventDefault();
        setSearchParam(keyword ? { keyword } : {});
      };
    
      return (
        <ListPage
          variant="catalog"
          title="모든 코스"
          description="자체 제작된 코스들로 기초를 쌓으세요."
        >
          <form className={searchBarStyles.form} onSubmit={handleSubmit}>
            <input
              name="keyword"
              value={keyword}
              onChange={handleKeywordChange}
              placeholder="검색으로 코스 찾기"
            ></input>
            <button type="submit">
              <img src={searchIcon} alt="검색" />
            </button>
          </form>
    
          <p className={styles.count}>{courses.length}개 코스</p>
    
          {initKeyword && courses.length === 0 ? (
            <Warn
              className={styles.emptyList}
              title="조건에 맞는 코스가 없어요."
              description="올바른 검색어가 맞는지 다시 한 번 확인해 주세요."
            />
          ) : (
            <div className={styles.courseList}>
              {courses.map((course) => (
                <CourseItem key={course.id} course={course} />
              ))}
            </div>
          )}
        </ListPage>
      );
    }
  • useNavigate 훅을 통한 페이지 자동 이동

    useNavigate훅을 통해 페이지를 특정 행위가 일어나고 나서 이동시킬 수 있다. 예를 들면 쇼핑몰 결제이후 결제 확인페이지로 이동하거나, 인터넷 강의 페이지의 경우 강의가 끝나면 강의 홈 페이지로 이동하는 경우다. useNavigate가 리턴하는 함수는 인자로 경로를 받고, 실행하면 해당 경로로 라우팅 시킨다.

    다음은 useNavigate훅을 이용하여 수강하고자 하는 코스 담기 버튼을 누르면 장바구니로 이동시키는 핸들러 함수를 구현한 예제이다.

    function CoursePage() {
      const navigate = useNavigate();
      ...
    
      const handleAddWishlistClick = () => {
        addWishlist(course?.slug);
        navigate('/wishlist');
      };
    
      return (
        <>
         ...
            <Button variant="round" onClick={handleAddWishlistClick}>
              + 코스 담기
            </Button>
         ...
        </>
      );
    }
  • react-helmet 라이브러리를 이용하여 문서 타이틀 편리하게 설정하기

    import { Helmet } from 'react-helmet';
    import Button from '../components/Button';
    import Container from '../components/Container';
    import Lined from '../components/Lined';
    import styles from './HomePage.module.css';
    import landingImg from '../assets/landing.svg';
    
    function HomePage() {
      return (
        <>
          <Helmet>
            <title>Codethat - 코딩이 처음이라면, 코드댓</title>
          </Helmet>
    		...
    	);
    }

    위와 같이 react-helmet을 npm을 통해 받아준 뒤, 매 페이지마다 Helmet이라는 컴포넌트에 title트개를 만들어 편하게 타이틀을 다르게 설정해줄 수 있다.

    SPA의 이해

  • 클라이언트 사이드 렌더링

    서버가 index.html파일과, 필요한 js파일을 클라이언트에 보내줌→웹 브라우저에서 js파일을 읽고 실행하여 동적으로 html파일을 생성함

    위 방식으로 리액트는 동작한다. 그런데 리액트는 html파일을 단 하나만 가지고 있다. 바로 서버에서 처음 보내준 index.html이다. index.html 을 보면

    하나만 달랑 있는 것을 확인할 수 있다.

    이 루트 아이디를 가지는 div에 그때 그때 필요한 js파일을 실행시키면서 우리가 페이지에서 볼 모든것을 렌더링 하는 것이다. 그래서 리액트로 만든 사이트에서 아무리 돌아다니고 주소창에 다양한 파라미터를 넣어서 쳐도 서버는 처음의 index.html과 동일한 파일만 응답으로 준다.

    이것이 바로 싱글 페이지 애플리케이션의 구조이다.

  • 배포 시 주의점

    개발환경에서는 라우팅이 우리가 의도한대로 잘 동작하지만, 사실 이건 모든게 개발할때는 세팅되어 있기 때문이고, 배포할 때는 따로 해줘야 하는 설정이 있다. 예를 들어 네틀리파이에 배포할 때는 netlify.toml파일을 루트 디렉토리에 추가하여 다음과 같이 index.html안에서 리다이렉션을 한다고 알려줘야 한다.

    AWS S3에 배포할 경우에는 따로 버킷 설정에서 해줘야 한다.

    // netlify.toml
    [[redirects]]
      from = "/*"
      to = "/index.html"
      status = 200

Context Provider로 테마 구현하기

Theme이라는 컨텍스트를 만든다.

 export const ThemeContext = createContext(null);

컴포넌트에 테마 토글 스위치를 위치시킨 후, ThemeContext.Provider로 감싸준다. 그리고 토글 스위치의 onChange이벤트에 theme state를 세팅하는 핸들러를 등록한다.

 function App() {
   const [theme, setTheme] = useState("light");
   const handleChange = () => {
     setTheme(theme === "light" ? "dark" : "light");
   };
   return (
     <ThemeContext.Provider value={{ theme }}>
       <ToggleSwitch theme={theme} onChange={handleChange} />
     </ThemeContext.Provider>
   );
 }

오늘의 나는 어떤 어려움이 있었을까?

알고리즘 문제를 못풀고 있다… 하루에 한 문제는 풀어야 한다고 생각하는데 24시간이 모자란것 같다. 하루빨리 시스템을 구축해야 할 것 같다.

내일의 나는 무엇을 해야할까?

  • 페어프로그래밍 시작
  • 스타일드 컴포넌트 강의 듣기
  • 데일리 미션 풀기
  • 딥다이브 발표 준비하기

0개의 댓글