-
[패캠] 타입스크립트 문법 - 클래스와 접근 제어자 (14/20)Front-end 개발 2024. 2. 1. 16:27
💡 본 타입스크립트 문법 시리즈는,
패캠의 '프론트엔드 웹 개발의 모든 것 초격차 패키지 Online'에 있는 TS 강의 노트이다.현재 수강 중인 패스트캠퍼스(fastcampus, 이하 패캠) 프론트엔드 패키지 강의가 있다.
강사님은 김영웅(Heropy) 님이다.
이 글을 쓰면서 강사님의 블로그에 '한눈에 보는 타입스크립트' 자료가 있다는 것을 알게 됬다... (바보😅)
강의를 듣는데, 강의자료가 없어서 일일이 강사님이 말씀을 따라 적으면서 강의 교안(?), 강의 노트를 작성했다.
혹시나 나처럼 패캠에서 타입스립트(TypeScript)를 수강하는 사람들에게 도움이 되면 좋겠다. 🔥
14. 클래스와 접근 제어자
타입스크립트 문법에서는 this로 접근할 수 있는 클래스의 속성들은 constructor 함수가 만들어지기 전에 클래스의 바디 부분에서 타입이 지정되어 있어야 한다. 타입스크립트에서 클래스를 사용하게 되면, 속성 부분의 타입을 constructor 함수 위쪽에 있는 클래스의 바디 부분에 명시해야 함을 기억해두자. 초기값이 필요하다면 타입 선언의 뒤쪽에 할당 연산자를 통해서 값을 입력할 수도 있다.
class User_A { first: string = '' last: string = '' age: number = 0 constructor(first: string, last: string, age: number) { this.first = first this.last = last this.age = age } getAge() { return `${this.first} ${this.last} is ${this.age}` } }
this로 클래스의 속성들에 접근을 하기 위해서는 접근 제어자가 필요하다
접근 제어자 (Access Modifiers)의 종류
- public - 어디서나 자유롭게 접근 가능, 클래스 바디에서 생략 가능
- protected - 나와 파생된 후손 클래스 내에서 접근 가능
- private - 내 클래스에서만 접근 가능
접근 제어자: public
public 접근 제어자는 어디서나 자유롭게 접근 가능하며 클래스 바디에서 생략이 가능하다.
UserB 부분에서 코드는 똑같지만 새롭게 getAge라는 메서드를 정의하고 있는 것이기 때문에, 기존 UserA의 getAge 부분의 내용이 덮어 써진다고 보면 된다. 각각의 속성들은 public이라는 접근 제어자를 추가 했기 때문에 this 키워드로 접근해서 내용을 사용하는 것에 전혀 문제가 없다. UserC 부분에서도 getAge 메서드를 덮어 써서 함수를 사용한다. 그때 this 키워드를 통해서 first, last, age 각각의 속성에 UserB와 같이 접근이 가능하다.
class UserA { public first: string = '' public last: string = '' public age: number = 0 constructor(first: string, last: string, age: number) { this.first = first this.last = last this.age = age } getAge() { return `${this.first} ${this.last} is ${this.age}` } } class UserB extends UserA { getAge() { return `${this.first} ${this.last} is ${this.age}` } } class UserC extends UserB { getAge() { return `${this.first} ${this.last} is ${this.age}` } } const neo = new UserA('Neo', 'Anderson', 102) console.log(neo.first) console.log(neo.last) console.log(neo.age)
public 접근 제어자는 클래스 바디에서 생략이 가능하지만, 되도록 일부러 붙여서 명시적으로 작성하는 것이 좋다.
접근 제어자: protected
protected 접근 제어자는 해당 클래스와 파생된 후손 클래스 내에서 접근 가능하다.
UserA 클래스의 속성 last의 접근 제어자를 protected로 수정하면, last 속성은 보호된 속성이 되어 UserA 클래스 내부나 혹은 그 UserA에서 파생된 하위 클래스 내에서만 해당하는 내용을 접근해서 쓸 수 있다.
결국, protected는 해당 속성을 보호해서 자신을 포함한 클래스 안쪽에서 사용하는 것은 전혀 문제가 없는데, 클래스 바깥쪽에서 속성을 사용하는 것을 허용하지 않겠다라는 의미를 가진다.
접근 제어자: private
private접근 제어자는 나의 클래스에서만 해당하는 속성에 접근할 수 있다.
UserA 클래스의 age 속성을 private 접근 제어자로 수정하면, age 라는 속성은 내 클래스에서만 접근 가능하기 때문에 usreA라는 클래스 내부에서 this 키워드를 통해서 접근하는 것은 전혀 문제가 되지 않지만, UserA를 벗어난 하위 클래스에서는 역시 접근을 할 수 없다. 나아가서 클래스 밖(인스턴스)에서 해당하는 age 속성을 조회하는 것도 불가능하다. (Error 발생)
속성을 private 접근 제어자로 설정하면, 비공개 속성이기 때문에 UserA라는 클래스 안에서만 접근해서 쓸 수 있다.
접근 제어자 정리
public 이라는 접근 제어자의 경우, 어디에서나 자유롭게 접근 가능해서 JavaScript에서 만드는 클래스의 속성과 같은 개념이라고 볼 수 있다. 추가 사항은 클래스 바디 부분에서 pulic이라는 키워드는 생략할 수 있는데 명시적으로 붙여주면 조금 덜 헷갈릴 수 있기 때문에 생략하거나 생략하지 않는 방법 모두 다 좋은 방법일 수 있다. protected 라는 접근 제어자의 경우, 해당 속성이 있는 클래스와 그 클래스를 상속 받아 사용하는 후손 클래스에서는 속성에 접근할 수 있다. 앞서 말한 클래스가 아니고 바깥쪽, 즉 생성자 함수를 호출해서 나오는 인스턴스에서 사용하는 것은 가능하지 않다.
private 접근 제어자는 완전히 비공개로 속성을 관리하는 것이기 때문에 해당 속성이 있는 클래스에서만 내용을 접근할 수 있다. 그 클래스를 상속받는 후손 클래스라도 그 비공개 속성에는 접근할 수 없다.
메소드에 사용하는 접근 제어자
public, portected, private 접근 제어자는 속성에서만 사용하는 것이 아니고, 메소드(클래스의 함수 형태인 속성)에서도 사용할 수 있다.
class UserA { public first: string = '' protected last: string = '' private age: number = 0 constructor(first: string, last: string, age: number) { this.first = first this.last = last this.age = age } private getAge() { return `${this.first} ${this.last} is ${this.age}` } } class UserB extends UserA { getAge() { return `${this.first} ${this.last} is ${this.age}` } } class UserC extends UserB { getAge() { return `${this.first} ${this.last} is ${this.age}` } } const neo = new UserA('Neo', 'Anderson', 102) console.log(neo.first) console.log(neo.last) // Error: protected console.log(neo.age) // Error: private neo.getAge() // Error: private
중복된 코드 제거하기
UserA 클래스의 constructor 함수를 보면 반복해서 나오는 구조가 그다지 좋은 형태가 아니다.
이 부분의 처리는 클래스 바디 부분에 만들어져 있는 각각의 속성 타입을 제거하고, 대신에 constructor 함수의 매개변수 부분에서 접근 제어자를 추가해주는 것이다. 이렇게 하면 매개변수를 속성에다가 할당하지 않아도 하나의 매개변수이면서 this 키워드로 접근할 수 있는 속성도 된다. 주의할 점은 pulic 접근 제어자는 클래스 바디에서 사용할 때만 생략이 가능하고, 매개변수 부분에서 사용할 때는 생략할 수 없다.
class UserA { constructor( public first: string = '', public last: string = '', public age: number = 0 ) { // ... } private getAge() { return `${this.first} ${this.last} is ${this.age}` } } class UserB extends UserA { getAge() { return `${this.first} ${this.last} is ${this.age}` } } class UserC extends UserB { getAge() { return `${this.first} ${this.last} is ${this.age}` } } const neo = new UserA('Neo', 'Anderson', 102) console.log(neo.first) console.log(neo.last) console.log(neo.age) neo.getAge() // Error, private
위와 같이 코드를 수정함으로써 매개변수를 각각의 속성에 다시 할당하는 코드는 필요하지 않다. 만약 각각의 속성에서 기본 값이 필요하다면, 단순히 할당 연산자로 기본 값을 추가해주면 된다. 수정된 코드는 기존에 초기화 코드를 만든 개념과 같다. 기존 코드를 훨씬 더 축약해서 작성해볼 수 있다. 그러면 constructor 함수 내부에 별다른 내용을 작성할 필요가 없어진다. 다시 한번 말하지만, 매개변수에서 접근 제어자를 사용할 때 pulic은 생략할 수 없다는 점을 꼭 기억하자.
Reference
김영웅 강사님 블로그 中 TS 파트
https://heropy.blog/2020/01/27/typescript/
김영웅 강사님 유튜브 채널
https://www.youtube.com/channel/UCcjhMpoaNvyy0StN9KgtF6w
'Front-end 개발' 카테고리의 다른 글
[패캠] 타입스크립트 문법 - 제네릭 클래스 (generic) (16/20) (0) 2024.02.01 [패캠] 패스트캠퍼스 문법 - 제네릭 함수 (generic) (15/20) (0) 2024.02.01 [패캠] 타입스크립트 문법 - 함수 오버로딩 (Overloading) (13/20) (0) 2024.02.01 [패캠] 타입스크립트 문법 - 함수 명시적 this 타입 (12/20) (0) 2024.02.01 [패캠] 타입스크립트 문법 - 타입 별칭 (Alias) (11/20) (0) 2024.02.01