(베이커리 이커머스 프로젝트 3일차)
깃헙 develop 브랜치와 팀원들 feature 브랜치 사이의 간극이 벌어지지 않게 하려고 노력중. 와중에 발생한 무수히 많은 병합 충돌을 처리하며 브랜치 사이의 ‘간극’에 점점 더 치를 떨게 됨. 머지않아 풀 리퀘스트 빌런, PR 무새가 될 것 같다.
…저기, 깃헙 본인 브랜치에 푸시 해주신 건 좋아요..! 이제 PR도 해주세요. 겁먹지 마세요 PR만으로는 문제가 되지 않아요 충돌 해결하는 리뷰어만 힘을 내면 됩니다..! pull 자주 받아주셔서 감사합니다. 본인 코드도 자주 풀 리퀘 해주세요… 허허 저희 언제 한 번 다같이 화면 켜두고 풀 → 풀 리퀘 사이클 한 번 돌아볼까요.
오늘 한 일
- ejs 템플릿 구조 분석을 마쳤다.
- nodemon과 Joi를 API 테스트에 활용함.
⇒ 수정할 때마다 서버 재실행하고 Postman으로 일일이 버튼 클릭해서 쓰던 때보다 너무나 편리하다.
// package.json "scripts": { "start": "nodemon app.js" }, // nodemon.json 설정파일 없이 그냥 이걸로 충분한가? => 충분하다
// api.rest 예시 GET http://localhost:7000/products ### POST http://localhost:7000/products/admin Content-Type: application/json { "product_name": "Chocolate Cup Cake", "product_price": "3200", "product_detail": "촉촉한 초코 컵케익", "product_image": "public/img/super-moist-chocolate-cupcakes-524176-1.jpg" } ###
- ‘상품’ CRUD 완성함.
빵 이미지 출처:
https://labaking.com/#!products/desserts/29/black-forest/
이미지 저장하는 방법들
sdk s3 bucket
multer
내일 할 일:
- order 테이블에 ‘status’ 필드를 추가해야 할지 고민해보기
- 프론트 구현
- (옵션)회원가입/로그인 기능 살펴보기
- admin 미들웨어에서 곧바로 DB 모델을 호출하는 것이 괜찮은가?
- (옵션)테스트에 Joi 활용을 고민중.
(앞으로 사용하게 될 docs들)
express-ejs-layouts 모듈 사용법 - https://www.npmjs.com/package/express-ejs-layouts
sequelize (구체적) api 문서 - https://sequelize.org/v3/api/model/
express.js res.render()와 그 외 문서 - https://www.geeksforgeeks.org/express-js-res-render-function/
어느 계층에서 발생한 에러인가 - error.stack
어느 계층에서 발생한 에러인가 - error.stack
- 다음과 같이 컨트롤러 계층에서:
// controllers/user.controller.js findUserInfo = async (req, res) => { // const { user_id } = req.locals.user; const user_id = 4; try { const user = await this.UserService.findUserInfo(user_id); return res.status(200).json({ user, }); } catch (e) { return res.json({ error: e, errorMessage: e.message, errorStack: e.stack, }); } };
- 서비스 계층에서:
// services/user.service.js findUserInfo = async (user_id) => { try { const user = await this.UserRepository.findUserInfo(user_id); return user; } catch (e) { e.name = 'service layer error'; e.message = '서비스 계층에서 문제 발생.'; e.status = 500; throw e; } };
- 레파지토리 계층에서:
// repositories/user.repository.js findUserInfo = async (user_id) => { try { const user = await this.userModel.findByPk(user_id); return user; } catch (e) { e.name = 'Database Error'; e.message = '요청을 처리하지 못하였습니다.'; e.status = 500; throw e; } };
각 계층에서 각각 다른 에러 메세지와 코드를 넘겨서, 만약 에러가 발생할 시 어디로부터 기인한 에러인지를 알고자 하였다. 그러나 위와 같이 쓰면 실은 레파지토리 계층에서 에러가 발생했더라도, 서비스 계층의 catch 문을 넘어오면서 e.status와 e.mesage 등이 덮어씌워지는 형국이라 내가 원하는 목적을 이룰 수는 없었다.
알아보니 error.stack
이라는 속성으로 에러가 발생한 위치를 파악할 수 있다고 한다.
updateProduct = async (req, res, next) => {
const { id } = req.params;
const { product_name, product_price, product_detail, product_image } =
req.body;
// ...
// 상품 업데이트 진행
try {
...
} catch (error) {
return res.status(500).json({
errorMessage: error.message,
errorStack: error.stack.split("\n")[1].trim(),
});
}
};
// => errorStack 값 예시:
"errorStack": "at ProductService.updateProduct (C:\\Users\\...\\services\\product.service.js:52:13)",
⇒ 이와 같이 하면 errorStack에는 에러가 발생한 첫 위치가 담기게 된다.
튜터 문답 - 계층화에서 발생하는 자잘한 고민과 팁
튜터 문답 - 계층화에서 발생하는 자잘한 고민과 팁
- 계층을 나누니 예를 들어 유저 정보를 업데이트 한다고 할 때, find메소드로 존재 유무를 검색하는 데에 한 번, 다시 update메소드를 돌릴 때 또 한 번 검색이 발생하게 된다. 이게 처리 속도에 영향을 많이 미칠까 하여 튜터에게 물어보니 findByPk()는 검색 속도가 충분히 빨라서 괜찮고, 만약 findOne 같이 조건절로 훑어야 하는 경우라면 속도에 지장이 꽤 있을 거라고 한다.
- update 메소드의 서비스 계층에 굳이 find로 존재 유무를 한 번 안 걸러줘도 된다고 하는데… 그러면 레파지토리 계층에서 ‘없음’에 대한 반환값 null에 대하여 에러를 던져주면 되는건가? 레파지토리 계층에서도 그렇게 에러를 처리하기도 하는지 궁금하다.
- 실무에서 보통은 update나 delete 작업 이후에 수정/삭제된 데이터를 (굳이 확인하려고) res에 담아보내지 않는다고 한다. 처리 후 처리된 행 개수나 단순히 처리됐다/안됐다 정도만 반환한다고 함.
- 원하는 필드들을 추리거나 데이터를 정렬하는 것 같은 처리는 서비스 계층에서 하는 것보다 레파지토리 계층에서 하는 것을 더 추천한다고 함. 내 생각도 같음.
- ⇒ 그런 작업은 DB가 처리하는 게 보통 더 빠르기 때문
- ⇒ 레파지토리에서 처리하게 만들면, 프론트단에서 ‘원하는 필드명들만 인자로 주문받아서’ 해당하는 필드가 테이블에 존재하는지를 보고 존재하면 쿼리하여 가져오는 식으로 만들 수도 있다는 장점이 있다. ‘원하는 필드명’들은
…args
로 파라미터를 받으면 프론트단 입장에서는 얼마든지 원하는 필드들을 바꿔 주문할 수 있고, 레파지토리 계층 입장에서는 하나의 메소드만 만들어 그걸로 유연하게 주문을 처리할 수 있게 된다.
Uploaded by N2T