Instagram Clone - react, scss(1)

seul_velog·2022년 5월 10일
0

✍️ html과 css, javascript로 westagram을 clone코딩한 뒤 react로 변환, 추가 하면서 작성한 내용들


1. 기존코드 React로 옮기기

// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import Main from './Pages/Main/Main';
import Login from './Pages/Login/Login';

const root = ReactDOM.createRoot(document.getElementById('root'));
// root 에 접근해서 아래를 그려주겠다.
root.render(
  <React.StrictMode>
    {/* <App /> */}
    {/* <Login /> */}
    <Main />
  </React.StrictMode>
);


// Login 컴포넌트
import React from 'react';
import './Login.css';

const Login = (props) => {
  return (
    <div>
      <div className='login'>
        <main className='login__container'>
          <h1 className='login__logo'>westagram</h1>
          <form className='login__form' action='./main.html'>
            <input
              type='text'
              className='login__input-id'
              placeholder='전화번호, 사용자 이름 또는 이메일'
            />
            <input
              type='password'
              className='login__input-pw'
              placeholder='비밀번호'
            />
            <button className='login__btn' disabled>
              로그인
            </button>
          </form>
          <div className='message'>
            <a href='#'>비밀번호를 잊으셨나요?</a>
          </div>
        </main>
      </div>
    </div>
  );
};

export default Login;


// main 컴포넌트
import React from 'react';
import './Main.css';
import { AiFillHeart, AiOutlineHeart } from 'react-icons/ai';
import { CgRemove } from 'react-icons/cg';

const Main = (props) => {
  return (
    <div>
		...
    </div>
  );
};

export default Main;

기본 설정

  • CRA 프로젝트를 설치
  • src 폴더 안에 > pages 폴더 > Login 폴더, Main 폴더를 생성한다.
  • Login 폴더와 Main 폴더 내부에 각각의 기존 html파일을 react 컴포넌트로 변환한다.
  • index.js 파일에서 Main 컴포넌트와 Login 컴포넌트를 render 하기 위해서 import해온다.
  • images 파일은 public 파일에 생성해서 가져오도록 하자. 여기서 public은 배포시 root 경로와 같고 따라서 'public'은 생략할 수 있다.

CSS 설정

  • 각각의 컴포넌트 내부에서 css파일 경로를 잘 확인해서 가져오자. 이렇게 되면 UI가 틀어지는데, 하나씩 체크해보자. 😀

  • 폰트어썸에서 가져온 폰트 설정은 url을 import 해줌으로써 해결 할 수 있었다.

    @import url('https://fonts.googleapis.com/css2?family=Lobster&display=swap');
  • 이미지 파일의 경우 경로를 다시 확인 하고 public 파일의 특징만 알면 쉽게 해결할 수 있다.

  • 외부에서 가져온 아이콘 파일의 경우 script 파일을 html에 넣어주거나 관련된 라이브러리를 설치해 주는 방법으로 해결할 수 있었다.

  • 아이콘 파일은 원래 구글폰트아이콘에서 가져와 사용했었는데, 구글링을 하면서 react-icons 사이트를 알게되어 이 페이지의 아이콘으로 교체를 해보았다.

    npm install react-icons --save
    import { AiFillHeart, AiOutlineHeart } from 'react-icons/ai';
    
      <AiOutlineHeart className='article-data__icons-heart' />
      <AiFillHeart className='article-data__icons-heart fill' />
  • 먼저 install을 하고 설명에 따라 import를 해와서 사용한다.

  • 이때 'react-icons/ai' 에서 ai 부분이 해당 아이콘의 타입인 것 같았다. 다른 타입의 아이콘을 사용할때 그 타입형식에 맞는 문자를 넣어주지 않으면 작동하지 않았다. 더 사용해 보면서 알아가보자. 🤔

📌 css 에서 사용한 background-image은 어떻게 연결시킬까?

  • css에서는 public 폴더에 접근하는게 불가능하므로 background-image 에 활용해야하는 이미지들은 src/assets/images/ 디렉토리에서 관리했다.
    이에 맞춰서 css에서 사용중인 background-image의 경로도 알맞게 설정해주자.



2. Router 컴포넌트 구현하기

📌 라우팅(Routing)이란 다른 경로(url 주소)에 따라 다른 View(화면)를 보여주는 것이다.

  • 라우터 설치
    npm install react-router-dom --save
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import Router from './Router';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Router />
  </React.StrictMode>
);
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

import Login from './pages/Login/Login';
import Main from './pages/Main/Main';

const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path='/' element={<Login />} />
        <Route path='/main' element={<Main />} />
      </Routes>
    </BrowserRouter>
  );
};

export default Router;
  • 화면에 render될 최상위 컴포넌트를 설정하고 해당 컴포넌트 내부에서 써드파티라이브러리인 router를 사용한다.
  • BrowserRouter 컴포넌트를 읽게되면 그 아래에 라우트 기능들을 활용할 수 있도록 해준다.
  • RoutesRoute 를 모아두고, Route 는 실제 페이지를 이동시킨다.

✍️ Link태 컴포넌트와 a 태그의 차이

  • <a> 는 외부링크 이동
  • <Link> 는 페이지내부에서 컴포넌트 전환이 필요할 때



3. useNavigate 사용하기

const Login = () => {
  const navigate = useNavigate(); // 1)

  const goToMain = () => {
    navigate('/main');
  };

  return (
    <div className='login-page'>
      <div className='login'>
        <main className='login__container'>
          <h1 className='login__logo'>westagram</h1>
          <form className='login__form' action='./main.html'>
            <input
              type='text'
              className='login__input-id'
              placeholder='전화번호, 사용자 이름 또는 이메일'
            />
            <input
              type='password'
              className='login__input-pw'
              placeholder='비밀번호'
            />
            <button className='login__btn' onClick={goToMain}> // 2)
              로그인
            </button>
          </form>
          <div className='message'>
            <a href='#'>비밀번호를 잊으셨나요?</a>
          </div>
        </main>
      </div>
    </div>
  );
};
  • 1) naviate 는 페이지를 이동하게 하는 함수를 나타낸다. 인자로는 경로를 넣을 수 있다. 페이지 전환 시 추가로 처리해야 하는 로직이 있는경우 활용할 수 있다. (조건문 필요한 상황 등)
  • 2) 버튼에 onClick 함수를 넣어주고 goToMain 함수의 navigate 경로로 이동시켜 줄 수 있도록 한다.



4. scss로 nesting 하기

  • 여러 css 파일이 합쳐지면서 덮어쓰는 것을 방지하기 위해 scss에서 nesting을 해준다.

✍️ memo
나는 처음 작성 방식이 BEM 이었으므로 scss로 변환했을 때 css 파일이 망가지는 일 없이 바로 변환이 되었다. 🤔

BEM 자체가 앞서 말했던 css 파일들을 합쳤을 때 발생하는 문제점을 해결하기 위한 방법으로써 사용된 css 방법론이기 때문에 당연한 것이며, 추후에는 굳이 BEM 방식을 사용하지 않고 scss nesting 을 활용해서 간단하고 가독성 좋게 작성해야 겠다고 생각했다.

또한 css 속성을 부여할 때 일반 태그(ex. div, p ...)는 가장 지양해야 하고 최대한 그 요소에 맞는 className을 부여해서 사용하는 것이 좋다고 한다. 같은 부모 요소 아래에 자식 요소들이 복잡해졌을 때 div 태그와 같이 일반 태그명에 속성을 준다면, 추후 여러군데 중복적으로 사용된 태그 사이에서 충돌을 발생시킬 수 있기 때문이라고 이해했다.😀

profile
기억보단 기록을 ✨

0개의 댓글