Back-End/Node.js

[Node.js] React와 Express로 CRUD 게시판 웹 서버 만들기 - 2 (REST API)

현기 2022. 9. 22. 20:43

지난내용

https://hyunki99.tistory.com/44

 

[Node.js] Express 웹 서버 만들기 (mySQL 연동) - 1

Express란 "Node.js를 위한 가장 빠르고 개방적인 간결한 웹 프레임워크"다. MIT허가서로 라이선스 되는 자유-오픈 소스 소프트웨어다. 웹 어플리케이션, API 개발을 위해 설계되었고, Node.js의 사실상

hyunki99.tistory.com

 

지난 포스팅에서 Express와 mySQL의 연동을 성공했습니다.

 

Create : 게시글 쓰기

Read : 게시글 조회

Update : 게시글 수정

Delete : 게시글 삭제

 

위 기능들을 Express를 사용해서 REST API를 구현해 봅시다.

REST API는 오늘날 웹에서 가장 많이 사용되고 있는 유연한 API입니다.

클라이언트가 서버에 데이터와 함께 요청을 전송하면

서버가 내부 함수를 시작하고 출력 데이터를 응답합니다. 

 

🔥 REST API란 무엇인가요?


REST는 Representational State Transfer의 줄임말입니다. REST는 클라이언트가 서버 데이터에 액세스하는 데 사용할 수 있는 GET, PUT, DELETE 등의 함수 집합을 정의합니다. 클라이언트와 서버는 HTTP를 사용하여 데이터를 교환합니다.REST API의 주된 특징은 무상태입니다. 무상태는 서버가 요청 간에 클라이언트 데이터를 저장하지 않음을 의미합니다. 서버에 대한 클라이언트 요청은 웹 사이트를 방문하기 위해 브라우저에 입력하는 URL과 유사합니다. 서버의 응답은 웹 페이지의 일반적인 그래픽 렌더링이 없는 일반 데이터입니다.  -AWS

 

 


Front - End

 

서버를 만들기 전에 데이터를 요청하고 표시할 게시판을 React로 만들었습니다.

디자인은 상관 없으니 자유롭게 만들어 주시면 됩니다. 

 


📝 Create 게시글 쓰기

 

 

⦁ Express 소스코드

//글 작성
app.post('/questions', (req, res) => {
//파라미터를 받아오는 부분
    let post_title = req.body.params.post_title;
    let post_content = req.body.params.post_content;
    let post_nickname = req.body.params.post_nickname;
    let post_user_id = req.body.params.post_user_id;
    let values = [post_title, post_content, 0, post_nickname, post_user_id]

//SQL 코드
    const sql = "INSERT INTO condb.post_info(post_title, post_content, post_like_count, post_nickname, post_user_id) VALUES(?, ?, ? ,?, ?)"
    db.query(sql,values,
        (err, result) => {
            if (err)
                console.log(err);
            else
                res.send(result);
        });
});

 

✔ 먼저 프론트단에서 입력한 데이터를 가져와야 합니다.

쿼리를 사용하는 방법이 있고 직접 body에서 가져오는 방법이 있습니다.

# 프론트에서 데이터를 가져오는 2가지 방법
req.body.params.데이터이름
req.query.데이터이름

 

그 후 db.query() 메서드를 통해 mySQL에 쿼리 문의 결과를 가져옵니다.

db.query("쿼리문", ?에 할당할 변수, (err, result))

 

물론 변수에 할당하지 않고 직접 넣어도 동작합니다.

또한, 두 번째 매개변수는 ?를 사용하지 않았다면 생략 가능합니다.

 

대부분 글의 제목과 내용은 사용자의 입력에 따라서 항상 바뀌기 때문에 ? 로 들어갈 자리를

비워주고 query() 메서드의 2번째 매개변수에 넣는 것이 바람직합니다. (배열도 넣을 수 있습니다.)

 

res.send()를 통해 최종적으로 프론트에 결과를 응답해줍니다.

 

⦁ React 소스코드

const newPosting = () => {
    axios.post('http://localhost:3001/questions',{
      params: {
        post_title: postId,
        post_content: desc,
        post_nickname : sessionStorage.getItem('user_nickname'),
        post_user_id : sessionStorage.getItem('user_id'),
      }
    })
      .then(res => {
        console.log(res.data)
        alert("글 작성이 완료되었습니다.")
        document.location.href = '/'
      })
      .catch(function(error){
       console.log(error);
    })
}

//render 부분에 작성
<Button onClick = {newPosting}/>

 

✔ newPosting 메서드를 버튼의 onClick 이벤트에 넣어줍니다.

 

 

⦁ Params 설명

// 다음과 같이 자유롭게 파라미터를 넘겨주세요.
params: {
    post_title: 글 제목,
    post_content: 글 내용,
    post_nickname : 닉네임,
    post_user_id : 작성한 사용자 아이디,
}

프론트에서 요청을 보낼 때 {키 : 값} 처럼 생긴 데이터 형식으로 전송합니다.

서버와 프론트의 통신에서 데이터의 키가 다르면 undefined 에러가 발생합니다.

 

따라서 데이터를 잘 받기 위해서는 주고받는 키의 이름이 일치하는지 잘 확인해야 합니다.

 

콘솔로그를 생활화 합시다.🤦‍♂️

 

❗ express에서 파라미터가 계속 undefined인 경우
axios의 2번째 매개변수에 null을 추가합니다.

axios는 'data'를 query로 변환해 주지 않는다고 해서 발생한 에러라고 합니다.

axios.post('http://localhost:3001/요청URL', null, {
        ⦁ ⦁ ⦁            
}

 

 


📝 Update 게시글 수정

 

 

 위의 코드를 이해했다면 쿼리문만 바꿔주면 UpdateDelete도 쉽게 구현할 수 있습니다.

저는 로그인이 구현되어 있기 때문에 본인만 수정할 수 있도록 조건문을 주었습니다.

 

📝 전체 소스코드 

더보기

⦁ Express 소스코드

//게시글 수정
app.post('update', (req, res) => {
    const post_id = req.body.params.post_id;
    const post_title = req.body.params.post_title;
    const post_content = req.body.params.post_content;
    const post_nickname = req.body.params.post_nickname;

    // 게시글 nickname과 동일한 nickname이 mysql에 있는지 확인
    const sql = "SELECT COUNT(*) AS result FROM user WHERE nickname = ?"

    db.query(sql, post_nickname, (err, data) => {
        if (!err) {
            // 결과값이 1보다 작다면(동일한 id 가 없다면)
            if (data.result < 1) {
                res.send("아이디가 존재하지 않습니다.")
            } else { // 동일한 nickname 있으면
                
                //업데이트할 게시글 찾아서 업데이트
                const sql2 = "UPDATE post_info SET post_title = ?, post_content=? where post_id = ?"
                const params = [post_title, post_content, post_id]
                db.query(sql2, params, (err, data) => {
                    if (!err) {
                        res.send("성공")
                    } else {
                        res.send(err)
                    }
                })
            }
        } else {
            res.send(err)
        }
    })
});

 

⦁ React 소스코드

// 수정요청
const onClickUpdate = () => {
    if (inputTitle != "" && desc != "") {
        axios.post('http://localhost:3001/onUpdate', {
            params: {
                post_id: 게시글번호,
                post_title: 글 제목,
                post_content: 글 내용,
                post_nickname: sessionStorage.getItem("user_nickname")
            }
        })
            .then(res => {
                console.log(res.data)
                alert("수정이 완료되었습니다.")
                document.location.href = '/'
            })
            .catch()
    }
    else {
        alert("글 혹은 내용을 입력해야만 합니다.")
    }
}

 

 


📝 Delete 게시글 삭제

 

 

Update와 비슷합니다. 글쓴이와 로그인한 사용자가 동일한 경우만 삭제가 가능합니다.

만약, 그냥 삭제만 하고 싶다면 앞에 조건문은 지우시고 사용하면 됩니다.

 

DELETE FROM 테이블 WHERE post_id = 삭제할 게시글번호

위의 쿼리문을 사용해서 DB에서 삭제시키면 됩니다.

 

 

📝 전체 소스코드 

더보기

⦁ Express 소스코드

app.post('/delete', (req, res) => {
    const post_id = req.query.post_id;
    const post_nickname = req.query.post_nickname;

    // 게시글 nickname과 동일한 nickname이 mysql 에 있는 지 확인
    const sql1 = "SELECT COUNT(*) AS result FROM user WHERE nickname = '?'"

    db.query(sql1, post_nickname, (err, data) => {
        if (!err) {
            if (data.result < 1) {
                res.send('실패')
            } else { // 동일한 nickname 있으면
                //삭제할 게시글 찾아서 삭제
                const sql2 = "DELETE FROM condb.post_info WHERE post_id = ?"
                db.query(sql2, post_id,
                    function (err, result, fields) {
                        if (err) throw err;
                        console.log(result);
                        res.send('true');
                    });
            }
        } else {
            res.send(err)
        }
    })
});

 

⦁ React 소스코드

// 삭제 버튼 클릭 이벤트
const onClickDelete = () => {
    if (sessionStorage.getItem('user_id') == postData.post_user_id) {
        axios.post('http://localhost:3001/onDelete', null, {
            params: {
                'postnickname': 글쓴이 닉네임,
                'post_id': 게시글id
            }
        })
            .then(res => {
                alert('게시글이 삭제 되었습니다.')
                //삭제되면 새로고침
                document.location.href = '/'
                console.log(res.data);
            })

            .catch()
    }
    else {
        alert('작성자만 삭제 및 수정이 가능합니다.')
    }
}

 

 


 


 

 

CRUD 기능은 웹에서 가장 기본적이면서 중요합니다.

Express를 중심으로 포스팅 했는데,

다음에는 React 관련 포스팅을 하도록 하겠습니다.

 

 


참고 문헌 :