본문으로 건너뛰기

안동민 개발노트

본문 시작

클래스 기본 문법

클래스의 속성·생성자·메서드로 인스턴스를 만들고 접근 제어자 축약과 static 멤버의 소속 범위를 익힙니다.

자바스크립트는 본래 프로토타입 기반 객체 지향 언어입니다.

다만 ES2015(ES6)부터는 다른 객체 지향 언어와 비슷한 클래스(Class) 문법을 지원하기 시작했습니다.

클래스는 객체 지향의 핵심 개념인 추상화, 캡슐화, 상속, 다형성을 표현하기 위한 문법적 장치입니다.

타입스크립트는 여기에 강력한 타입 시스템을 결합해 클래스를 더 안전하고 견고하게 사용할 수 있게 해줍니다.

이번 절에서는 타입스크립트의 클래스 기본 문법과 핵심 요소들을 상세히 살펴보겠습니다.

클래스 기본 문법

TypeScript 클래스는 JavaScript의 class 문법 위에 필드 타입, 접근 제어자, 생성자 매개변수 속성 같은 타입 정보를 얹어 객체 초기화 규칙을 드러냅니다.

  1. 클래스 선언과 인스턴스 생성

    클래스를 선언하는 것은 class 키워드를 사용하며, 일반적으로 클래스 이름은 파스칼 케이스(PascalCase, 첫 글자 대문자)를 사용합니다. 클래스(Class)

  2. 접근 제어자

    타입스크립트의 클래스는 속성과 메서드의 접근 수준을 제어하는 세 가지 접근 제어자(Access Modifiers)로 외부 API와 내부 구현을 구분합니다. 추상화, 캡슐화, 상속, 다형성

  3. 생성자의 매개변수에 접근 제어자 사용하기

    타입스크립트에서는 생성자 매개변수에 접근 제어자를 붙여 속성 선언과 초기화를 한 번에 처리할 수 있습니다. parameter property

  4. 클래스 기본 문법 기준

    정확성 클래스 본문에는 인스턴스가 반드시 가져야 할 필드와 생성 시점에 채워야 할 값을 함께 드러냅니다. 비용 클래스는 객체 지향의 핵심 개념인 추상화, 캡슐화, 상속, 다형성을 표현하기 위한 문법적 장치입니다. 확장성 클래스 필드 타입, constructor parameter property, 접근 제어자를 함께 쓰면 인스턴스 shape과 초기화 규칙이 코드에 드러납니다. 예외 public, private, protected는 타입 검사 단계의 계약이므로 런타임 은닉 보장과 구분해 읽어야 합니다.

  5. 정확성 클래스 본문에

    인스턴스가 반드시 가져야 할 필드와 생성 시점에 채워야 할 값을 함께 드러냅니다.

  6. 비용 클래스

    객체 지향의 핵심 개념인 추상화, 캡슐화, 상속, 다형성을 표현하기 위한 문법적 장치입니다.

  7. 확장성 클래스 필드 타입, constructor

    parameter property, 접근 제어자를 함께 쓰면 인스턴스 shape과 초기화 규칙이 코드에 드러납니다.

  8. 예외 public, private, protected

    타입 검사 단계의 계약이므로 런타임 은닉 보장과 구분해 읽어야 합니다.


클래스 선언과 인스턴스 생성

클래스는 초기 상태와 허용 동작을 한 곳에 묶는다

constructor는 객체를 만들 때 불변 조건을 세우고, field와 method는 객체별 상태와 동작 API를 만든다.

  1. Constructor
    Constructor new 시점에 필요한 초기값

    검증 수행

  2. Fields
    Fields 객체

    유지해야 하는 상태를 타입과 함께 선언

  3. Methods
    Methods 상태

    읽거나 바꾸는 허용 동작

  4. Instance
    Instance 같

    설계도에서 만들어져도 상태는 객체별로 독립

구분역할
읽는 기준어떤 상태를 보호하는가
사용 기준외부에 어떤 동작만 허용하는가
판단문법보다 상태와 API 경계가 핵심

클래스를 선언하는 것은 class 키워드를 사용하며, 일반적으로 클래스 이름은 파스칼 케이스(PascalCase, 첫 글자 대문자)를 사용합니다.

// 'Person'이라는 이름의 클래스를 선언합니다.
class Person {
  // 1. 속성 (Property): 클래스의 데이터를 나타냅니다.
  // 각 속성에도 타입을 명시합니다.
  name: string;
  age: number;
  private _job: string; // private 접근 제어자를 가진 속성

  // 2. 생성자 (Constructor): 클래스의 인스턴스가 생성될 때 호출됩니다.
  // 인스턴스의 속성들을 초기화하는 역할을 합니다.
  constructor(name: string, age: number, job: string) {
    this.name = name; // this는 현재 생성되는 인스턴스를 가리킵니다.
    this.age = age;
    this._job = job;
  }

  // 3. 메서드 (Method): 클래스의 동작(함수)을 나타냅니다.
  // 매개변수와 반환 값에 타입을 명시합니다.
  greet(): string {
    return `안녕하세요, ${this.name}입니다. 저는 ${this.age}살이고 ${this._job}입니다.`;
  }

  // Getter (속성 값을 읽을 때 사용)
  get job(): string {
    return this._job;
  }

  // Setter (속성 값을 설정할 때 사용)
  set job(newJob: string) {
    if (newJob.length < 2) {
      console.log("직업명은 2글자 이상이어야 합니다.");
      return;
    }
    this._job = newJob;
  }
}

// 클래스의 인스턴스 (객체) 생성
// new 키워드와 함께 생성자를 호출합니다.
const person1 = new Person("김철수", 30, "개발자");
const person2 = new Person("이영희", 25, "디자이너");

console.log(person1.name); // 김철수
console.log(person1.age);  // 30
console.log(person1.greet()); // 안녕하세요, 김철수입니다. 저는 30살이고 개발자입니다.

// Getter 사용
console.log(person2.job); // 디자이너

// Setter 사용
person2.job = "마케터";
console.log(person2.greet()); // 안녕하세요, 이영희입니다. 저는 25살이고 마케터입니다.

person2.job = "SE"; // setter에 정의된 조건에 의해 변경되지 않음
console.log(person2.job); // 마케터 (변경되지 않음)

클래스의 기본적인 구성 요소는 다음과 같습니다.

  • 속성 (Properties): 클래스의 상태를 나타내는 변수입니다. 각 속성에도 타입을 명시합니다. (예: name: string;)
  • 생성자 (Constructor): new 키워드를 통해 클래스의 인스턴스를 생성할 때 호출되는 특별한 메서드입니다. 인스턴스의 초기 상태를 설정하는 역할을 합니다.
  • 메서드 (Methods): 클래스가 수행할 수 있는 동작을 나타내는 함수입니다. 일반 함수와 마찬가지로 매개변수와 반환 값에 타입을 명시할 수 있습니다.
  • this 키워드: 클래스 내부에서 this는 현재 클래스의 인스턴스를 가리킵니다. 이를 통해 인스턴스의 속성과 메서드에 접근할 수 있습니다.
  • Getter/Setter: 특정 속성에 대한 읽기/쓰기 접근을 제어하는 메서드입니다. 속성처럼 접근하지만 내부적으로는 함수가 실행됩니다.

접근 제어자

타입스크립트의 클래스는 속성과 메서드의 접근 수준을 제어하는 세 가지 접근 제어자(Access Modifiers)를 제공합니다.

이는 객체 지향의 캡슐화(Encapsulation)를 구현하는 데 중요한 역할을 합니다.

public (공개): 가장 기본적인 접근 제어자입니다.

선언된 속성이나 메서드가 클래스 외부에서 자유롭게 접근 가능함을 의미합니다.

아무런 접근 제어자를 명시하지 않으면 기본적으로 public으로 간주됩니다.

class PublicExample {
  public value: number; // public 명시
  message: string;      // 기본값 public

  constructor(val: number, msg: string) {
    this.value = val;
    this.message = msg;
  }

  public display(): void {
    console.log(`Value: ${this.value}, Message: ${this.message}`);
  }
}

const pe = new PublicExample(10, "Hello");
console.log(pe.value);   // 10 (접근 가능)
pe.display();            // Display: Value: 10, Message: Hello (접근 가능)

private (비공개): 선언된 속성이나 메서드가 해당 클래스 내부에서만 접근 가능함을 의미합니다.

클래스 외부나 상속받은 자식 클래스에서도 접근할 수 없습니다.

이는 특정 데이터를 외부에서 직접 변경하지 못하도록 보호할 때 유용합니다.

class PrivateExample {
  private secretCode: string; // private 속성

  constructor(code: string) {
    this.secretCode = code;
  }

  public revealCode(): string {
    return `비밀 코드: ${this.secretCode}`; // 클래스 내부에서 접근 가능
  }
}

const pve = new PrivateExample("MY_PRIVATE_KEY");
// console.log(pve.secretCode); // Error: Property 'secretCode' is private and only accessible within class 'PrivateExample'.
console.log(pve.revealCode()); // 비밀 코드: MY_PRIVATE_KEY (public 메서드를 통해 간접 접근)

자바스크립트의 # 프라이빗 필드 문법과 유사하나, 타입스크립트의 private는 컴파일 시점에 검사되는 타입 시스템 레벨의 제약입니다.

protected (보호된): 선언된 속성이나 메서드가 해당 클래스 내부와 이 클래스를 상속받은 자식 클래스 내부에서만 접근 가능함을 의미합니다.

클래스 외부에서는 접근할 수 없습니다.

이는 부모 클래스의 특정 속성이나 메서드를 자식 클래스에서 활용해야 하지만, 외부 노출은 막고 싶을 때 사용됩니다.

class ProtectedExample {
  protected protectedValue: string; // protected 속성

  constructor(value: string) {
    this.protectedValue = value;
  }

  protected getProtectedValue(): string {
    return this.protectedValue;
  }
}

class ChildExample extends ProtectedExample {
  constructor(value: string) {
    super(value); // 부모 클래스의 생성자 호출
  }

  public printProtected(): void {
    console.log(`자식에서 접근: ${this.protectedValue}`);     // 자식 클래스에서 접근 가능
    console.log(`자식에서 메서드 접근: ${this.getProtectedValue()}`); // 자식 클래스에서 메서드 접근 가능
  }
}

const child = new ChildExample("보호된 값");
child.printProtected(); // 자식에서 접근: 보호된 값, 자식에서 메서드 접근: 보호된 값
// console.log(child.protectedValue); // Error: Property 'protectedValue' is protected and only accessible within class 'ProtectedExample' and its subclasses.

생성자의 매개변수에 접근 제어자 사용하기

타입스크립트에서는 생성자의 매개변수에 직접 접근 제어자(public, private, protected, readonly)를 붙여서, 해당 매개변수를 클래스의 속성으로 동시에 선언하고 초기화할 수 있는 편리한 문법을 제공합니다.

class CompactPerson {
  // 매개변수에 public을 붙여 자동으로 속성으로 선언하고 초기화
  constructor(public name: string, public age: number, private _secretInfo: string) {
    // this.name = name; 이런 식으로 속성 할당 코드를 생략할 수 있습니다.
  }

  get secretInfo(): string {
    return this._secretInfo;
  }
}

const compactP = new CompactPerson("김효진", 28, "비밀 일기");
console.log(compactP.name);       // 김효진
console.log(compactP.age);        // 28
// console.log(compactP._secretInfo); // Error: private 속성이므로 접근 불가
console.log(compactP.secretInfo); // 비밀 일기 (getter를 통해 접근)

이 방식은 코드를 훨씬 간결하게 만들어주며, 특히 클래스 속성 정의와 생성자 초기화 코드를 줄이는 데 효과적입니다.

다음 다이어그램은 생성자 매개변수 속성을 일반 필드 선언, 접근 제어자, 초기화 코드와 어떻게 대응해 읽으면 좋은지 정리한 것입니다.

생성자 매개변수는 필드 선언과 초기화를 함께 줄인다

접근 제어자가 붙은 매개변수는 클래스 멤버가 되므로, 생성자 본문은 검증과 파생값 계산에 집중할 수 있습니다.

  1. 속성 선언

    field name 과 id 가 인스턴스 필드로 만들어집니다.

  2. 공개 범위 결정

    access public , private , readonly 가 멤버 규칙이 됩니다.

  3. 초기화 생략

    assign this.name = name 같은 단순 대입을 반복하지 않습니다.

  4. 본문의 역할

    body 나이 검증, 직업명 정규화처럼 규칙이 있는 로직만 남깁니다.


static 속성과 메서드

클래스의 static (정적) 멤버는 클래스의 인스턴스가 아닌, 클래스 자체에 속하는 속성이나 메서드입니다.

즉, new 키워드로 인스턴스를 생성하지 않고도 클래스 이름으로 직접 접근할 수 있습니다.

유틸리티 함수나 모든 인스턴스가 공유해야 하는 상수 값 등을 정의할 때 유용합니다.

class MathUtil {
  static PI: number = 3.14159; // 정적 속성

  static calculateCircleArea(radius: number): number { // 정적 메서드
    return this.PI * radius * radius; // 정적 메서드 내에서 정적 속성 접근 시 this.PI
  }

  // 인스턴스 메서드에서는 정적 멤버에 직접 접근하지 않는 것이 일반적입니다.
  // 다만 클래스 이름으로 접근은 가능합니다.
  public getInstancePi(): number {
    return MathUtil.PI; // 클래스 이름으로 접근
  }
}

// 인스턴스 생성 없이 직접 클래스 이름으로 접근
console.log(MathUtil.PI); // 3.14159
console.log(MathUtil.calculateCircleArea(5)); // 78.53975

const util = new MathUtil();
console.log(util.getInstancePi()); // 3.14159 (인스턴스를 통해 정적 속성 접근)

// 오류: 인스턴스를 통해 정적 메서드에 접근할 수 없습니다.
// util.calculateCircleArea(10); // Error: Property 'calculateCircleArea' does not exist on type 'MathUtil'. Did you mean 'static calculateCircleArea'?

static 멤버는 클래스명 뒤에 점(.)을 찍어 접근합니다.

this를 사용하면 같은 클래스 내의 다른 static 멤버에 접근할 수 있습니다.


클래스는 복잡한 애플리케이션의 구조를 체계적으로 설계하고 관리하는 데 필수적인 요소입니다.

타입스크립트는 자바스크립트의 클래스 문법에 타입 안전성과 접근 제어자 같은 객체 지향적 기능을 추가하여, 더욱 견고하고 유지보수하기 쉬운 코드를 작성할 수 있도록 돕습니다.

아래 다이어그램은 클래스가 필드, 생성자, 메서드, 접근 제어자를 하나의 설계도로 묶고, new 호출을 통해 인스턴스 상태와 동작으로 이어지는 흐름을 정리한 것입니다.

클래스 설계도는 new를 통해 독립 인스턴스로 바뀐다

class 선언은 상태와 동작의 규칙이고, new 호출이 그 규칙을 가진 실제 객체를 만든다.

  1. class Person 필드, 생성자, 메서드

    접근 제어자를 선언

  2. constructor 초기값 검증

    필드 채우기

  3. new Person() 독립적인 인스턴스 상태

    생성

  4. method/getter 정해진 API로만 상태

    읽고 변경

점검기준
this현재 인스턴스의 필드와 메서드에 접근
getter/setter속성처럼 쓰되 검증 로직을 둘 수 있음
private외부 직접 수정을 막아 내부 상태 보호

클래스 멤버를 설계할 때는 인스턴스 상태인지, 외부 API인지, 클래스 공통 유틸리티인지 먼저 나누면 접근 제어자와 static 여부를 더 안정적으로 결정할 수 있습니다.

클래스 멤버 결정표

필드, 메서드, 생성자, 정적 멤버를 역할별로 분리하면 클래스가 외부 API와 내부 상태를 더 명확하게 드러냅니다.

  1. state
    인스턴스 상태

    state 객체마다 달라지는 값은 필드로 두고 생성자에서 초기화합니다.

  2. behavior
    인스턴스 동작

    behavior 상태를 읽거나 바꾸는 로직은 인스턴스 메서드에 둡니다.

  3. static
    클래스 공통

    static 객체 상태와 무관한 상수·유틸리티는 클래스 이름으로 접근합니다.

  4. public
    외부 API

    public 호출자가 의존해도 되는 멤버만 공개하고, 나머지는 내부 구현으로 숨깁니다.

  5. private
    내부 불변식

    private 잘못 바뀌면 객체가 깨지는 값은 메서드를 통해서만 갱신하게 만듭니다.


다음 다이어그램은 클래스 기본 문법을 인스턴스 생성과 멤버 공개 범위 기준으로 정리한 표입니다.

클래스 공개 범위 설계

생성자, 인스턴스 속성, 접근 제어자, static 멤버를 한 번에 보면 클래스가 어떤 책임을 외부에 공개하는지 보입니다.

  1. 초기 상태

    생성자 constructor는 인스턴스가 유효하게 시작하기 위한 필수 값을 받습니다. constructor()

  2. 객체별 값

    인스턴스 멤버 각 객체가 따로 가지는 속성과 메서드는 인스턴스 멤버로 둡니다. user.name

  3. 사용 경계

    접근 제어 public, private, protected로 외부에서 만질 수 있는 범위를 제한합니다. private id

  4. 클래스 규칙

    static 멤버 인스턴스 없이 공유되는 상수나 팩토리 메서드는 static으로 분리합니다. User.create

클래스 기본 문법은 상태와 동작을 하나의 타입으로 묶습니다

생성자, 속성, 메서드, 접근 제어자, static 멤버를 통해 인스턴스가 가져야 할 데이터와 행동을 명확히 정의합니다.

  1. 초기 상태 설정

    생성자 constructor에서 인스턴스가 필요한 값을 받아 속성에 안전하게 저장합니다. constructor

  2. 객체별 데이터

    인스턴스 new로 만든 객체마다 다른 상태를 가지며 메서드는 그 상태를 사용합니다. new User()

  3. 사용 범위 제한

    접근 제어 public, private, protected로 속성과 메서드를 어디서 사용할 수 있는지 표시합니다. private

  4. 클래스 소속 멤버

    static 개별 인스턴스가 아니라 클래스 자체에 속한 값과 기능을 표현합니다. Class.method

아래 다이어그램은 TypeScript 클래스의 속성, 생성자, 메서드, static 멤버를 한 화면에서 연결합니다.

클래스 기본 구성표

클래스는 상태와 동작을 하나의 타입으로 묶고, 생성자를 통해 인스턴스가 시작할 때 필요한 값을 채웁니다.

  1. 속성
    상태에 타입 부여

    속성 클래스가 보관할 값의 이름과 타입을 선언해 인스턴스 모양을 정합니다. name: string

  2. 생성자
    초기 상태 설정

    생성자 new 호출 시 전달받은 값으로 속성을 채우고 객체를 사용 가능한 상태로 만듭니다. constructor(name: string)

  3. 메서드
    동작의 타입 계약

    메서드 인스턴스가 수행할 함수를 선언하고 인자와 반환 타입을 명시합니다. move(distance: number)

  4. static
    클래스 자체의 멤버

    static 인스턴스가 아니라 클래스 이름으로 접근할 공통 값과 함수를 표현합니다. User.create()