CDR4733 / nine-shop

0 stars 0 forks source link

Node.js 개인과제 피드백 - 정영훈 튜터 #3

Open jyh7a opened 4 weeks ago

jyh7a commented 4 weeks ago

첫 노드 과제 하느라 고생 많으셨습니다.

README를 어떤 부분까지 테스트가 되었는지 파악하기 쉽게 잘 작성해주었습니다!

branch도 1-upload브랜치에서 작업하고 main으로 잘 PR하였습니다. 다만 바로 main으로 PR하기 보다는 만들어둔 dev로 PR후 테스트하고 정상적으로 동작하면 다시 dev -> main 브랜치로 PR해 주세요.

git commit도 잘 작성하였지만 아래 링크를 참고하여서 조금더 체계화된 커밋 메세지를 적으시면 앞으로 팀원들과 협업할때 더 편하게 서로의 커밋 메세지만 보고 어떤 작업을 하였는지 파악 할 수 있습니다. git commit message convention: https://velog.io/@archivvonjang/Git-Commit-Message-Convention

현재 .env를 사용하지 않아서 dbUserName, dbPassword가 노출되고 있으니 dbPassword는 꼭 변경해주시고. 튜터님들 찾아와서 어떤 에러가 있어서 .env사용시 에러가 나는지 파악후 수정해야합니다.

아래는 프로젝트 피드백입니다.


1. 과제 제출 질문 답변

Q) 3. API 명세서를 작성해야 되는 이유는 무엇인가요? A) 외부 개발자 뿐만 아니라 내부 개발자들도 API명세를 보고 어떤 기능을 어떤형식으로 개발해야할 지 이해할 수 있습니다. 주로 백엔드 프론트 개발자가API명세서를 보고 서로의 기능을 개발합니다.

Q) 8. 대표적인 Http Status Code는 무엇이며, 각각은 언제 사용하나요? A) 500 서버에러 까지 추가해주시면 됩니다.

Q) 10. API 설계 시 RESTful하게 설계한다는 것은 무엇인가요? A) RESTful API는 리소스 경로 HTTP 메소드 기반으로 설계하는 것입니다.

Q) 11. 비밀번호 저장 시 평문으로 저장하면 DB 유출 시 문제가 됩니다. 어떻게 저장해야 안전하게 저장할 수 있을까요? A) 비밀번호는 해싱을 통해 저장해야 합니다. bcrypt와 같은 해시 함수를 사용하여 비밀번호를 일방향으로 변환 하면 다시 값을 되돌릴 수 없어서 보안적으로 조금더 안전합니다. 암화화는 암호키를 가지고 복원할 수 있어서 보안에 조금 더 취약합니다.

Q) 13. 과제 하면서 어려웠던 기술적인 부분을 적어주세요. A) 이 부분은 보안과 관련해서도 중요하기때문에 튜터님들 찾아와서 어떤에러가 있는지 파악 후 꼭 수정해야합니다!




2. 유효성 검사 코드 위치 수정

https://github.com/CDR4733/nine-shop/blob/69d6dcf1ed26efddd61118449e0ae5e6939f8e47/src/routers/products.router.js#L15-L30 const existingName = await Products.findOne({ name }).exec(); 이 코드는 유효성 검사보다는 데이터베이스 중복 검사입니다. if (!name || !description || !manager || !password) { 이 코드가 유효성 검사 코드입니다. 유효성 검사 코드를 데이터 베이스 중복 검사 코드 보다 위로 올려주세요. 이유는 name이 없다면 중복 검사코드에서 에러가 발생하게 됩니다.
name이 있을때만 데이터베이스 중복검사 코드를 실행 하도록 수정해 주세요.




3. 비동기 로직 에러 처리

https://github.com/CDR4733/nine-shop/blob/69d6dcf1ed26efddd61118449e0ae5e6939f8e47/src/routers/products.router.js#L166-L168 상품 삭제 라우터를 예로 들어봅시다. 만약 productId에 mongodb에서 사용하는 id형식이 아니라 1, 2 , abc 이런 값이 들어온다면 에러가 나면서 서버가 멈추게 됩니다. 어떻게 이런 예상하지 못한 에러를 대비할 수 있을까요? 바로 try catch 구문입니다. try catch 구문으로 변경 후 productId값을 변경해서 테스트해보세요.

예)

/** 상품 삭제(D),[DELETE],'/products/:id' API **/
router.delete("/products/:productId", async (req, res, next) => {
  try {
    // 1. 경로매개변수에서 productId 가져오기
    const { productId } = req.params;
    // 2. 현재 나의 product를 조회해온다
    const currentProduct = await Products.findById(productId).exec();
    // 3. 유효성 검사
    // 3-1. 만약 해당 id의 상품이 존재하지 않는 경우 -> 404, 상품이 존재하지 않습니다.
    if (!currentProduct) {
      return res.status(404).json({
        status: "404",
        message: "상품이 존재하지 않습니다.",
      });
    }
    // 3-2. 비밀번호
    const { password } = req.body;
    // 3-2-1. 비밀번호를 입력하지 않은 경우 -> 400, 비밀번호를 입력하지 않았습니다.
    if (!password) {
      return res.status(400).json({
        status: "400",
        message: "비밀번호를 입력해주세요.",
      });
    }
    // 3-2-2. 만약 비밀번호가 일치하지 않는 경우 -> 400, 비밀번호가 일치하지 않습니다.
    if (password !== currentProduct.password) {
      return res.status(401).json({
        status: "401",
        message: "비밀번호가 일치하지 않습니다.",
      });
    }
    // 4. 삭제한다.
    await Products.deleteOne({ _id: productId });
    // 5. 삭제된 결과를 클라이언트에 반환한다.
    return res.status(200).json({
      status: "200",
      message: "상품 삭제에 성공했습니다.",
      data: {
        id: productId,
      },
    });
  } catch (error) {
    console.log(error)
  }  
});




4. 에러 처리 미들웨어 사용

이제 에러 처리 미들웨어를 사용해 봅시다. 일단 error-handler.middleware에 에러 처리 함수를 작성합니다. 에러 처리 함수에 첫번째 매개변수에는 err가 들어가야합니다. 그 후에 에러를 출력, 에러 상태 코드 확인 그리고 적절한 에러 메세지와 함께 클라이언트에게 전달하면됩니다. 아래 코드를 순서대로 작성 후 어떻게 이 에러 로직이 실행되는지 테스트하고 스스로에게 설명해 보세요!

export default errorHandler;


- index.js
```javascript
import express from "express";
import connect from "./schemas/index.js";
import productsRouter from "./routers/products.router.js";
import errorHandler from "./middlewarmies/error-handler.middleware.js";

const app = express();
const PORT = 3000;

// ... 생략

// 에러 처리 
app.use(errorHandler);

app.listen(PORT, () => {
  console.log(PORT, "포트로 서버가 열렸어요!!");
});

products.router.js

/** 상품 삭제(D),[DELETE],'/products/:id' API **/
router.delete("/products/:productId", async (req, res, next) => {
  try {
    // 1. 경로매개변수에서 productId 가져오기
    const { productId } = req.params;
    // ... 생략 
    });
  } catch (error) {
    next(error)
  }  
});
CDR4733 commented 4 weeks ago
  1. Q13> 과제 하면서 어려웠던 기술적인 부분을 적어주세요. => .env 적용 안되는 문제 이 부분은 결국 ubuntu에서 .env 파일을 자체적으로 직접 만들어주는 방식(vim .env)으로 해결했습니다. 이에 따라 밖으로 노출되어있던 코드도 다시 수정해서 ubuntu에서 새로 pull 했습니다!
CDR4733 commented 4 weeks ago
  1. 유효성 검사 코드 위치 수정 => 수정 완료했습니다!!