10/16/2024

화살표 메서드 vs. 정규 메서드

프로젝트를 진행하면서 클래스의 메서드를 구현하다 갑자기 궁금증이 생겼다. 화살표 함수와 일반 함수 중 무엇을 사용해야 할까? 아니면 차이가 없나? 각각의 장단점이 명확하기에 이에 대해 알아본다.


prototype 속성

클래스에서 일반 함수로 메서드를 정의하면 메서드는 클래스의 prototype 속성에 추가된다. 그래서 클래스의 모든 인스턴스가 동일한 메서드를 공유하며 메서드가 각 인스턴스마다 복사되지 않는다. 메서드가 공유되기 때문에 메모리 사용량을 줄일 수 있다. 이와 반대로, 화살표 함수로 메서드를 정의하면 속성으로 취급하며 prototype 속성이 아닌 각 인스턴스에 직접 정의된다. 따라서, 각 인스턴스가 화살표 함수의 복사본을 가지며 일반 메서드처럼 공유되지 않는다. 메모리 효율성 측면에서 메서드는 일반 함수로 정의하는 것이 좋다. 


this 예약어

일반 함수로 정의된 메서드는 메서드가 인스턴스에서 호출될 때 this 예약어가 클래스 인스턴스를 가리킨다. 메서드가 콜백으로 전달되거나 인스턴스 컨텍스트 없이 호출될 때 문제가 발생할 수있다. 경우에 따라서 this 예약어가 정의되지 않거나(strict 모드) 전역 객체를 참조한다(non-strict 모드). 즉, 호출되는 방식에 따라 this 예약어 값이 결정되기 때문에 인스턴스에서 직접 호출되면 인스턴스를 가리키나 컨텍스트 없이 호출되거나 콜백으로 전달될 경우 값이 손실될 수 있다. 반면에 화살표 함수로 정의된 메서드는 정의된 컨텍스트에 this 예약어를 바인딩하며 호출되는 방식에 따라 this 예약어 값이 변경되지 않는다. 즉, 화살표 함수는 콜백으로 전달되거나 다른 컨텍스트에서 사용될 때도 올바른 값을 유지한다.


결론

클래스가 자주 인스턴스화되고 메모리 효율성을 고려해야 하는 경우 일반 메서드를 사용하지만 클래스가 인스턴스화 되는 경우가 적거나 싱글톤이고 클래스가 복잡하여 간소화와 유지 보수를 원하는 경우 혹은 메서드를 콜백으로 자주 사용할 경우 화살표 메서드를 사용한다. 각 서비스의 애플리케이션과 컨트롤러 함수의 공통 메서드는 일반 함수로 구현했다. 컨트롤러의 각 API는 일반 함수로 구현하는 편이 더 좋을 것 같은데 catchAsync() 함수를 포함하고 1번 밖에 호출되지 않기 때문에 화살표 함수로 구현했다. 이메일, JWT, Redis와 같은 유틸 클래스의 메서드는 빈번히 호출되기 때문에 일반 함수를 사용했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// UserController deleteMe()
private deleteMe = catchAsync(
  async (
    request: RequestWithUser,
    response: Response,
    next: NextFunction,
  ): Promise<void> => {
    if (request.user!.banned) {
      return next(
        new UnauthorizedUserError(
          Code.FORBIDDEN,
          '차단되어서 회원탈퇴를 할 수 있는 권한이 없습니다.',
        ),
      );
    }
 
    await this.repository.update(
      { _id: request.user!.id },
      { active: false, deletedAt: Date.now() },
    );
 
    const success = ApiResponse.handleSuccess(
      Code.NO_CONTENT.code,
      Code.NO_CONTENT.message,
      null,
      '회원탈퇴 했습니다.',
    );
 
    response.status(Code.OK.code).json(success);
  },
);
 
// JwtUil issue()
public static issue(payload: JwtPayload): JwtBundle {
  return {
    accessToken: this.build(
      payload,
      this.ACCESS_TOKEN_SECRET,
      this.ACCESS_TOKEN_EXPIRATION
    ),
    refreshToken: this.build(
      payload,
      this.REFRESH_TOKEN_SECRET,
      this.REFRESH_TOKEN_EXPIRATION
    ),
  };
}
 
cs

update: 2024.10.16

댓글 없음:

댓글 쓰기