내배캠 70일차

·2023년 1월 22일
0

내일배움캠프

목록 보기
75/142
post-thumbnail

사용한 github주소

기본적인 crud예제 프로그램 만들기

기본설정

terminal

npm init -y
npm i express dotenv
npm i -D typescript
npm i -D @types/node @types/express @types/dotenv
npm i -D ts-node-dev 

tsc --init

tsconfig.json

{
  // include : 컴파일할 파일 경로를 설정합니다. [ src폴더 하위의 모든 .ts 확장자를 가진 파일 ]
  "include": ["src/**/*.ts"],
  "compilerOptions": {
    "lib": ["ES2021","DOM"],
    // esModuleInterop 속성이 위의 코드 처럼 true로 설정될 경우, ES6 모듈 사양을 준수하여 CommonJS 모듈을 가져올 수 있게 됩니다.
    // e.g. typescript-test.ts => import express from "express"
    "esModuleInterop": true,
    // 타입스크립트가 모듈을 찾는방법을 지정
    "moduleResolution":"NodeNext",
    "target": "ES2021",
    // rootDir : 컴파일될 타입스크립트 코드들의 위치를 명시합니다. 
    // "rootDir": "src",
    // outDir : 컴파일 후 생성되는 js파일이 생성될 폴더명
    "outDir": "dist",
    // strictNullChecks
    "strictNullChecks": true,
    // 암시적 any 타입을 허용하지 않는다   
    "noImplicitAny": true
  }
}

package.json

ts-node-dev : nodemon 같은 것, 파일이 변경되면 자동으로 변경된 ts파일을 실행시켜준다!

• --transpile-only: 타입스트립트의 빠른 트랜스파일 모듈 사용.
• src/index.ts: 엔트리파일 지정.

"dev": "ts-node-dev --transpile-only src/index.ts"

.env

PORT=6600

index.ts

// Required External Modules - 모듈
import dotenv from "dotenv";
import express, { Request, Response } from "express";

dotenv.config();

// App Variables - 앱 변수 선언
//포트가 없으면 프로그램 종료
if (!process.env.PORT) {
  process.exit(1);
}

const PORT: number = parseInt(process.env.PORT as string, 10);
const app = express();

// App Configuration - JSON 형식으로 데이터를 전달받기위해서
app.use(express.json());

// Server Activation - 서버 활성화
app.get("/", (req: Request, res: Response) => {
  res.send("Hi");
});

app.listen(PORT, () => {
  console.log(`Listening on port http://localhost:${PORT}`);
});

items

item.interface.ts

기본이 되는 BaseItem 인터페이스와
BaseItem을 상속받을 Item 인터페이스를 만든다.

Item ⇒ 특정한 값을 검색하거나 삭제할때 사용
BaseItem ⇒ 아이템을 수정, 등록 할때 사용

export interface BaseItem {
  name: string;
  price: number;
  description: string;
  image: string;
}

export interface Item extends BaseItem {
  id: number;
}

items.interface.ts

아이템들을 합치기위한 items 인터페이스 생성

item.interface 로부터 Item을 가져와서 Items 인터페이스 생성 후 내보냄

import { Item } from "./item.interface";

export interface Items {
  [key: number]: Item;
}

[key: number]: Item;
이러한 부분을 타입스크립트에서 인덱스 시그니처 라고 합니다.
=> 이런 형식

Items = {
  1: { id: 1, name: "item1", price: 100, description: "This is item1", image: "item1.jpg" },
  2: { id: 2, name: "item2", price: 200, description: "This is item2", image: "item2.jpg" },
  3: { id: 3, name: "item3", price: 300, description: "This is item3", image: "item3.jpg" },
};

서비스 구현

items.service.ts

// 인터페이스 불러오기
import { BaseItem, Item } from "./item.interface";
import { Items } from "./items.interface";
// 메모리에 데이터 저장
let items: Items = {
  1: {
    id: 1,
    name: "Burger",
    price: 599,
    description: "Tasty",
    image: "https://cdn.auth0.com/blog/whatabyte/burger-sm.png",
  },
  2: {
    id: 2,
    name: "Pizza",
    price: 299,
    description: "Cheesy",
    image: "https://cdn.auth0.com/blog/whatabyte/pizza-sm.png",
  },
  3: {
    id: 3,
    name: "Tea",
    price: 199,
    description: "Informative",
    image: "https://cdn.auth0.com/blog/whatabyte/tea-sm.png",
  },
};
// Service Methods - findAll, find, create, update, remove
export const findAll = async (): Promise<Item[]> => Object.values(items);

export const find = async (id: number): Promise<Item> => items[id];

export const create = async (newItem: BaseItem): Promise<Item> => {
  const id = new Date().valueOf();

  items[id] = {
    id,
    ...newItem,
  };

  return items[id];
};

export const update = async (
  id: number,
  itemUpdate: BaseItem
): Promise<Item | null> => {
  const item = await find(id);

  if (!item) {
    return null;
  }

  items[id] = { id, ...itemUpdate };

  return items[id];
};

export const remove = async (id: number): Promise<null | void> => {
  const item = await find(id);

  if (!item) {
    return null;
  }

  delete items[id];
};
  • Object.values(items) : items의 value를 배열로 보여줌
    [{id:~, name:~}, {id:~, name:~}, {id:~, name:~}] 이런식
    Object.values

  • valueOf() : 원시값 반환

사용할 API

# get all items - findAll
GET /api/menu/items

# get a single item using an id parameter - find
GET /api/menu/items/:id

# create an item
POST /api/menu/items

# update an item using an id parameter
PUT /api/menu/items/:id

# remove an item using an id parameter
DELETE /api/menu/items/:id

라우터 생성

items.router.ts

// 외부 모듈 및 인터페이스 불러오기
import express, { Request, Response } from "express";
import * as ItemService from "./items.service";
import { BaseItem, Item } from "./item.interface";

// 라우터 정의
export const itemsRouter = express.Router();

// 컨트롤러 구현
// GET items - findAll
itemsRouter.get("/", async (req: Request, res: Response) => {
  try {
    const items: Item[] = await ItemService.findAll();

    res.status(200).send(items);
  } catch (e) {
    res.status(500).send(e.message);
  }
});

// GET items/:id - find
itemsRouter.get("/:id", async (req: Request, res: Response) => {
  try {
    const id: number = parseInt(req.params.id, 10);
    const item: Item = await ItemService.find(id);

    if (item) {
      return res.status(200).send(item);
    }

    res.status(404).send("item not found");
  } catch (e) {
    res.status(500).send(e.message);
  }
});

// POST items - create
itemsRouter.post("/", async (req: Request, res: Response) => {
  try {
    const item: BaseItem = req.body;

    const newItem: Item = await ItemService.create(item);

    res.status(201).json(newItem);
  } catch (e) {
    res.status(500).send(e.message);
  }
});

// PUT items/:id - update
itemsRouter.put("/:id", async (req: Request, res: Response) => {
  try {
    const id: number = parseInt(req.params.id, 10);
    const itemUpdate: Item = req.body;

    const existingItem: Item = await ItemService.find(id);

    if (existingItem) {
      const updatedItem = await ItemService.update(id, itemUpdate);
      return res.status(200).json(updatedItem);
    }

    const newItem = await ItemService.create(itemUpdate);

    res.status(201).json(newItem);
  } catch (e) {
    res.status(500).send(e.message);
  }
});

// DELETE items/:id - remove
itemsRouter.delete("/:id", async (req: Request, res: Response) => {
  try {
    const id: number = parseInt(req.params.id, 10);
    const result: void | null = await ItemService.remove(id);

    if (result === null) {
      return res.status(404).send("item not found");
    }
    res.sendStatus(204);
  } catch (e) {
    res.status(500).send(e.message);
  }
});

index.ts 에 router 추가

import { itemsRouter } from "./items/items.router";

app.use("/api/menu/items", itemsRouter);
profile
개발자 꿈나무

0개의 댓글