React

Swagger로 Express AP를 문서화하기

Asset Type
express
swagger
File Type
When to use
2022/04/03
Created time
2022/04/03 17:52
Created by
Last edited time
2022/05/07 13:15
해당 글은 댓글에 정상적인 코드가 있기 때문에 맨 마지막에 코드를 첨부했습니다.
먼저 위 프로젝트의 템플릿을 클론합니다.
이는 해당 작업을 경로에 명시적으로 매핑해야 하기 때문에 발생합니다. 그렇지 않으면 Swagger가 자체적으로 API 끝점을 파악할 수 없습니다.
Swagger는 소스 코드에 액세스하거나 네트워크 트래픽을 검사하지 않고도 인간과 기계가 웹 서비스의 기능을 이해할 수 있도록 하는 RESTful API용 표준 언어 불가지론적 인터페이스인 Open API 사양을 사용합니다.
각 버전에 사용 가능한 모든 설정은 공식 문서를 참조하세요. 여기서는 API 정보, 이름, 제목, 설명, 라이선스, API 소유자 연락처 등의 기본 사항만 사용합니다.
API의 속성은 모델 및 엔드포인트 정의를 검색하기 때문에 필수적이므로 정확하게 알려주십시오.
마지막으로 swaggerJsdoc함수를 사용하여 매개변수로 전달된 옵션을 스캔하고 변환된 Swagger 사양 개체를 반환합니다. 이것은 차례로 swaggerUi설정 프로세스와 함께 사용할 수 있습니다.
이제 npm start명령을 통해 애플리케이션을 시작할 수 있습니다. http://localhost:3000/api-docs/ URL 에 액세스하면 다음 화면이 표시됩니다 .
app.use( "/api-docs", swaggerUi.serve, swaggerUi.setup(specs, { explorer: true }) );
Plain Text
복사
선택적으로 API에 너무 많은 작업이 있는 경우 UI에 검색 창을 추가할 수 있습니다. 이를 위해 구현을 다음과 같이 변경합니다.

Creating the model

routes/books.js에 가서 맨 위에 넣습니다.
/** * @swagger * components: * schemas: * Book: * type: object * required: * - title * - author * - finished * properties: * id: * type: integer * description: The auto-generated id of the book. * title: * type: string * description: The title of your book. * author: * type: string * description: Who wrote the book? * finished: * type: boolean * description: Have you finished reading it? * createdAt: * type: string * format: date * description: The date of the record creation. * example: * title: The Pragmatic Programmer * author: Andy Hunt / Dave Thomas * finished: true */
Plain Text
복사
주석은 yml 형식으로 만약 필요하면 익스텐션으로 formating할 수 있다.(swagger-jsdoc comment formatter)
@swagger주석을 통해 나머지 Swagger 사양 정의를 설정하는 데 도움이 됩니다.
여기에서 원하는 만큼 스키마를 정의할 수 있습니다. 우리의 경우, 우리는 단지 도메인을 정의하고 있습니다 Books.
required 속성은 요청에서 반드시 채워야 하는 속성 목록을 수신합니다. 이 단계는 API를 사용할 때 보내야 할 내용을 사람들에게 알리는 데 필수적입니다.
속성 은 properties모델 속성에 대한 자세한 정보를 설명합니다. 각 속성에는 이름 뒤에 해당 유형, 설명(선택 사항) 및 형식(값의 유효성도 검사할 수 있음)이 있어야 합니다. 사용 가능한 데이터 유형의 전체 목록은 Swagger 데이터 유형 을 참조하십시오 .
마지막으로 이 스키마 모델에 대한 요청 데이터의 예를 제공할 수 있습니다. 나중에 유용할 것입니다.
/** * @swagger * tags: * name: Books * description: API to manage your books. */ /** * @swagger * path: * /books/: * post: * summary: Creates a new book * tags: [Books] * requestBody: * required: true * content: * application/json: * schema: * $ref: "#/components/schemas/Book" * responses: * "200": * description: The created book. * content: * application/json: * schema: * $ref: "#/components/schemas/Book" */
Plain Text
복사
Swagger 태그부터 시작하여 부분적으로 분석해 보겠습니다. 태그를 사용하면 Swagger 문서 내에서 섹션을 만들 수 있습니다. 이것은 이 태그에 할당된 모든 경로가 동일한 디비전 아래에 표시됨을 의미합니다. 조직적인 설정입니다.
이 예에서 모든 끝점은 동일한 태그에 매핑됩니다.
다음으로 첫 번째 경로인 책 만들기를 설정할 차례입니다. 아주 간단합니다. 먼저 제목을 정의하고 경로가 첨부될 태그를 지정합니다.
그런 다음 요청과 응답이 있습니다. 요청 내에서 요청이 필요한지 여부, 요청의 콘텐츠 유형 및 처리해야 하는 스키마의 세 가지를 정의합니다.
#components/schemas스키마는 Swagger 연산자 를 통해 참조할 수 있습니다 .
응답에 관해서는 HTTP 응답 코드와 각각의 속성을 정의하기만 하면 됩니다. 
이상적으로 이러한 매핑은 각 Express 라우팅 기능 위에 배치되어야 합니다. 그러나 단순함을 위해 한 곳에 집중하고 있습니다.
매개변수를 받는 작업과 받지 않는 작업의 두 가지 주요 범주로 작업을 분리하고 있습니다 id.이는 Swagger가 경로를 적절한 경로 매개변수와 일치시키는 방법을 이해하는 데 필요합니다.
유형에 관계없이 엔드포인트에 매개변수가 있을 때마다 매개변수 속성 아래에 세부사항을 알려야 합니다.

제대로 작동되지 않는 사람들이 있고 댓글을 보면 코드를 제공해줍니다.

1.
put this text at front of books.jsthen worksnote you must write “paths”… in the example it was just “path”
/*** @swagger* tags:* name: Books* description: API to manage your books.* paths:* /books/:* get:* summary: Lists all the books* tags: [Books]* responses:* “200”:* description: The list of books.* content:* application/json:* schema:* $ref: ‘#/components/schemas/Book’* post:* summary: Creates a new book* tags: [Books]* requestBody:* required: true* content:* application/json:* schema:* $ref: ‘#/components/schemas/Book’* responses:* “200”:* description: The created book.* content:* application/json:* schema:* $ref: ‘#/components/schemas/Book’* /books/{id}:* get:* summary: Gets a book by id* tags: [Books]* parameters:* – in: path* name: id* schema:* type: integer* required: true* description: The book id* responses:* “200”:* description: The list of books.* content:* application/json:* schema:* $ref: ‘#/components/schemas/Book’* “404”:* description: Book not found.* put:* summary: Updates a book* tags: [Books]* parameters:* – in: path* name: id* schema:* type: integer* required: true* description: The book id* requestBody:* required: true* content:* application/json:* schema:* $ref: ‘#/components/schemas/Book’* responses:* “204”:* description: Update was successful.* “404”:* description: Book not found.* delete:* summary: Deletes a book by id* tags: [Books]* parameters:* – in: path* name: id* schema:* type: integer* required: true* description: The book id* responses:* “204”:* description: Delete was successful.* “404”:* description: Book not found.* components:* schemas:* Book:* type: object* required:* – title* – author* – finished* properties:* id:* type: integer* description: The auto-generated id of the book.* title:* type: string* description: The title of your book.* author:* type: string* description: Who wrote the book?* finished:* type: boolean* description: Have you finished reading it?* createdAt:* type: string* format: date* description: The date of the record creation.* example:* title: The Pragmatic Programmer* author: Andy Hunt / Dave Thomas* finished: true*/
JavaScript
복사
2.
ps: i forgot , you also have to chagne in server.js
url: “http://localhost:3000/books”,
tourl: “http://localhost:3000”,
이제야 동작이 됩니다!
// [rootDir]/routes/books.js /** * @swagger * tags: * name: Books * description: API to manage your books. * paths: * /books/: * get: * summary: Lists all the books * tags: [Books] * responses: * "200": * description: The list of books. * content: * application/json: * schema: * $ref: "#/components/schemas/Book" * post: * summary: Creates a new book * tags: [Books] * requestBody: * required: true * content: * application/json: * schema: * $ref: "#/components/schemas/Book" * responses: * "200": * description: The created book. * content: * application/json: * schema: * $ref: "#/components/schemas/Book" * /books/{id}: * get: * summary: Gets a book by id * tags: [Books] * parameters: * - in: path * name: id * schema: * type: integer * required: true * description: The book id * responses: * "200": * description: The list of books. * content: * application/json: * schema: * $ref: "#/components/schemas/Book" * "404": * description: Book not found. * put: * summary: Updates a book * tags: [Books] * parameters: * - in: path * name: id * schema: * type: integer * required: true * description: The book id * requestBody: * required: true * content: * application/json: * schema: * $ref: "#/components/schemas/Book" * responses: * "204": * description: Update was successful. * "404": * description: Book not found. * delete: * summary: Deletes a book by id * tags: [Books] * parameters: * - in: path * name: id * schema: * type: integer * required: true * description: The book id * responses: * "204": * description: Delete was successful. * "404": * description: Book not found. * components: * schemas: * Book: * type: object * required: * - title * - author * - finished * properties: * id: * type: integer * description: The auto-generated id of the book. * title: * type: string * description: The title of your book. * author: * type: string * description: Who wrote the book? * finished: * type: boolean * description: Have you finished reading it? * createdAt: * type: string * format: date * description: The date of the record creation. * example: * title: The Pragmatic Programmer * author: Andy Hunt / Dave Thomas * finished: true */ const express = require("express"); const router = express.Router(); const books = require("../util/data"); router.get("/", function (req, res) { res.status(200).json(books); }); router.get("/:id", function (req, res) { let book = books.find(function (item) { return item.id == req.params.id; }); book ? res.status(200).json(book) : res.sendStatus(404); }); router.post("/", function (req, res) { const { title, author, finished } = req.body; let book = { id: books.length + 1, title: title, author: author, finished: finished !== undefined ? finished : false, createdAt: new Date(), }; books.push(book); res.status(201).json(book); }); router.put("/:id", function (req, res) { let book = books.find(function (item) { return item.id == req.params.id; }); if (book) { const { title, author, finished } = req.body; let updated = { id: book.id, title: title !== undefined ? title : book.title, author: author !== undefined ? author : book.author, finished: finished !== undefined ? finished : book.finished, createdAt: book.createdAt, }; books.splice(books.indexOf(book), 1, updated); res.sendStatus(204); } else { res.sendStatus(404); } }); router.delete("/:id", function (req, res) { let book = books.find(function (item) { return item.id == req.params.id; }); if (book) { books.splice(books.indexOf(book), 1); } else { return res.sendStatus(404); } res.sendStatus(204); }); module.exports = router;
JavaScript
복사
// [rootDir]/server.js var express = require("express"), bodyParser = require("body-parser"), swaggerJsdoc = require("swagger-jsdoc"), swaggerUi = require("swagger-ui-express"); const app = express(); app.use( bodyParser.urlencoded({ extended: true, }) ); app.use(bodyParser.json()); app.use("/books", require("./routes/books")); const options = { definition: { openapi: "3.0.0", info: { title: "LogRocket Express API with Swagger", version: "0.1.0", description: "This is a simple CRUD API application made with Express and documented with Swagger", license: { name: "MIT", url: "https://spdx.org/licenses/MIT.html", }, contact: { name: "LogRocket", url: "https://logrocket.com", email: "info@email.com", }, }, servers: [ { url: "http://localhost:3000", }, ], }, apis: ["./routes/books.js"], }; const specs = swaggerJsdoc(options); app.use( "/api-docs", swaggerUi.serve, swaggerUi.setup(specs, { explorer: true }) ); const PORT = process.env.PORT || 3000; app.listen(PORT); console.debug("Server listening on port: " + PORT);
JavaScript
복사