본문 바로가기

Nodejs

리팩토링, validation(2024-04-29)

리팩토링

- 소프트 웨어 개발 과정에서 코드를 재구성하여 가독성을 높이고 유지보수를 쉽게 만드는 과정
- 코드의 구조를 개선하고 중복을 제거하여 더 나은 설계 패턴을 도입함으로 코드의 품질을 향상 시킴
- 코드의 기능을 변경하지 않으면서 코드를 개선하는 방법

더보기

router > tweets.js

import express from 'express';
import * as tweetcontroller from '../controller/tweet.js';
const router = express.Router();



// 해당 아이디에 대한 트윗 가져오기
// GET
// http://localhost:8080/tweets?username=:username
router.get('/', tweetcontroller.getTweets);


// 글 번호에 대한 트윗 가져오기
// GET
// http://localhost:8080/tweets/:id
router.get('/:id', tweetcontroller.getTweet);


// 트윗하기
// POST
// http://localhost:8080/tweets
// name, username, text를 받아서 글을 등록 
// json형태로 입력 후 추가된 데이터까지 모두 json으로 출력
router.post('/', tweetcontroller.createTweet);




// 트윗 수정하기
// PUT
// http://localhost:8080/tweets/:id
// id, username, text를 받아서 글을 수정
// json형태로 입력 후 변경된 데이터까지 모두 json으로 출력
router.put('/:id', tweetcontroller.updateTweet);


// 트윗 삭제하기
// DELETE
// http://localhost:8080/tweets/:id
router.delete('/:id', tweetcontroller.deleteTweet);


export default router;

 

data > tweet.js

let tweets = [
    {
        id:'1',
        text: '안녕하세요!',
        createAt: Date.now().toString(),
        name:'김사과',
        username:'apple',
        url: 'https://www.logoyogo.com/web/wp-content/uploads/edd/2021/02/logoyogo-1-45.jpg'
    },
    {
        id:'2',
        text: '반갑습니다!',
        createAt: Date.now().toString(),
        name: '반하나',
        username: 'banana',
        url: 'https://www.urbanbrush.net/web/wp-content/uploads/edd/2019/07/urbanbrush-20190716011532646988.png'   
    }
];

// 모든 트윗을 리턴 시키는 함수
export async function getAll(){
    return tweets;

}


// 해당 아이디에 대한 트윗을 리턴 시키는 함수
export async function getAllByUsername(username){
    return tweets.filter((tweet) => tweet.username === username)
}

// 글 번호에 대한 트윗을 리턴
export async function getById(id){
    return tweets.find((tweet) => tweet.id === id);

}

// 트윗을 작성
export async function create(text, name, username){
    return tweet = {
        id : '10',
        text,
        createAt:Date.now().toString(),
        name: name,
        username: username
 // 위처럼  키와 밸류가 같다면 한번 만 써도 됨
 // name,
 // username 이런식으로 
    }
    tweets = [tweet, ... tweets];
    return tweets;
}

// 트윗을 변경
export async function update(id, text){
    const tweet = tweets.find((tweet) => tweet.id === id);
    if (tweet){
        tweet.text = text; // 기존의 text에 새로 입력받은 text값 대입
    }
    return tweet;

}

// 트윗을 삭제
export async function remove(id){
    tweets = tweets.filter((tweet) => tweet.id !== id);

}

 

controller > tweet.js

import * as tweetRepository from '../data/tweet.js';

// 여러 트윗을 가져오는 함수
export async function getTweets(req, res){
    const username = req.query.username;
    const data = await(username ? tweetRepository.getAllByUsername(username)   : tweetRepository.getAll());
    res.status(200).json(data);
};

// 하나의 트윗을 가져오는 함수
export async function getTweet(req, res, next){
    const id = req.params.id;
    const tweet = await tweetRepository.getById(id);
    if(tweet){
        res.statut(200).json(tweet)
    }else{
        res.status(404).json({message : `${id}의 트윗이 없습니다`})
    }
    }


// 트윗을 생성하는 함수
export async function createTweet(req, res, next){
    const {text, name, username} = req.body;
    const tweet = await tweetRepository.create(text, next, username);
    res.status(201).json(tweet);
}


// 트윗을 변경하는 함수
export async function updateTweet(req, res, next){
    const id = req.params.id;
    const text = req.body.text;
    const tweet = await tweetRepository.update(id, text);
    if(tweet){
        res.status(201).json(tweet);
    }else{
        res.status(404).json({massage: `${id}의 트윗이 없습니다`})
    }
}

// 트윗을 삭제하는 함수
export async function deleteTweet(req, res, next){
    const id = req.params.id;
    tweets = tweetRepository.remove(id);
    // 입력 받은 id 값은 보여주지 않겠다
    res.sendStatus(204);
}

 

 

리팩토링 이전의 형태

더보기
import express from 'express';

const router = express.Router();

let tweets = [
    {
        id:'1',
        text: '안녕하세요!',
        createAt: Date.now().toString(),
        name:'김사과',
        username:'apple',
        url: 'https://www.logoyogo.com/web/wp-content/uploads/edd/2021/02/logoyogo-1-45.jpg'
    },
    {
        id:'2',
        text: '반갑습니다!',
        createAt: Date.now().toString(),
        name: '반하나',
        username: 'banana',
        url: 'https://www.urbanbrush.net/web/wp-content/uploads/edd/2019/07/urbanbrush-20190716011532646988.png'   
    }
];

// 해당 아이디에 대한 트윗 가져오기
// GET
// http://localhost:8080/tweets?username=:username
router.get('/', (req, res) => {
    const username = req.query.username;
    const data = username 
        ? tweets.filter((tweets) => tweets.username == username): tweets;
        // tweets 안에 username 값이 있으면 가져오고 없으면 

    res.status(200).json(data);
})


// 글 번호에 대한 트윗 가져오기
// GET
// http://localhost:8080/tweets/:id
router.get('/:id', (req, res, next) => {
    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:`${id}의 트윗이 없습니다.`});
    }
});


// 트윗하기
// POST
// http://localhost:8080/tweets
// name, username, text를 받아서 글을 등록 
// json형태로 입력 후 추가된 데이터까지 모두 json으로 출력
router.post('/', (req, res, next) => {
    const {text, name, username} = req.body;
    const tweet = {
        id: '10',
        text: text,
        createAt: Date.now().toString(),
        name: name,
        username: username,
        url: 'https://www.urbanbrush.net/web/wp-content/uploads/edd/2019/07/urbanbrush-20190716011532646988.png'
    };
    tweets = [tweet, ... tweets];
    res.status(201).json(tweets);
});




// 트윗 수정하기
// PUT
// http://localhost:8080/tweets/:id
// id, username, text를 받아서 글을 수정
// json형태로 입력 후 변경된 데이터까지 모두 json으로 출력
router.put('/:id', (req, res, next) => {
    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(201).json(tweet);
    }else{
        res.status(404).json({massage: `${id}의 트윗이 없습니다`})
    }
});


// 트윗 삭제하기
// DELETE
// http://localhost:8080/tweets/:id
router.delete('/:id', (req, res, next) => {
    const id = req.params.id;
    tweets = tweets.filter((tweet) => tweet.id !== id);
    // 입력 받은 id 값은 보여주지 않겠다
    res.status(204).json(tweets);
});





export default router;

 

isLength(): 문자열 길이 검증
    app.get('/:email', [param('email').isLength({min:3}).withMessage('이메일을 3자 이상 입력하세요.!'),
    validate], (req, res, next) => {
    res.send(':연애편지:');
    });

isEmail(): 이메일 주소의 유효성 검증
    app.get('/:email', [param('email').isEmail().withMessage('이메일을 입력하세요.!'),
    validate], (req, res, next) => {
    res.send(':연애편지:');
    });

isInt(): 숫자의 최소 또는 최댓값 검증
    app.get('/:num', [param('num').isInt({min:10, max:100}).withMessage('숫자의 범위는 10이상 100이하로 입력하세요.'),
    validate], (req, res, next) => {
    res.send(':주황색_하트:');
    });

matches(): 정규표현식을 사용하여 문자열의 패턴을 검증
    app.get('/:name', [param('name').matches({/^[가-힣]+$/}).withMessage('이름은 한글로 입력하세요.'),
    validate], (req, res, next) => {
    res.send(':회색_물음표:');
    });

 

validation

더보기
import express from 'express';
import { body, param, validationResult } from 'express-validator';

const app = express();
app.use(express.json());

const validate = (req, res, next) => {
    const errors = validationResult(req);
    if(errors.isEmpty()){
        return next();
    }
    console.log(errors.array());
    return res.status(400).json({message: errors.array()[0].msg});
}
app.get('/:email', [param('email').isEmail().withMessage('이메일을 입력하세요!'), validate], (req, res, next) => {
    res.send(':연애편지:');
});
app.post('/users', [
    body('name').trim().isLength({min:2}).withMessage('이름은 두글자 이상으로 입력!'),
    body('age').isInt().withMessage('나이는 숫자로 입력!'),
    body('height').isInt({min:100, max:200}).withMessage('키는 100이상 200이하로 입력하세요!'),
    body('job').notEmpty(),
    validate
], (req, res, next) => {
    console.log(req.body);
    res.sendStatus(201);
})

app.post('/text', [
    body('text').trim().isLength({min:3}).withMessage('세 글자 이상으로 입력'), validate

], (req, res, next) => {
    console.log(req.body);
    res.sendStatus(201);
})

app.put('/text', [
    body('text').trim().isLength({min:3}).withMessage('세 글자 이상으로 입력'), validate

], (req, res, next) => {
    console.log(req.body);
    res.sendStatus(201);
})



app.listen(8080);

'Nodejs' 카테고리의 다른 글

Authentication (2024-05-02)  (0) 2024.05.02
과제 회원가입, 로그인 router, tweet 활용  (0) 2024.04.29
params, query  (0) 2024.04.29
route 활용 (tweet 예제) (2024-04-26)  (0) 2024.04.26
post, error, route (2024-04-25)  (0) 2024.04.25