본문 바로가기
Things I was curious about

static, private, public은 언제 사용하는걸까?

by 갈릭 deep잉 소스좋아 2024. 3. 24.

static, private, public 키워드를 개발하면서 정확히 언제 사용하는지 모르고 사용한다는 느낌을 받았다.

분명 용도가 다르니 이름이 다른 것일텐데 그 목적과 쓰임에 대해서 공부한 내용을 정리해보려고 한다!

 


static은 왜 사용하는걸까?

  • 클래스의 변수, 메서드 등을 공유하는데에 쓰인다. 이를 통해 해당 클래스로 만들어지는 객체사이에서 중복되는 메서드, 속성을 효율적으로 정의하기 위해 쓰인다.
  • 단, 선언하자마자 메모리(데이터 영역)에 올라가게 된다. 즉, 사용하지 않아도 항상 메모리 공간을 차지하게 됨.
class Person {
  name: string;
  age: number;
  iq: number;
  gender: string;
  constructor(name = "sunghwan", age = 28, iq = 120, gender = "man") {
    this.name = name;
    this.age = age;
    this.iq = iq;
    this.gender = gender;
  }

  static talk(a: Person, b: Person): void {
    console.log(`${b.name}가 ${a.name}에게 대화를 요청했다.`);
    return;
  }
}

const defaultPerson = new Person();
const artificialPerson = new Person("또 다른 나", 20, 200, "man");
Person.talk(defaultPerson, artificialPerson);

위의 코드처럼 static을 해당 class에 선언을하게 되면 해당 talk메소드를 외부에서 호출할 수 있게 되고 클래스로부터 생성되는 객체마다 해당메소드를 필드값으로 담아둘 필요없이 필요할 때만 클래스에 의해 호출을 하면 된다.

 

Deep Dive

public, static, private에 대한 특징과 차이점

  • public : 클래스 내에서 메소드를 만들 때 기본 값으로 설정되는 값이다. 해당 클래스 뿐만 아니라 외부에서도 자유롭게 접근이 가능하다.
  • static : 클래스 내부적으로 접근이 가능하도록 하는 키워드이다. static으로 생성된 정적 필드는 클래스의 인스턴스가 모두 공유하지만 해당 메소드는 클래스의 인스턴스와는 아무런 연관이 없다.
class Person {
  name: string;
  age: number;
  iq: number;
  gender: string;
  talkCnt: number;
  constructor(
    name = "sunghwan", age = 28, iq = 120, gender = "man", talkCnt = 0
  ) {
    this.name = name;
    this.age = age;
    this.iq = iq;
    this.gender = gender;
    this.talkCnt = talkCnt;
  }

  static talk(a: Person, b: Person): void {
    console.log(`${b.name}가 ${a.name}에게 대화를 요청했다.`);
    a.talkCnt++;
    b.talkCnt++;
    return;
  }
}

const defaultPerson = new Person();
console.log("말하기 전 : ", defaultPerson);
const artificialPerson = new Person("또 다른 나", 20, 200, "man");
Person.talk(defaultPerson, artificialPerson); // 클래스를 통해 메소드 호출
console.log("말하기 후 : ", defaultPerson);

static 키워드를 통해 메소드를 정의해주면 해당 메소드는 Person.talk를 통해 호출할 수 있다.
(클래스의 인스턴스로 접근을 하려고하면 에러를 내뱉는다.)

 

  • private : 클래스 자체적으로 접근이 가능하도록 하는 키워드이다. 해당 키워드로 선언된 변수나 메소드는 외부에서 사용할 수 없을 뿐만 아니라, 오직 해당 클래스에서만 쓰이고 하위 클래스에게 상속을 해줄 수 없다.
class Person {
  name: string;
  age: number;
  iq: number;
  gender: string;
  talkCnt: number;
  constructor(
    name = "sunghwan", age = 28, iq = 120, gender = "man", talkCnt = 0
  ) {
    this.name = name;
    this.age = age;
    this.iq = iq;
    this.gender = gender;
    this.talkCnt = talkCnt;
  }

// private키워드로 인한 정보 은닉(오로지 Person에서만 접근 가능함)
  private talk(a: Person): void {
    console.log(`${this.name}가 ${a.name}에게 대화를 요청했다.`);
    a.talkCnt++;
    this.talkCnt++;
    return;
  }

  addTalkCnt(a: Person) {
    this.talk(a);
  }
}

const defaultPerson = new Person();
console.log("말하기 전 : ", defaultPerson);
const artificialPerson = new Person("또 다른 나", 20, 200, "man");
defaultPerson.addTalkCnt(artificialPerson); // 해당 클래스의 인스턴스는 talk 메소드에 직접적으로 접근이 불가능하다.
console.log("말하기 후 : ", defaultPerson);

위 코드의 결과값은 static 키워드를 사용했을 때와 동일하다.

 

  • 그렇다면 언제 static이 쓰이고 언제 private이 쓰이는 걸까??
  1. static을 사용하는 경우
    • 공유 데이터 및 동작 관리: 클래스의 인스턴스와 관련이 없는 데이터를 관리하거나, 인스턴스와 무관한 동작을 수행할 때 사용.
    • 전역적인 동작 정의: 클래스 내부에서 전역적으로 동작해야 하는 메서드를 정의할 때 사용.
class Counter {
    static count = 0;
  
    constructor() {
      // 인스턴스 생성될 때마다 count 증가
      Counter.count++;
    }
  
    static getCount() {
      // 클래스 메서드에서 count 값 반환
      return Counter.count;
    }
  }
  
  // 인스턴스 생성
  const counter1 = new Counter();
  const counter2 = new Counter();
  const counter3 = new Counter();
  
  // count 값 출력
  console.log(Counter.getCount()); // 출력: 3

 

 

2. private을 사용하는 경우

  • 캡슐화 및 정보 은닉: 클래스의 내부 구현 세부사항을 숨기고, 외부에서의 접근을 제한하여 안전성을 유지할 때 사용됩니다.
  • 내부 상태 보호: 외부에서 클래스의 내부 상태를 변경하거나 접근하는 것을 방지하기 위해 사용됩니다.
class test {
  private add(a: number, b: number) {
    return a + b;
  }

  private multipleFive(a: number) {
    return a * 5;
  }

  private dividedByTwo(a: number) {
    return a / 2;
  }

  secretCalculate(a: number, b: number) {
    const resultAdd = this.add(a, b);
    const resultMul = this.multipleFive(resultAdd);
    const res = this.dividedByTwo(resultMul);
    return res;
  }
}

const testObj = new test();
//secretCalculate 메소드의 procedure를 숨기고 결과값만을 출력한다.
console.log(testObj.secretCalculate(5, 10));
console.log(testObj.add(5,10));//add 메소드는 test클래스에서만 쓰이는 메소드이므로 해당 클래스의 인스턴스는 접근할 수 없기에 에러를 내뱉는다

 

 

Conclusion

정리하자면, privatestatic모두 클래스 내부에서만 사용이 가능하다.

그러나 private은 클래스 내에서만 접근할 수 있는 데이터를 보호하기 위해 사용되고 이를 클래스 외부에서 읽거나 조작할 수는 없다. static은 클래스의 모든 인스턴스가 공유할 수 있는 정적인 데이터나 동작을 정의할 때 사용한다.

static으로 선언된 변수나 함수는 프로그램이 동작하는 시점에서부터 메모리의 데이터영역에 적재되어 프로그램의 실행이 끝날 때 까지 사라지지 않는다.

private, public으로 선언된 변수나 함수는 인스턴스들이 각자 다른 데이터를 다루기 때문에 객체가 생성되는 시점에서 메모리의 힙 영역에 적재되고 가비지 컬렉션에 의해 정리된다.

public : 어디에서나 접근가능한 붕어빵.(전시용 붕어빵)

static : 특정 붕어빵에 국한된 것이 아닌 모든 붕어빵에 적용되는 속성. (로고)

private : 붕어빵을 만드는 비밀 레시피

댓글