
1. twitter 예제 refactoring 사전작업
1. Client 기본파일을 다운로드
(Twitter의 기능이 있는 client 기본파일)
2. Client가 있는 디렉토리에 Server 폴더 생성
index.js 파일 생성/작성 후 폴더 내부에 controller, data, router 폴더 추가 생성.
가능하다면 nodemon 툴, gitignore 파일도 생성.
3. server와 client 폴더 내 node.js 설치
1. cd C:\yjcho\Node.js\project\server 로 경로 변경.
2. npm audit fix --force // 보안 취약점을 수정해주는 코드
3. npm audit fix -force
4. npm i (node_modules의 복원).
5. npm start
아래와 같이 트위터형식의 기본적인 프로그램이 localhost에서 실행됨.
사용 경로: C:\yjcho\Node.js\Project_test\Server\index.js
전체 화면을 렌더링해주는 기능. 아래 내용 작성.
server단에서 이용되는 모듈들의 설치도 잊지말고 해주어야 함.
import express from "express"; import cors from "cors"; import morgan from "morgan"; import tweetsRouter from "./router/tweets.js"; const app = express(); app.use(express.json()); app.use(cors()); app.use(morgan("tiny")); // 사용자들이 들어오게되면 로그를 콘솔에 찍어줌 app.use("/tweets", tweetsRouter); app.use((req, res, next) => { res.sendStatus(404); }); app.use((error, req, res, next) => { console.log(error); res.sendStatus(500); }); app.listen(8080); |
react.js도 이용함.
→ .jsx 파일 內 react.js를 사용한 예시
첨부한 client와 생성한 server파일을 위주로 앞으로 twitter 예제의 refactoring을 진행할 예정
아래 경로에 디렉토리 및 파일 생성
C:\yjcho\Node.js\Project\Server\controller\tweets.js
C:\yjcho\Node.js\Project_test\Server\data\tweets.js
2. Routing 기능 실습
교육 간 사용할 경로: C:\yjcho\Node.js\project\Server\router\tweets.js
아래의 5가지 기능을 구현해 볼 예정.
1) 'GET' 을 이용→username을 통한 data 출력
3) 'POST'를 이용→id: Date.now().toString()을 id에 추가 후 출력
아래의 'tweets 배열'과 'node.js express 모듈' 및 'postman 프로그램'을 이용하여 routing을 진행.
import express from 'express'; let tweets = [ { id:'1', text:'첫 트윗입니다', createdAt: Date.now().toString(), // 현재 시간을 문자열로 변경 name: 'apple', username: '김사과', url: '' }, { id:'2', text:'안녕하세요', createdAt: Date.now().toString(), // 현재 시간을 문자열로 변경 name: 'banana', username: '반하나', url: '' } ]; const router = express.Router(); ... ... ... ... export default router; // router를 내보내기함. |
아래의 번호들을
...
...
...
...
에 삽입함.
1) 'GET' 을 이용 → username을 통한 data 출력
router.get('/', (req, res, next)=> { // route경로에 대한 get 요청이 들어올 시 실행할 익명함수. const username = req.query.username; // 요청의 쿼리 파라미터에서 username 값을 가져와 변수에 저장. const data = username ? tweets.filter((tweet) => tweet.username === username) // username 값이 존재하면(truthy 값) tweets 배열에서 해당 유저의 tweet만 필터링한 결과를 data 변수에 할당. : tweets; // username 값이 존재하지 않으면 (falsy 값) 모든 tweets을 data 변수에 할당. res.status(200).json(data); // HTTP 응답 코드를 200으로 설정하고, data를 JSON 형태로 클라이언트에게 반환. }); |
해당 코드 작성 후 체크목적 Postman 프로그램 실행.
REST API의 모음집을 생성하는 작업.
My Workspace 內 왼쪽의 'Collections' 탭에서 'new'를 클릭 → 'Collection'을 한번 더 클릭.
'Twitter'라는 Collection을 새로 생성.
새로 생성한 Collections 탭에서 아래와 같이 Variables 탭의 내용을 작성 후 Save.
1) 에서 삼항연산자의 false return값인 tweets; 의 파일을 생성하는 과정
우측 점 3개 클릭 후 Add request 클릭.
Twitter 內 경로의 새로 생성한 Request의 name을 'Get Tweets'로 수정.
GET의 주소창을 {{base}}/tweets 로 작성.
(여기서 {{base}}는 이전에 지정해두었던 http://localhost:8080 주소임.)
1) 의 삼항연산자에서 tweets.filter((tweet) => tweet.username === username) filter의 data를 생성
같은 파일을 Copy 후 이름을 'Get Tweets by username'으로 변경.
GET의 주소창에서 ' {{base}}/tweets?username=김사과 ' 를 작성.
1)의 코드에서 const username = req.query.username; 의 부분 中 query에 해당하는 부분.
(URL의 query 매개변수: URL 끝에 ?와 함께 전달되는 매개변수)
Key: username
Value: 김사과
작성 후 Save & Send.
정상적으로 실행될 때의 화면.
(오류가 발생하는 경우, 서버를 Ctrl + C 로 닫았다가 다시 오픈하면 정상적으로 작동하는 경우도 있음.)
2) 'GET' 을 이용 → id를 통한 data 출력
router.get('/:id', (req, res, next)=> { // id를 통해 router의 get 메서드를 이용함 const id = req.params.id; const tweet = tweets.find((tweet) => tweet.id === id); if (tweet) { res.status(200).json(tweet); } else { res.status(404).json({message: `Tweet id(${id}) not found`}); } }); |
id가 1인 경우를 찾으려 함.
주소창에서 {{base}}/tweets/1 입력
Save + Send 시 'Get Tweets'에서 정상적으로 작동하는 것을 확인할 수 있음.
3) 'POST'를 이용 → id: Date.now().toString()을 id에 추가 후 출력
router.post('/', (req, res, next)=> { const {text, name, username} = req.body; const tweet = { id: Date.now().toString(), text: text, createdAt: new Date(), name: name, username: username }; tweets = [tweet, ...tweets]; // tweets에 tweet이 추가가 되어 tweets가 되었다는 의미. res.status(201).json(tweet); }); |
오늘의 날짜가 문자열로 받아진 후 id의 뒤에 출력됨.
POST 주소창에서 {{base}}/tweets 입력 후
Body>raw 에서 아래와 같은 내용을 입력하여 json을 추가.
Save + Send 시 정상적으로 입력한 json이 추가된 것을 확인할 수 있음.
4) 'PUT'을 이용 → id를 통한 text 수정
router.put('/:id', (req, res, next)=> { // id를 받아서 text를 찾기 const id = req.params.id; const text = req.body.text; const tweet = tweets.find((tweet) => tweet.id === id); if (tweet) { tweet.text = text; res.status(200).json(tweet); } else { res.status(404).json({message: `Tweet id(${id}) not found`}); } }); |
id가 1인 배열의 text를 변경
아래와 같이 PUT 주소창에 {{base}}/tweets/1 입력 후
Body>raw 에서 아래와 같은 내용을 입력하여 변경될 json을 추가.
Save + Send 시 정상적으로 text가 변경된 것을 확인할 수 있음.
5) 'DELETE'를 이용 → data를 삭제
router.delete('/:id', (req, res, next) => { const id = req.params.id; tweets = tweets.filter((tweet) => tweet.id !== id); // 삭제할 id를 제외하고 나머지를 필터로 출력하는 구조. res.sendStatus(204); }); |
아래와 같이 DELETE 주소창에 {{base}}/tweets/1 입력 후
Save + Send 시 'id'=1을 찾을 수 없다고 출력되며 정상적으로 삭제가 된 것을 확인할 수 있음.
3. fetch 기능 실습
교육 간 사용할 경로: C:\yjcho\Node.js\project\Client\src\service\tweet.js
tweet에 이용할 CRUD기능을 모두 가져옴
export default class TweetService { // TweetService라는 클래스를 새로 생성하여 기본적(default)으로 내보내게 함. tweets = [ // tweets의 list data { id: 1, text: '첫번째 트윗이예요!', createdAt: '2022-05-09T04:20:57.000Z', name: 'apple', username: '김사과', url: 'https://widgetwhats.com/app/uploads/2019/11/free-profile-photo-whatsapp-1.png', }, ]; // async : 함수를 비동기함수로 선언하는 역할을 함. 주로 함수 내부에서 await를 같이 사용하여 비동기작업의 완료까지 함수의 실행을 중지시킬 수 있음. async getTweets(username) { // 함수 getTweets: fetch를 통해 tweets ? username= : username의 삼항연산식을 가져옴. return username ? this.tweets.filter((tweet) => tweet.username === username) : this.tweets; } async postTweet(text) { //함수 postTweet: fetch를 통해 /tweets post로 입력한 데이터를 전송. const tweet = { id: Date.now(), // 현재 시간을 밀리초단위로 가져와 id의 속성값으로 사용. createdAt: new Date(), // 현재 시간을 가져와 createdAt의 속성값으로 사용. name: 'apple', username: '김사과', text: 'text', // text 인자로 받은 값을 그대로 text의 속성값으로 사용. }; this.tweets.push(tweet); // this.tweets 배열에 tweet 객체를 추가하여 return으로 tweet 반환. return tweet; } async deleteTweet(tweetId) { //함수 deleteTweet: filter를 통해 tweet의 아이디와 tweetId와 값이 다르면, 데이터를 삭제. this.tweets = this.tweets.filter((tweet) => tweet.id !== tweetId); } async updateTweet(tweetId, text) { //함수 updateTweet: find를 통해 tweet의 아이디와 tweetId와 값이 같으면 반환. const tweet = this.tweets.find((tweet) => tweet.id === tweetId); if (!tweet) { // 만약 tweet가 존재하지 않으면, throw를 통해 에러와 에러메시지를 출력. throw new Error('tweet not found!'); } tweet.text = text; // 만약 tweet가 존재하면, tweet객체의 text를 우항의 text로 업데이트하여 return으로 반환. return tweet; } } |
4. validation 기능 실습
validation과 관련된 모듈의 설치가 필요함.
npm i express-validator
npm i express
을 입력하여 설치.
예) text가 4자리 이하인 경우 error를 출력 / 4자리 이상일 때 정상적으로 출력.
교육 간 사용할 경로: C:\yjcho\Node.js\Project\Server\middleware\validator.js
import {validationResult} from 'express-validator'; export const validate = (req, res, next) => { // validate라는 이름의 middleware 함수를 정의함. const errors = validationResult(req); // validationResult 객체를 사용하여 이전 middleware에서 유효성 검사를 수행한 결과를 가져옴. 이 결과는 errors 변수에 저장됨. if(errors.isEmpty()){ // errors 객체가 비어있으면(유효성 검사를 통과), next() 함수를 호출하여 다음 middleware로 이동. return next(); } return res.status(400).json({message: errors.array()}); // errors 객체가 비어있지 않으면(유효성 검사를 통과하지 못함) res.status(400)을 사용하여 400 Bad Request 상태 코드를 반환하고, JSON 형식으로 errors 객체에 저장된 오류 메시지를 반환. }; |
C:\yjcho\Node.js\Project\Server\router/tweets.js 경로에서 추가로 아래 코드를 작성.
import express from 'express'; import * as tweetController from '../controller/tweet.js'; import {body} from 'express-validator'; import {validate} from '../middleware/validator.js'; // 위의 칸에서 작성한 파일 validator.js를 가져옴. const router = express.Router(); const validateTweet = [ body('text') .trim() .isLength({min:4}) // text의 공백을 모두 제거하여 그 자릿 수가 4자리 이하인 경우 msg에러를 출력. .withMessage('text는 최소 4자 이상입니다.'), validate ] const app = express(); app.use(express.json()); // Express 애플리케이션에 JSON 데이터를 파싱하기 위한 미들웨어 추가. // POST 와 PUT에 유효성검사 매개변수를 이용. router.post('/', validateTweet , tweetController.createTweet); router.put('/:id', validateTweet , tweetController.updateTweet); export default router; |
Postman 프로그램을 작동해서 Body > Raw에 내용을 기재한 후 Save + Send 시 정상적으로 작동 확인.
POST 정상적으로 작동 시 추가한 내용이 정상적으로 생성.

text의 글자가 4글자 이하일 시, msg에 'text는 최소 4자 이상입니다.' 라는 문구 출력 후 error 발생.

5. 중간 점검
Client/Server 디렉토리 內 package.json 설치 후 터미널 2개를 띄워 실행.
1. C:\yjcho\Node.js\Project\Server 경로로 index.js 실행.
2. C:\yjcho\Node.js\Project\Client 경로로 react-script 실행.
정상적으로 twitter 기능을 담은 웹페이지 화면