컴퓨터 공학 & 통신

[개념 정리] 클래스 - static 장단점

왈왈디 2023. 6. 30. 20:03
728x90

class에서 사용하는 static을 처음 사용해본 것은

NestJS로 프로젝트를 진행하며,

entity class 내에서 다른 class의 메서드를 사용하고자 했으나

entity class 내에서는 다른 클래스의 인스턴스화가 어려워 일반 메서드를 사용하기 어려웠다.

그때 필요한 메서드를 static 메서드로 만드니 사용할 수 있었다.

 

당시에는 static 방식이 인스턴스를 만들지 않고도 메서드와 속성을 사용할 수 있어 만능처럼 느껴졌으나,

static에는 장단점이 존재한다.

 

Static

static은 인스턴스가 아닌 클래스에 속하며, 클래스의 변수나 메서드 등을 공유하는데 사용된다. 

이를 통해 해당 클래스로 만들어지는 객체 사이에서 중복되는 메서드, 속성 등을 효율적으로 정의할 때 쓰인다.

단순히 전역 변수가 아니라,

static 키워드로 선언하여 이 클래스 내 객체들끼리 사용되는 메서드 또는 속성이다.

 

자바스크립트 예시를 살펴보자.

class Bungeoppang {
	constructor(doughQuantity = 100, sauceType = '팥', sauceQuantity = 100){
    	this.dougnQuantity = doughQuantity;
        this.sauceType = sauceType;
        this.sauceQuantity = sauceQuantity;
    }
    
    ready(){
    	console.log('주문하신 ' + this.sauceType + ' 붕어빵 나왔습니다.')
    }
    
    static askSauceType(){
    	console.log(`무슨 맛으로 드릴까요?`);
    }
    
    static dough = '밀가루';
}

const pizzaBung = new Bungeoppang(120, '피자', 120);

pizzaBung.ready(); //'주문하신 피자 붕어빵 나왔습니다.'
Bungeoppang.askSauceType(); //"무슨 맛으로 드릴까요?"
console.log(Bungeoppang.dough); //'밀가루'

붕어빵 예시에 소 종류를 묻는 static 메서드와, dough라는 static 속성을 추가했다.

아래 처럼 인스턴스를 선언하지 않고도 Bungeoppang 클래스에서 static 메서드와 static 속성을 바로 사용할 수 있다.

 

 

아래는 내가 NestJS, TypeScript 프로젝트에서 선언했던 static 메서드이다.

//src/utils/utils.service.ts 
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import * as crypto from 'crypto';

@Injectable()
export class UtilsService {
  constructor(
    public readonly jwtService: JwtService,
    readonly config: ConfigService,
  ) {}

  static hashPassword(password: string, salt: string): string {
    return crypto
      .pbkdf2Sync(password, salt, 1000, 32, 'SHA512')
      .toString('base64');
  }

  static createSalt(): string {
    return crypto.randomBytes(64).toString('base64');
  }
 }

위와 같이 utils class에서 static으로 정의한 메서드를

아래와 같이 BaseUser class에서 인스턴스를 만들지 않고 UtilsService class에서 바로 꺼내어 사용했다.

//src/users/entities/base-user.entity.ts 

import { UnauthorizedException } from '@nestjs/common';
import { Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
import { UtilsService } from 'src/utils/utils.service';

export class BaseUser {
  @Column({ nullable: false, unique: true })
  email: string;

  @Column({ nullable: false })
  password: string;

  @Column({ name: 'password_salt' })
  passwordSalt: string;

  @Column({ name: 'refresh_token', nullable: true })
  refreshToken: string;

  @Column({ nullable: false })
  name: string;

  @Column({ name: 'phone_number', unique: true, nullable: false })
  phoneNumber: string;

  @Column({ name: 'marketing_agreement' })
  marketingAgreement: boolean;

  @CreateDateColumn({ type: 'timestamp', name: 'created_at' })
  createdAt: Date;

  @UpdateDateColumn({ type: 'timestamp', name: 'updated_at' })
  updatedAt: Date;

  updatePassword(password: string): void {
    this.passwordSalt = UtilsService.createSalt();
    this.password = UtilsService.hashPassword(password, this.passwordSalt);
  }
 }

 

단점

(자바 기준) static으로 선언된 변수, 블록, 메서드는 선언과 동시에 heap영역이 아닌 method area 라는 별도의 메모리 영역에 할당 되며 프로그램이 종료될 때까지 Garbage Collector에 의해 메모리가 회수되지 않는다.

때문에 반드시 필요한 경우에 사용하는 것이 아니라면 메모리 낭비를 불러올 수 있다는 단점이 있다.

마구잡이로 사용해서는 안되고, 어느쪽이 더 효율적일지를 판단해가며 사용하자.

 

참고: inflearn 강의 'CS 지식의 정석 - 큰돌'

728x90