express 프로젝트에 3-layered-architecture를 적용하던 도중에 에러가 발생했다. 코드는 다음과 같다.
router
const productController = new ProductController();
router.get("/products", productController.findAllProducts);
controller
productService = new ProductService();
async findAllProducts(req, res, next) {
try {
let sort = req.query.sort ? req.query.sort.toUpperCase() : "DESC";
sort = ["ASC", "DESC"].includes(sort) ? sort : "DESC";
const result = await this.productService.findAllProducts(sort);
return res.status(200).json(result);
} catch (e) {
next(e);
}
}
service
productRepository = new ProductRepository();
async findAllProducts(sort) => {
const products = await this.productRepository.getAllProduct(sort);
return {
ok: true,
message: "상품을 성공적으로 조회하였습니다.",
data: products
};
}
repository
async getAllProduct(sort) {
const products = await this.db.products.findMany({
include: {
users: {
select: { name: true }
}
},
orderBy: {
createdAt: sort.toLowerCase(),
}
});
return products;
}
error
원인은 router와 controller를 연결할때 this가 동적으로 바뀌어 발생한 문제였다.
router
const productController = new ProductController();
router.get("/products", productController.findAllProducts);
controller
productService = new ProductService();
async findAllProducts(req, res, next) {
...
}
위의 코드에서 controller는 일반 메서드이기 때문에 this의 값은 동적으로 상위 스코프의 따라 결정된다. 이 메서드를 router.get에서 콜백함수로 넘겨주었기 때문에 productController.findAllProducts의 this는 router가 된다.
일반 함수의 this는 상위 스코프에 따라 동적으로 할당되지만, 화살표 함수의 this는 함수가 정의될때 정적으로 할당되어 변하지 않는다.
일반 함수와 달리 화살표 함수는 this가 정적으로 할당되어 변하지 않기 때문에 controller를 화살표 함수로 변경한다.
router
const productController = new ProductController();
router.get("/products", productController.findAllProducts);
controller
productService = new ProductService();
findAllProducts = async (req, res, next) {
...
}
일반 함수의 this를 bind를 통해 직접 할당해주어서 문제를 해결한다.
router
const productController = new ProductController();
router.get("/products", productController.findAllProducts.bind(productController));
controller
productService = new ProductService();
async findAllProducts(req, res, next) {
...
}