[express.js] 화살표 함수와 일반 함수의 차이(this)

김지엽·2023년 12월 4일
0
post-thumbnail
post-custom-banner

1. 개요

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

2. 문제 원인

원인은 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는 함수가 정의될때 정적으로 할당되어 변하지 않는다.

3. 해결 방법

- 일반 함수 -> 화살표 함수

일반 함수와 달리 화살표 함수는 this가 정적으로 할당되어 변하지 않기 때문에 controller를 화살표 함수로 변경한다.
router

const productController = new ProductController();
router.get("/products", productController.findAllProducts);

controller

productService = new ProductService();

findAllProducts = async (req, res, next) {
    ...
}

- bind 사용하기

일반 함수의 this를 bind를 통해 직접 할당해주어서 문제를 해결한다.

router

const productController = new ProductController();
router.get("/products", productController.findAllProducts.bind(productController));

controller

productService = new ProductService();

async findAllProducts(req, res, next) {
    ...
}

참고

arrow function
bind

profile
욕심 많은 개발자
post-custom-banner

0개의 댓글