[Node.js] node.js로 간단한 CRUD API를 만들어보고 postman으로 테스트해보기

Haeun Noh·2023년 10월 25일
1

Node.js

목록 보기
1/2
post-thumbnail

1026


0. node.js 준비

0.1. express 설치

vscode를 열고 cmd를 켜 npm install express를 치면 express가 다운받아집니다.

express: node.js 웹 애플리케이션 프레임워크

express는 자유롭게 활용할 수 있는 수많은 HTTP 유틸리티 메서드 및 미들웨어를 통해 쉽고 빠르게 강력한 API를 작성할 수 있다는 것이 장점입니다.


0.2. nodemon 설치

npm install nodemon -g

그렇게 express를 다운받았다면 실행을 편리하게 해줄 nodemon을 설치해줄 것입니다.

위에서 -g는 모든 곳에 nodemon을 적용한다는 의미입니다.
굳이 넣지 않아도 문제는 없지만 넣으면 좋습니다.

nodemon: node monitor의 약자로, 노드가 실행하는 파일이 속한 디렉터리를 감시하고 있다가 파일이 수정되면 자동으로 노드 애플리케이션을 재시작하는 확장 모듈

nodemon을 사용하면 저장할 때마다 바로바로 노드 애플리케이션을 재시작해줘서 node 파일명 명령어를 매번 새로 작성하는 수고를 덜어줍니다.

그럼 이제 모든 준비가 끝났습니다!
간단한 crd기능을 node.js로 구현하러 가보도록 합시다



1. 기본적인 node.js의 api 구조 이해하기

const express = require('express') // require : 모듈을 불러옴. import 구문과 비슷한 역할
const app = express()
// 포트 번호 : 각 프로그램들을 구분하는 것
const port = 3000

// GET 요청
// 주소 "/"
// req => 요청메시지 객체, res => 응답메시지 객체
app.get('/', (req, res) => {
    res.send('Hello World!')// 해당 데이터는 응답 메시지의 Body에 들어간다
})

// listen : port번호에 대해 listen하고 있는 것
app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})
app.get('/', (req, res) => {
    res.send('Hello World!')// 해당 데이터는 응답 메시지의 Body에 들어간다
})

GET요청을 보내는 화살표 함수입니다.
function을 명시해도 되지만 보통 화살표 함수의 형태로 많이 사용합니다.

/ 은 주소를 의미합니다. 만약 localhost:3000에서 실행했다면 localhost:3000과 같이 /를 붙이지 않아도 실행이 잘 됩니다.

req와 res는 각각 요청메시지 객체와 응답메시지 객체를 뜻합니다.

  • req(request) : 요청을 의미
  • res(response) : 응답을 의미
	res.send('Hello World!')

요청메시지를 사용하여 "Hello World!" 라는 문자 형식의 데이터를 응답 메시지(req)의 Body에 보냅니다.

// listen : port번호에 대해 listen하고 있는 것
app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

이 코드는 port(3000)번호에 대해 듣고 있는 것이라고 생각하면 됩니다.
포트 번호가 실행되면 Example app listening on port 3000 이라는 텍스트가 콘솔에 출력되게 됩니다.
nodemon을 사용하여 실행한 콘솔 화면입니다. 위의 텍스트가 출력되어 있는 것을 확인할 수 있죠?


2. GET 요청 날려보기

app.get("/hello", (req, res) => {
    res.header("Content-Type", "text/plain")// 데이터 타입이 텍스트임을 알려준다
    // Ctrl f5 를 누르면 변하는 이유 : 이전 캐시를 쓰지 말아라
    // Ctrl f5를 눌러도 변하지 않는 이유 : 캐시를 해놨기 때문. - 304 => 캐시를 했다. 컴퓨터가 기존 세이브를 계속 실행한다
    res.send("<h1>Hello</h1>")
})

이제 간단한 get(read) 요청을 해보도록 하겠습니다.

위에서 주소는 localhost:3000/hello가 될 것이고 그 이유는 port가 3000이기 때문입니다.
마찬가지로 요청메시지 객체는 req, 응답 메시지 객체는 res에 담겨 오겠죠.

    res.send("<h1>Hello</h1>")

요청온 주소에 html형식으로 Hello를 화면에 출력하게 됩니다.

    res.header("Content-Type", "text/plain")

그런데 새로운 게 보이네요
위의 코드는 데이터의 타입이 텍스트라고 명시해주는 코드입니다.
만약 위에서 출력했던 <h1>Hello</h1>의 형식이 html이 아니라 텍스트 그 자체로 출력되게 하고 싶다면 Content-Typetext/plain로 설정해주면 됩니다.

2.1. 근데 새로고침(f5)를 눌러도 변경사항이 반영되지 않아요

이것의 원인을 쉽게 말하면 컴퓨터가 매번 요청을 받아오기 귀찮아서 이전에 반영했던 저장사항을 마치 새로 요청을 받아온 것처럼 꾸며놓은 겁니다.

f12키를 눌러 개발자 모드에 들어간 뒤, 네트워크에 들어가고, 다시 f5(또는 Ctrl+f5)키를 누르면 상태 부분에 200이 뜨는 것을 확인할 수 있는데요,

다시 f5를 누르면 상태가 200 -> 304로 변한 것을 확인할 수 있습니다. 왜 바뀐 걸까요??

이것이 바로 컴퓨터가 기존 세이브를 계속 실행한다는 뜻입니다. 즉, 캐시를 했다는 것이죠.

캐시를 하지 않고 변경사항을 반영하고 싶다면 앞서 잠깐 나왔던 Ctrl + f5를 누르면 됩니다.
이것은 이전 캐시를 쓰지 말아라 라는 의미를 담고 있으니 변경사항이 바로바로 반영이 되겠죠!



3. GET, POST, DELETE를 활용하여 간단한 api 만들어보기

그럼 get, post, delete로 api라고 하기에는 뭐하지만 아주아주 간단한 api를 만들어보겠습니다.

const express = require('express') // require : 모듈을 불러옴. import 구문과 비슷한 역할
const app = express()
// 포트 번호 : 각 프로그램들을 구분하는 것
const port = 3000

app.get("/data",  (req, res) => {
    // json : json형식의 데이터를 보내는 send
    res.json({name: "John", age: 20})
})

// GET, POST, PUT, PATCH, DELETE
let array = []
// 조회
app.get("/array", (req, res) => {
    res.json(array)
    // 꼭 json을 넣지 않아도 된다
    res.json(1)
    res.json("Hello")
})

// 주소가 같더라도 메서드가 다르므로 괜찮다
app.post("/array", (req, res) => {
    array.push({content: array.length+1})// post 요청을 할 때마다 json데이터가 들어간다.
    res.json({result: "ok"})
})

app.delete("/array", (req, res) => {
    array = []
    res.json({result: "delete ok"})
})

// listen : port번호에 대해 listen하고 있는 것
app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

3.1. GET 요청 날리기

먼저 get방식입니다.

app.get("/data",  (req, res) => {
    // json : json형식의 데이터를 보내는 send
    res.json({name: "John", age: 20})
})

.json이 처음 등장했는데 그냥 json형식의 데이터를 보내는 send와 똑같다고 생각하시면 됩니다.

이렇게 resname이 John이고 age가 20인 json 데이터를 보냅니다.

위처럼 브라우저로 확인해볼 수도 있지만 api가 잘 작동하는지 테스트를 하는 postman으로 한 번 값이 받아와지는지를 확인해보도록 하겠습니다.
잘 받아와지는 것을 확인할 수 있네요!


위의 get방식은 간단한 버전이었고 이번에는 조금 더 활용이 들어간 get방식의 api를 짜보겠습니다.

let array = []
app.get("/array", (req, res) => {
    res.json(array)
    res.json(1)
    res.json("Hello")
})

이번에는 배열을 활용해서 응답을 보내겠습니다.

어? 근데 응답에는 json형태만 보낼 수 있는 거 아니에요?

res에 꼭 json형태만 보내지 않아도 됩니다!
배열 형태, 숫자 형태, 문자열 형태 그 어느것이든 넣을 수 있어요~

postman으로 실행했을 때도 문제없이 잘 작동하는 것을 볼 수 있네요!


3.2. POST 요청 날리기

이번에는 값을 넣을 수 있는 post 요청을 날려보도록 하겠습니다.

app.post("/array", (req, res) => {
    array.push({content: array.length+1})// post 요청을 할 때마다 json데이터가 들어간다.
    res.json({result: "ok"})
})

어? 근데 get 요청 날린 코드와 주소가 "/array"로 같은데요?? 이러면 중복되는 거 아닌가요?

아닙니다!
주소는 같지만 HTTP 메서드가 get과 post로 다르기 때문에 오류가 나지 않는답니다.

위의 코드는 post요청이 갈 때마다 arrayarray.length+1의 데이터를 넣는데요, 처음 array.length0이므로 값은 1 2 3 4 ... 이렇게 쭉 저장될 거라는 걸 알 수 있습니다.

그리고 응답값으로는 값이 잘 저장되었다는 표시로 result: ok가 보여지겠군요!
그럼 postman으로 결과 확인해봅시다.
이렇게 값이 잘 들어간 것을 확인한 뒤, post 요청을 총 3번 보내봤어요.
그럼 get요청을 보냈을 때 json데이터가 총 3개가 들어있겠죠? 이것도 한 번 확인해봅시다.
잘 들어갔네요!


3.3. PATCH 요청 날리기

이번에는 넣은 값을 변경할 수 있는 update요청을 한 번 날려보도록 하겠습니다.

app.patch("/posts/:id", (req, res) => {
    const id = req.params.id// url에서 추출한 게시물 id
    pool.query(
        "SELECT * FROM post WHERE id = ?",
        [id],
        function(err, rows, fields) {
            if ( rows.affectedRows === 0 ) {// db에 존재하지 않는다
                res.status(404).json({result: null})// 404 오류를 반환하는 엔드포인트
            } else {
              	// 게시물이 존재하는 경우
                delete req.body.id// req.body에서 id속성 삭제
                const modified = Object.assign(rows[0], req.body)// Object.assign: rows[0]과 req.body를 병합하여 modified객체 생성
                // rows[0]: db의 원래 게시물 데이터, req.body: 내가 보낸 데이터
	
                // 게시물의 title, author, content 수정
                pool.query("UPDATE post SET title = ?, author = ?, content = ? WHERE id = ?",
                    [modified.title, modified.author, modified.content, id],
                    function(err, rows, fields) {
                        if ( err ) {
                            res.status(400).json({result: err})
                        } else {
                            res.json({result: "ok"})
                        }
                    })
            }
        }
    )
})

먼저 어떤 id를 가진 데이터가 있는지를 확인합니다. 사진에서는 id가 3인 데이터가 있군요
그렇다면 우리는 id가 3인 데이터를 수정할 것입니다.
Body > raw, JSON 을 잘 확인한 뒤, 사진에서는 title만 수정합니다.
다시 GET요청을 보내면 title만 잘 변경된 것을 확인할 수 있습니다.
이번에는 title, author, content 3개를 모두 변경해보겠습니다.
이번에도 잘 변경된 것을 확인할 수 있네요!


3.4. DELETE 요청 날리기

이번에는 넣은 값을 삭제할 수 있는 delete 요청을 한 번 날려보도록 하겠습니다.

app.delete("/array", (req, res) => {
    array = []
    res.json({result: "delete ok"})
})

이제는 대강 어떻게 작성해야 하는지에 대한 틀이 잡혀갑니다.

delete요청을 보내면 array는 빈 배열이 되고 값 삭제가 잘 되었다는 뜻으로 result: delete ok가 응답 메시지로 보여지겠네요
한 번 확인해볼까요?

값이 잘 삭제되었다는 응답을 보고 다시 한 번 get 요청을 보내보면 값이 없어진 것을 조회할 수 있습니다.



이렇게 node.js로 GET, POST, PATCH, DELETE 요청을 보내서 아주아주 간단한 CRUD API를 만들어봤는데요, 이 글을 읽고서 api에 대한 틀이 조금이라도 잡혔으면 좋겠습니다.
글 읽어주셔서 감사합니다.

profile
기록의 힘을 믿는 개발자, 노하은입니다!

0개의 댓글