REST + API 합성어
-REST 아키텍쳐를 준수하는 웹 API로 RESTful API라고 부르기도 한다.
-REST : REpresentational State Transfer. 웹에서 자료를 전송하기 위한 표현 방법에 대한 아키텍쳐. REST를 정확하게 구현하기 위해선 많은 제한조건이 있으나 기본적인 가이드를 따르면 조금 더 좋은 구조의 API 구성이 가능
-API : 어플리케이션 프로그래밍 인터페이스, 서비스나 프로그램 간에 미리 정해진 기능을 실행 할 수 있도록 하는 규약.
-REST API는 API의 동작을 HTTP method+명사형 URL로 표현함
-/post라는 URL은 '게시글'이라는 자원을 가리킨다고 할 때, get-가져오기, post-새로 만들기, put-수정하기(덮어씌움-다른 데이터 삭제될 가능성 존재), delete-삭제하기 등 HTTP 메소드와 결합하여 API 동작을 정의해야함.
*참고로 patch는 부분수정임.
-REST API URL의 자원은 '복수형으로 표현'되며 하나의 자원에 대한 접근은 '복수형+아이디'를 통해 특정 자원에 접근함
-/posts/는 '게시글 전체'를 칭하는 URL 이라 할 때 /posts/1은 '1번 게시글'을 의미.
-REST API는 URL을 통해 자원을 계층적으로 표현함
-/users/1/posts는 '1번 유저의 게시글 전체'라는 자원을 의미.
목표 : DB 없이 Node.js 모듈 활용, 간단한 메모 작성/수정/삭제/확인기능 API 구현, express-generator 사용하지 않고 MVC 패턴 구현
MVC 패턴
-웹 서비스의 가장 대표적인 프로젝트 구성 패턴
-프로젝트의 기능들을 어떻게 분리할지에 대한 하나의 구성 방법
-Model-View-Controller를 구분하여 프로젝트 구조를 구성
-Node.js의 모듈화를 이용하여 MVC 패턴을 구현할 수 있음
-JSON API를 구현하는 경우, Node.js는 기본적으로 JSON을 처리하는 방법을 가지고 있기 때문에 View는 생략될수있음
(1) Model
-'데이터에 접근하는 기능 혹은 데이터 그 자체'
-'데이터의 읽기, 쓰기는 모델을 통해서만' 이루어지도록 구성
(2) View
-'데이터를 표현하는 기능'
-Controller에 의해 데이터를 전달받고 화면에 표시함
(3) Controller
-Model을 통해 데이터에 접근하여, 처리 결과를 View로 전달하는 기능
-웹서비스에선 주로 라우팅 함수가 해당 기능을 수행
(4) ★구현 사항★
-JavaScript의 'Array 함수 사용하여 데이터 처리 구현'
-router와 route handler를 사용하여 HTTP 요청, 응답처리 구현
-오류처리 미들웨어를 사용하여, 오류를 처리하는 방법 구현
-정의되지 않은 라우팅에 대해 404 오류처리구현
---models/note.js
// 배열 사용하여 노트가 담기는 목록 구현.
// 목록 생성, 수정, 삭제 기능을 여기서 구현.(데이터 처리)
let notes = [
{
id: 1,
title: 'first note',
content: 'My first note is here.'
}
];
//메모 목록을 보내주는 함수 'list'
//메모 목록 안에서 id와 title만 object로 만들어 만들어 보내는 함수
exports.list= () =>{
return notes.map(({ id, title })=>(
{
id,
title,
}
));
}
---routes/notes.js
const { Router } = require('express');
const Note = require('../models/note');
const router = Router();
//메모 목록을 가져옴 : get
router.get('/', (req, res, next) => {
//리퀘스트 핸들러로 Note.list함수를 써서 노트 목록을 notes라는 이름으로 받음
const notes = Note.list();
// 노트 목록을 json으로 전달
res.json(notes);
});
---models/note.js
// id를 받아 메모 목록안에 전달받은 id와 같은 id가 있는지 찾음
exports.get = (id) =>{
const note = notes.find(
(note) => note.id === id
);
if (!note) {
throw new Error('No note found');
}
return note;
}
// http Method get임.
router.get('/:id', (req, res, next) =>{
const id = Number(req.params.id);
try{
//변환해준 id를 Note.get으로 받아 사용
const note = Note.get(id);
res.json(note);
} catch(e) {
next(e);
}
});
---models/note.js
// 메모의 제목과 내용을 인자로 받아서 새로운 메모를 생성,
//위에 있는 메모 목록의 가장 마지막 요소로 추가하는 함수
exports.create = (title, content) =>{
// 노트의 가장 마지막 요소를 받아서 그 요소의 id를 lastId라는 변수로 디스트럭팅.
// 노트 목록은 배열이므로 length-1이 마지막 요소.
const { id : lastId} = notes[notes.length-1];
// 새 노트는 마지막 id에 1을 더하고 전달 받은 제목과 내용을 가짐
const newNote= {
id: lastId+ 1,
title,
content,
};
notes.push(newNote);
return newNote;}
---routes/notes.js
// 작성 API는 자원을 생성하므로 POST 메소드를 사용
router.post('/', (req, res, next) =>{
// post 메소드는 req.body로 요청값을 받는데 req.body 안에서 title, content로 디스트럭팅,
const { title, content } = req.body;
// 디스트럭팅한 값을 Note.create로 넘겨서 그 값을 토대로 메모를 작성하여 목록 마지막에 넣게됨.
const note = Note.create(title, content);
// 이렇게 새로 생성 된 노트를 json으로 응답처리함.
res.json(note);
});
---models/note.js
exports.update = (id, title, content) =>{
//전달받은 id 값과 id가 일치하는 노트를 index로 지정
const index = notes.findIndex(
(note) => note.id === id
);
if(index < 0) {
throw new Error('Note not found for update');
}
// 요소 검사 통과시 요소를 객체로 전달 받고(노트 목록의 요소는 객체형태) 이 객체의 제목과 내용을 변경하고 수정 대상의 인덱스에 마지막으로 그 내용을 저장
const note = notes[index];
note.title = title;
note.content = content;
notes[index] = note;
return note;
}
---routes/notes.js
// 자원 수정 -> put 메소드 사용.
// path param : 특정 자원 나타냄.
router.put('/:id', (req, res, next)=> {
const id = Number(req.params.id);
// body에 전달된 title과 content를 디스트럭팅 해서
const{ title, content } = req.body;
try{
const note =
// 노트의 업데이트 함수에 전달하고 반환해서
Note.update(id, title, content);
// 반환 받은 값을 json화
res.json(note);
// update에서 에러를 던지면 여기서 잡아서 에러 미들웨어 실행
} catch(e) {
next(e);
}
});
---models/note.js
exports.delete = (id) => {
// some : 특정 조건에 맞는 요소가 있는지 찾아 t/f 반환
// 요소가 없다면 에러 투척
if(!notes.some((note) => note.id === id)) {
throw new Error (
`Note not found for delete`
);
}
// 삭제 대상 외의 것들을 모아서 노트목록 재구성
notes = notes.filter(not => note.id !== id);
//삭제시 리턴값 필요 없음
return;
}
---routes/notes.js
router.put('/:id', (req, res, next)=> {
const id = Number(req.params.id);
try{
Note.update(id, title, content);
res.json(note);
} catch(e) {
next(e);
}
});
---index.js
app.use(express.json());
---index.js
app.use((err, req, res, next) =>{
res.status(500);
res.json({
result: 'fail',
error: err.message,
});
});
---index.js
app.use((req, res, next) =>{
res.status(404);
res.send({ result: 'fail',
error: `Page not found ${req.path}`
});
});
-API를 테스트할 수 있는 도구로 HTTP 요청을 손쉽게 작성하여 테스트 할 수 있게 도움.
-또한 API를 문서화할 수 있는 기능 및 다양한 도구를 제공함.
API 문서화
collection 만들기
api request 만들기
api와 collection에 document 작성
전체 문서 확인
API 테스트
HTTP method 설정
query param 사용
path variable 사용
body 사용