12주 2일차 - 웹 접근성, 서버 복습
1. 배운 것
- jsx 내에서 label태그의 for 속성은 htmlFor 로 써야 한다. for는 반복문이라서.
- 몽고디비 콜렉션, 모델, 스키마
- 클라이언트의 수정내용을 서버에도 반영하려면 build 다시 해준다.
- drop database가 안되는 경우 권한 설정 문제이다. 몽고디비 아틀라스 홈페이지에서 security 탭으로 가서 권한 변경하기.
2. 내용 정리
useEffect 복습
어떠한 상태(state)의 값이 바뀌었을때 동작할 함수를 작성할 수 있다.
- 첫번째 인자 콜백함수: 가장 처음에 앱이 실행될 때의 첫 렌더링 또는 state변경 후 재렌더링 종료시 실행됨.
- 두번째 인자 Dependency Array: 의존성 배열이다. 첫번째 매개변수인 함수가 두번째 매개변수인 의존성 배열의 값이 변경될 때만 실행되게 제한함. 생략 가능하며 생략시 모든 렌더링 때마다 함수가 실행됨.
- 의존성 배열이 빈 배열이면 함수를 최초 렌더링 시 1번만 실행.
Axios 방식 CORS 이슈 해결 - 1. 클라이언트
// client > src > component > List.js
import React, { useState, useEffect } from 'react';
import styled from 'styled-components';
import axios from 'axios';
const StyledList = styled.ul`
> li {
list-style: none;
margin-bottom: 10px;
border-bottom: 0.5px solid #6f6f6f;
}
`;
const List = ({ contentList }) => {
useEffect(() => {
axios
.post('/api/test')
.then(response => {
// 성공 핸들링
alert('요청 성공');
console.log(response);
})
.catch(error => {
// 에러 핸들링
alert('요청 실패');
console.log(error);
});
}, []);
return (
<>
{contentList.length !== 0 ? (
<StyledList>
{contentList.map((el, idx) => (
<li key={idx}>제목:{el}</li>
))}
</StyledList>
) : null}
</>
);
};
export default List;
- 경로를 client 폴더로 하여 axios 설치.
- Component > List.js
- 비동기 코드 처리를 위해 useEffect import하기
- axios도 import 하기
- 함수 컴포넌트 리턴문 이전에 useEffect 함수 넣기
- useEffect 콜백함수 내부에서 axios post 요청 코드 넣기
- 프록시 설정 (참고 https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually)
// client > src > setupProxy.js 새 파일 생성
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: '<http://localhost:5000>',
changeOrigin: true,
})
);
};
404 오류 : 클라이언트랑 서버의 포트 번호가 달라서 발생. 프록시 설정으로 해결한다.
Axios 방식 CORS 이슈 해결 - 2. 서버
클라이언트의 post요청을 처리할 코드를 추가.
app.post('/api/test', (req, res) => {
console.log(req);
res.status(200).json({ success: true });
});
서버에서 응답으로 보내는 json데이터를 클라이언트에서 받기
- 클라이언트에서 접근하는 방법: response.data.프로퍼티key
- 서버에서 보내는 방법: res.status(200).json({ key: value })
서버 코드
// 서버 코드에서 응답으로 보내는 json객체의 데이터 클라이언트에서 받기
// response.data.success = true
// response.data.text = 'hi'
// 1. 서버 코드
app.post('/api/test', (req, res) => {
// console.log(req);
res.status(200).json({ success: true, text: 'hi' });
});
클라이언트 코드
// 2. 클라이언트 코드
// useEffect 훅 내부에서 state를 서버의 응답 데이터 값으로 변경.
const List = ({ contentList }) => {
const [text, setText] = useState('');
useEffect(() => {
axios
.post('/api/test')
.then(response => {
// 성공 핸들링
alert('요청 성공');
setText(response.data.text);
})
.catch(error => {
// 에러 핸들링
alert('요청 실패');
console.log(error);
});
}, []);
return (
<>
<h3>{text}</h3>
{contentList.length !== 0 ? (
<StyledList>
{contentList.map((el, idx) => (
<li key={idx}>제목:{el}</li>
))}
</StyledList>
) : null}
</>
);
};
클라이언트에서 서버로 데이터 보내기
const body = {
author: 'Ryan',
}; // 서버로 보낼 데이터인 body 객체 생성
useEffect(() => {
axios
.post('/api/test', body) // post의 2번째 인수로 보냄.
.then(response => {
// 성공 핸들링
alert('요청 성공');
setText(response.data.text);
})
.catch(error => {
// 에러 핸들링
alert('요청 실패');
console.log(error);
});
}, []);
- 클라이언트
- 서버로 보낼 key-value를 가진 객체를 생성.
- post요청 2번째 인수로 해당 객체를 넣는다.
// server > index.js
// 클라이언트에서 보낸 데이터를 파싱하기 위해 사용하는 2가지 코드
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 클라이언트에서 보낸 데이터에 접근하기
app.post('/api/test', (req, res) => {
console.log(req.body.author);
res.status(200).json({ success: true, text: 'hi' });
});
- 서버
- 클라이언트에서 보낸 요청을 바디파서로 파싱해서 받아와야 함. (설치 필요 x)
- req.body.key값 으로 접근
Mongoose Model
참고 https://mongoosejs.com/docs/index.html
- Model : 스키마를 감싸주어 해당 스키마를 쓸 수 있게 해주는게 Model.
- Schema : 저장될 데이터의 형태를 정의한다.
- Collection : 같은 성격의 데이터들이 묶인 모둠을 말한다.
MongoDB는 NoSQL이므로 SQL보다는 더 자유롭게 데이터를 저장할 수 있지만 그렇다고 아무런 규칙이 없는 것은 아니다.
MongoDB에서는 같은 성격의 데이터를 Collection 으로 묶어주어야 한다. 예를 들어 유저 정보는 user 콜렉션에, 글 정보는 post 콜렉션에 담아두는 등의 방식으로 묶는다.
server 폴더에 Model 들을 관리할 Model 폴더를 만들고 Collection 별로 묶을 모델과 스키마를 정의한 파일을 만들고 모듈로 export.
express 서버를 만든 index.js에서 이 모듈을 import 해온다.
// server > Model > Post.js
const mongoose = require('mongoose');
// 1. 스키마의 내부에 저장될 데이터의 형태를 정의. (생성자 함수)
const postSchema = new mongoose.Schema({
title: String,
content: String,
});
// 2. 모델을 선언.
const Post = mongoose.model('Post', postSchema);
// 3. 모듈 export.
module.exports = { Post };
DB에 데이터 넣기 - 모델 import & 인스턴스 생성
// 4. 정의한 모델을 import 해오기
// server > index.js
// ... 생략
const { post } = require('./Model/Post');
// ... 생략
// 5. post 요청 시 인스턴스 생성.
app.post('/api/test', (req, res) => {
const communityPost = new Post({
title: '글제목이다',
content: '글내용이다',
},
{ collection: 'posts' } // 콜렉션 지정
);
communityPost.save(); // .save() 없으면 db로 데이터 안넘어옴!!
res.status(200).json({ success: true, text: 'hi' });
});
이제 post 요청이 오면 db로 스키마에서 정의한 데이터 형식으로 지정한 콜렉션에 데이터가 들어온다.
db 이름 바꾸는 법 : mongoURI에서 mongodb.net/ 뒤에서 ?retryWrites=true 사이에 db 이름을 넣는다. 미기재시 test 란 이름으로 db 생성됨.
줌 세션
웹 표준만 잘 지켜도 크로스 브라우징이나 seo, 웹 접근성은 어느정도 갖춰지기 때문에 웹 표준을 지켜서 개발해야 한다.
WAI-ARIA는 어디까지나 보조적인 역할이다. 꼭 필요한 경우에만 사용한다. 시멘택한 태그 사용으로 해결할 수 있는 경우엔 태그 사용만으로 해결하고 그 외에 보조적인 설명이 필요할 때 사용한다.
material-ui, chakra-ui 등 ui 라이브러리의 예시에서 WAI-ARIA 사용 방법을 참고하면 좋다.
background가 이미지인 button 요소의 경우 스크린리더에서 이미지의 의미 전달을 위해 WAI-ARIA의 aria-label 속성을 써줄 수 있다.
더 공부할 내용
- useEffect 안의 코드가 2번 실행되는 경우에 index.js에서 React.StrictMode 컴포넌트를 지우면 해결되는 이유?
- useEffect의 dependency array 문제. 단순히 린터를 끄면 될 문제인지? https://bobbyhadz.com/blog/react-hook-useeffect-has-missing-dependency
3. 리뷰
마냥 왕초보 던전에서 머물것만 같았는데 어느덧 부트캠프가 점점 끝이 다가오는게 느껴진다. 섹션2를 마치면서는 불안감에 압도당해서 어찌할 줄 몰라했는데 팀프로젝트가 다가온다는 압박감은 오히려 줄어든 것 같다.
서버 코드는 아무리 봐도 적응이 안된다. 계속 보면 나아지겠지만 지금은 어렵다.
'기록 > 코드스테이츠 프론트엔드' 카테고리의 다른 글
12주 4일차 - Auth Basic (0) | 2022.07.15 |
---|---|
12주 3일차 - 네트워크, CRUD, Authentication (0) | 2022.07.13 |
12주 1일차 - 데일리코딩 뜯어보기 (0) | 2022.07.11 |
11주차 마무리 - 힐링 (0) | 2022.07.10 |
11주차 토요일 (0) | 2022.07.09 |