bluegram - 7일차

박상은·2021년 12월 19일
0

🍃 blegram

목록 보기
11/20

1. 프론트 환경변수 설정

여기를 참고해서 dotenv-webpack 플러그인을 적용시켰습니다.

  • 주의할 점은 프론트 .env파일 수정 시 변경사항을 적용하려면 프론트 서버를 재시작해야 합니다.

2. AppLayout

모든 페이지가 화면에 렌더링 되기 전에 AppLayout.jsx를 거쳐서 렌더링 되도록 만들고 AppLayout.jsx에서는 공통 레이아웃을 적용시켰습니다.

이로써 각 페이지마다 NavigationBar를 적용시킬 필요 없으며, 수정할 때도 AppLayout.jsx만 변경시켜도 되므로 유지 보수에도 더욱 이점이 있도록 설계했습니다.

import React from "react";

// components
import NavigationBar from "@components/NavigationBar";

// styled-components
import { Wrapper, MainContainer } from "./style";

const AppLayout = ({ children }) => {
  return (
    <Wrapper>
      <NavigationBar />

      // children에 각 페이지에 대한 값(jsx)이 들어온다.
      <MainContainer>{children}</MainContainer>
    </Wrapper>
  );
};

export default AppLayout;

3. 로그인 / 회원가입 페이지

로그인과 회원가입 페이지에서 공통적으로 사용하는 컴포넌트들을 추출해서 작은 단위의 컴포넌트로 만들어서 재사용하는 방식으로 구현했습니다.

재사용 컴포넌트들이 많아서 그 중에 하나만 예시로 가져왔습니다.

제 기준으로 재사용 컴포넌트들은 반드시 사이드이펙트 없는 순수한 컴포넌트로 만들고, PropTypes를 이용해서 전달될 props의 타입들에 대한 유효성 검사를 실시합니다.

import React from "react";
import Proptypes from "prop-types";

// styled-components
import { Wrapper } from "./style";

const Input = props => {
  return <Wrapper {...props} />;
};

Input.propTypes = {
  type: Proptypes.string.isRequired,
  placeholder: Proptypes.string,
  maxLength: Proptypes.number,
  value: Proptypes.oneOfType([Proptypes.string, Proptypes.number]).isRequired,
  onChange: Proptypes.func.isRequired,
};

export default Input;

4. styled-components 적용

styled-components를 사용하여 css-in-js 방식으로 스타일을 적용했습니다.

하나의 파일에서 styled-components를 적용해서 스타일이 적용된 컴포넌트를 만들 수 있지만 해당 파일의 라인수가 너무 커지기 때문에 스타일과 컴포넌트에 대한 코드는 분리해서 적용했습니다.

/components/common/Button/index.jsx/components/common/Button/style.js로 폴더를 이용해서 분리 적용했습니다.

import styled from "styled-components";

export const Wrapper = styled.input`
  &[type="text"],
  &[type="password"] {
    width: 60%;
    padding: 0.5rem;
    font-size: 1rem;
    font-weight: 500;
    border: 1px solid purple;
    margin-bottom: 0.3rem;
  }

  &[type="file"] {
    display: none;
  }

  &:focus {
    box-shadow: 0 0 3px purple;
  }

  &::placeholder {
    font-size: 0.7rem;
    color: rgba(128, 0, 128, 0.5); // purple
  }
`;

4. 이미지 처리 방식

현재 프로젝트에서 이미지 처리의 방식은 사용자가 이미지를 올리는 즉시 서버로 이미지를 전송해서 저장하고, 저장한 이미지의 이름을 다시 클라이언트로 전송해서 그 이름을 이용해서 프리뷰를 보여주고, 다음 요청에 이미지 이름을 전달하는 방식으로 구현했습니다.

  • 이미지 처리 순서 ( 회원가입 기준으로 설명 )
    1. 브라우저에 이미지 올림
    2. 서버로 바로 전송
    3. 서버에서 처리 후 이미지 이름만 반환
    4. 해당 이름으로 preview 보여줌
    5. 해당 이름을 다음 응답에 첨부해서 보내줌
    6. 생성된 유저 아이디와 이미지 이름로 Image테이블에 추가

기본적으로 클라이언트에서 서버로 이미지를 전송할 땐 multipart/form-data형식으로 전송해줬으며, 서버측에서는 multer를 이용해서 이미지를 서버의 public폴더에 저장합니다. ( 추후에는 이미지를 저장하는 위치를 바꿀 예정... 서버에 부담이 심하다고 판단됨 )

import path from "path";
import express from "express";
import multer from "multer";

const __dirname = path.resolve();
const router = express.Router();

const storage = multer.diskStorage({
  destination(req, file, done){
    done(null, path.join(__dirname, "public", "images"));
  },
  filename(req, file, done){
    const ext = path.extname(file.originalname);
    const basename = path.basename(file.originalname, ext);
    
    const filename = basename + "-" + new Date().getTime() + ext;

    done(null, filename);
  }
});
const limits = { fileSize: 20 * 1024 * 1024 };

const upload = multer({ storage, limits });

router.post("/", upload.array("images"), (req, res) => {
  const filenames = req.files.map(file => file.filename);

  res.status(201).json({ message: "이미지 생성에 성공하셨습니다.", images: filenames })
});

export default router;

마무리

1. 어렵거나 힘들었던 점

  1. cors 문제 발생
  2. react-router-dom 버전 업데이트
  3. http status code
  4. 아이콘 제작

2. 해결

2.1 cors

  • credentials: true를 준 이유는 passport가 자체적으로 세션쿠키를 사용하기 때문에 브라우저에서 쿠키를 전송해줘야 하기 때문입니다.
    물론 클라이언트측에서도 axios의 설정으로 withCredentials: true를 줘서 서버로 쿠키를 전송하도록 설정했습니다.
  • 추가적으로 credentials: true인 경우에는 origin: *를 주면 보안상의 문제로 오류가 나기 때문에 클라이언트의 주소를 명시했습니다.
// app.js에 아래 내용 추가
import cors from "cors";

app.use(cors({
  credentials: true,
  origin: process.env.CLENT_URL
}));

react-router-dom가 v6으로 업데이트되면서 NavLink의 사용법이 달라져서 activeStyle을 적용하지 못한 상태여서 추후에 적용할 예정입니다.

2.3 http status 204

http status 204일 경우에는 응답 데이터가 전송되지 않아서 기존에 204를 사용하던 응답을 모두 200으로 변경했습니다.

2.4 아이콘 제작

현재 프로젝트에서 사용하는 모든 아이콘은 어도비 일러스트를 이용해서 직접 제작해서 사용하고 있습니다.

0개의 댓글