FE RYAN
완벽하지 않으면 어때
FE RYAN
전체 방문자
오늘
어제

블로그 메뉴

  • 💾 깃허브 링크
  • 홈
  • 태그
  • 분류 전체보기 (151)
    • 개인프로젝트 (8)
      • 개인 포트폴리오 웹앱 (6)
      • 프론트엔드 기술면접 아카이빙 웹앱 (2)
    • 기록 (121)
      • 원티드 프리온보딩 인턴십 (0)
      • 코드스테이츠 프론트엔드 (75)
      • 생각들 (3)
      • Today I learned (32)
      • 회고 (9)
      • 리뷰 (1)
    • 개발 (17)
      • React (3)
      • Javascript (7)
      • CSS (1)
      • HTML (3)
      • HTTP (1)
      • 자료구조 (0)
      • 알고리즘 (2)
    • 코딩테스트 (2)
      • 백준 (2)
      • 프로그래머스 (0)
    • 디자인 (1)
      • UI & UX (1)
    • 수학 (0)
    • 자기계발 (0)

공지사항

인기 글

태그

  • 자바스크립트
  • 프론트엔드
  • 타입스크립트
  • 딥다이브
  • useMemo
  • 메인프로젝트
  • HTML
  • 리액트
  • 부트캠프
  • 코드스테이츠
  • seb 39
  • ES6
  • css
  • Til
  • 신입개발자
  • 자바스크립트 딥다이브
  • 원시타입
  • 회고
  • 포트폴리오
  • seb39

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
FE RYAN

완벽하지 않으면 어때

기록/코드스테이츠 프론트엔드

12주 3일차 - 네트워크, CRUD, Authentication

2022. 7. 13. 23:38
728x90

12주 3일차 - 네트워크, CRUD, Authentication

1. 배운 것

  • useEffect의 종속성 배열 복습
  • 서버 api 구현방법 복습

2. 내용 정리

네트워크 체크리스트

Chapter1. TCP/IP

  • 패킷교환 방식의 이점에 대해 이해한다.
  • IP의 비순서성, 비신뢰성에 대해 이해한다.
  • TCP의 3 way handshake 및 그와 비교되는 UDP에 대해 이해한다.

Chapter2. 네트워크 계층 모델

  • 네트워크 통신을 계층별로 나눈 이유에 대해 이해한다.
  • 통신 과정에서 일어나는 데이터 캡슐화에 대해 이해한다.

Chapter3. HTTP

  • HTTP 메세지 구조를 이해한다.
  • HTTP의 무상태성과 비연결성에 대해 이해한다.
  • HTTP 헤더 중 바디를 설명하는 헤더인 표현헤더에 대해 이해한다.
  • HTTP 헤더 중 요청과 응답에서 주로 사용되는 헤더에 대해 이해한다.
  • HTTP 헤더 중 서버에 요청하는 컨텐츠를 협상할 수 있는 협상헤더에 대해 이해한다.

Chapter4. Web Cache

  • 웹 캐시의 필요성에 대해 이해한다.
  • Cache-Control: max-age=60이 어떤 의미인지 이해한다.
  • 요청에서 사용하는 If-Modified-Sinse 헤더와 응답에서 사용하는 Last-Modified 헤더에 대해 이해한다.
  • 요청에서 사용하는 If-None-Match헤더와 응답에서 사용하는 Etag 헤더에 대해 이해한다.
  • 프록시 서버의 필요성에 대해 이해한다.
  • 프라이빗 캐시와 프록시 캐시의 차이에 대해 이해한다.
  • Cache-Control 헤더의 값인 no-cache와 must-revalidate의 차이에 대해 이해한다.

웹 프론트엔드 개발자가 알아야할 최소한의 백엔드 지식과 코드 (API)

유튜버 라매개발자님의 동일한 제목의 유튜브 강의 영상을 공부하며 정리한 내용입니다.

웹 앱의 동작과정 - 게시판 예시

const express = require('express');
const app = express();

// 더미데이터
const database = [
  { id: 1, title: '글1' },
  { id: 2, title: '글2' },
  { id: 3, title: '글3' },
];

app.get('/', (req, res) => {
  // sendFile 말고 render 메서드로도 페이지를 보낼 수 있다. (ejs, pug 검색)
  res.sendFile(__dirname + '/views/index.html');
});

app.get('/database', (req, res) => {
  res.send(database);
});

app.listen(3000, () => console.log('server on'));
  1. GET: 서버의 db에 저장된 게시글들을 화면에서 보기 위해 클라이언트가 서버에게 db에 저장된 게시글을 요청하는 api를 호출한다.
  2. 서버가 클라이언트의 요청을 받아 db에서 데이터를 가져와 클라이언트로 응답을 보낸다.
  3. POST: 클라이언트가 서버에게 게시글의 제목 또는 내용을 수정해달라는 api를 호출한다.
  4. 서버는 수정된 내용을 db에 저장하고 수정이 정상적으로 끝났다는 응답을 클라이언트로 보낸다.
  5. 추가, 삭제 등도 클라이언트가 서버에게 요청하고 서버가 요청을 처리하고 응답을 보낸다.

값 추가 - 방법 1 : req.params (거의 안쓰는 방법이다)

get 요청 응답 코드

// 더미 db
const database = [
  { id: 1, title: '글1' },
  { id: 2, title: '글2' },
  { id: 3, title: '글3' },
];

app.get('/', (req, res) => {
  // sendFile 말고 render 메서드로도 페이지를 보낼 수 있다. (ejs, pug 검색)
  res.sendFile(__dirname + '/views/index.html');
});

app.get('/database', (req, res) => {
  res.send(database); // 응답
});

app.get('/database/:title', (req, res) => {
  const title = req.params.title;
  database.push({
    id: database.length + 1,
    title, // title: req.params.title
  }); // db에 데이터 추가
  res.send('값 추가 성공');
});

값 추가 방법 2 : req.body (주로 쓰이는 방법)

bodyParser 필요.

// bodyParser 사용하기
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

post요청 응답 코드

app.post('/add-database', (req, res) => {
  const title = req.body.title;
  database.push({
    id: database.length + 1,
    title, // title: req.body.title
  });
  res.send('값 추가 성공. 바디파서 사용해서 req.body 받기.');
});

특정한 값만 가져오기(get) - req.params

받아온 req.params는 문자열임에 유의한다.

// * GET: 요청한 특정 값만 보내기
app.get('/database/:id', (req, res) => {
  const id = req.params.id; // req.params는 문자열이다.
  const data = database.filter(el => el.id === Number(id));
  // filter 메서드 대신 find 메서드를 써도 됨.
  res.send(data);
});

값 수정하기(PUT)

어떤 글을 수정할지 id로 해당 글을 특정하는 예시.
서버가 클라이언트에게서 수정하고 싶은 값을 받아와야 한다.

// * PUT: 값 수정하기
app.put('/database', (req, res) => {
  const id = req.body.id;
  const title = req.body.title;

  database[id - 1].title = title;

  res.send('값 수정 완료.');
});

값 삭제하기(DELETE)

해당하는 id의 데이터를 삭제하는 예시.

// * DELETE: 값 삭제하기
app.delete('/database', (req, res) => {
  const id = req.body.id;

  database.splice(id - 1, 1);

  res.send('값 삭제 완료.');
});

같거나 비슷한 곳의 데이터를 조작할 때 url을 일치시키고 HTTP 메서드를 용도에 맞게 각각 사용하여 RESTful한 api를 만들 수 있다. post, put, delete 모두 url은 /database 로 동일하게 작성하였음.

참고자료

  • 웹 프론트엔드 개발자가 알아야할 최소한의 백엔드 지식과 코드 (API) https://www.youtube.com/watch?v=uIWl19relcc&t=1338s

웹 프론트엔드 개발자가 알아야할 최소한의 백엔드 지식과 코드 (user) → 회원가입, 로그인, 에러처리

유튜버 라매개발자님의 동일한 제목의 유튜브 강의 영상을 공부하며 정리한 내용입니다.

1. 회원가입 api 만들기

const database = [{ id: 1, username: 'abc', password: 'abc' }];

// * 회원가입 api 만들기
app.post('/signup', (req, res) => {
  const { username, password, age, birthday } = req.body;
  database.push({
    username,
    password,
    age,
    birthday,
  });
  res.send('회원가입 성공');
});

로그인 api 만들기

유저가 입력한 값으로 db를 filter하였을때 해당 정보가 없다면 length가 0이고 아이디는 일치하지만 비밀번호가 틀릴 경우도 입력값과 db에 저장된 값과 비교하여 조건분기 할 수 있다. if문 둘 다 해당되지 않으면 마지막에 응답으로 로그인 성공을 보낸다.

// * 로그인 api 만들기
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  const user = database.filter(user => user.username === username);
  if (user.length === 0) {
    return res.send('등록되지 않은 id입니다.');
  }
  if (user[0].password !== password) {
    return res.send('비밀번호가 틀립니다.');
  }
  res.send('로그인 성공.');
});

주의 : 유저의 비밀번호를 평문으로 저장하면 안된다. 반드시 암호화하여 저장해야 한다.

비밀번호 암호화하기

argon2 라이브러리로 간단하게 비밀번호를 해싱하여 암호화를 적용해줄 수 있다.

// * 회원가입 api 만들기 + 비밀번호 암호화 적용하기
app.post('/signup', async (req, res) => {
  const { username, password, age, birthday } = req.body;
  const hash = await argon2.hash(password);
  database.push({
    username,
    password: hash,
    age,
    birthday,
  });
  res.send('회원가입 성공');
});

// 데이터베이스에 비밀번호가 암호화되어 저장된걸 확인할 수 있다.
/*
{
        "username": "abcd",
        "password": "$argon2id$v=19$m=4096,t=3,p=1$VFzuRA7IxXQF2mV8xsX5jA$OtDJ+M/I+URmCfND6jCBdkN0bHPfUNmTl4NQVet84jc",
        "age": "10",
        "birthday": "12.11"
    }
*/

암호화된 비밀번호와 일치 여부를 로그인시 검증하기

argon2 라이브러리 사용 시 verify 메서드로 검증 가능.
id나 비밀번호가 일치하지 않을 경우 응답의 상태코드는 403번으로 보냄.

// * 로그인 api 만들기 + 비밀번호 검증
app.post('/login', async (req, res) => {
  const { username, password } = req.body;
  const user = database.filter(user => user.username === username);
  if (user.length === 0) {
    return res.status(403).send('등록되지 않은 사용자입니다.');
  }
  if (!(await argon2.verify(user[0].password, password))) {
    return res.status(403).send('비밀번호가 틀립니다.');
  }
  res.send('로그인 성공.');
});

useEffect의 dependency array 복습 - 조건부 effect 발생

의존성 배열이 생략된 경우, 빈 배열인 경우, 종속성 값이 의존성 배열에 존재하는 경우에 따라 콜백함수가 언제 실행되는지 알고 있어야 한다.

  1. 의존성 배열 생략: 모든 렌더링(컴포넌트 최초 생성, state 변경) 발생 시 콜백함수 실행
  2. 빈 배열: 최초 렌더링 시 1회만 콜백함수 실행 예시: → 최초 외부 API의 리소스를 받아오고 더 이상 API 호출이 필요하지 않을 경우 사용.
  3. 종속성 요소 존재: 해당 요소의 값이 변할 때 콜백함수 실행

Create: 게시글 생성하기, useNavigate

판다코딩님 인프런 MERN스택 강의 내용으로 공부 내용을 정리한 부분입니다.

게시판 업로드 폼 같은 경우 제목, 본문 등 다양한 유저의 인풋값 마다 핸들러 함수를 정의할 필요 없이 onChange 이벤트의 콜백함수를 익명함수로 정의하면서 각각의 내용에 맞는 state 변경함수를 내부에서 실행시키면 된다.

클라이언트 - Upload.js (글 작성 페이지)

const Upload = props => {
  // useNavigate 사용
  let navigate = useNavigate();

  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');

  const onSubmit = e => {
    e.preventDefault();
    if (title === '' || content === '') return alert('모든 항목을 채워주세요');

    let body = {
      title,
      content,
    };
    axios
      .post('/api/post/submit', body)
      .then(response => {
        if (response.data.success) {
          alert('포스팅 성공! 홈으로 돌아갑니다.(useNavigate)');
          navigate('/');
        } else {
          return alert('포스팅 실패');
        }
      })
      .catch(err => console.log(err));
  };
  1. 제목, 내용의 state를 각각 생성.
  2. 입력창에서 onChange 이벤트 발생 시의 핸들러함수를 익명함수로 정의하면서 제목, 내용을 입력값(e.currentTarget.value)으로 setState.
  3. axios import 하여 제출버튼 클릭시 실행되는 핸들러함수에서 post 요청 보내기.
    1. db로 보낼 데이터인 새 객체를 생성하고 내용은 제목과 내용의 state로.
    2. axios.post 하면서 url, 객체 2가지를 인수로 보내고
    3. 이어받아서 프로미스 체이닝(1. then: 성공시 동작, 2. catch: 에러 핸들링) 한다.
  4. 제출버튼 클릭시 핸들러함수에서 preventDefault 시킬 것. 작성한 axios 코드가 실행되지 않고 페이지가 새로고침되는 것을 방지해야 함.
  5. react-router-dom의 useNavigate를 사용하여 글 업로드 완료 시 홈 디렉토리( ‘ / ’ )로 이동시키기.

서버 - index.js

app.post('/api/post/submit', (req, res) => {
  let temp = req.body;

  const communityPost = new Post(temp);
  // .save() 없으면 db로 데이터 안넘어옴!!
  communityPost
    .save()
    .then(() => {
      res.status(200).json({ success: true, text: 'hi' });
    })
    .catch(err => {
      res.status(400).json({ success: false });
    });
});

post 요청시의 경로를 클라이언트의 Upload.js에서 post요청한 경로와 같게 수정하였다.


더 공부할 내용

  • 인증

3. 리뷰

3.1 좋았던 점

3.2 아쉬웠던 점

  • 인증 공부하려고 한건데 지난 과정들에서 기억이 나지 않는 부분들과 인증 이전에 알아야 할 것들만 보다가 하루가 다 가버렸다.
  • 유어클래스 이론 내용으로만 가득찬 날들은 도저히 내용이 머리에 들어오지가 않는다.
  • 들어는 봤고 나중에 보충하잔 식으론 난 공부 못하겠는데.

3.3 notes

보이는 라디오는 회고날 같은때나 좀 집어넣었으면 좋겠다. 취지야 좋은데 선참시든 그룹 회고든 이런 세션들은 좀 뻔히 다음 과제가 미친듯이 어려울게 보이는데 흐름 끊는 위치에 넣는건 좀 아닌것 같다.

728x90
저작자표시 비영리 변경금지 (새창열림)

'기록 > 코드스테이츠 프론트엔드' 카테고리의 다른 글

13주차 - 반응형 웹 제출 과제  (0) 2022.07.22
12주 4일차 - Auth Basic  (0) 2022.07.15
12주 2일차 - 웹 접근성, 서버 복습  (0) 2022.07.12
12주 1일차 - 데일리코딩 뜯어보기  (0) 2022.07.11
11주차 마무리 - 힐링  (0) 2022.07.10
    '기록/코드스테이츠 프론트엔드' 카테고리의 다른 글
    • 13주차 - 반응형 웹 제출 과제
    • 12주 4일차 - Auth Basic
    • 12주 2일차 - 웹 접근성, 서버 복습
    • 12주 1일차 - 데일리코딩 뜯어보기
    FE RYAN
    FE RYAN

    티스토리툴바