자바스크립트 클래스의 추가 기능
이 기사에서는 자바스크립트 클래스의 추가 기능에 대해 설명합니다.
YouTube Video
자바스크립트 클래스의 추가 기능
자바스크립트의 프라이빗 속성
자바스크립트에서 프라이빗 속성은 객체 또는 클래스 내부에서만 접근할 수 있는 속성을 말합니다. 이것은 캡슐화를 제공함으로써 외부 코드로부터의 직접적인 수정이나 참조가 불가능하게 하여 더 안전하고 견고한 코드 설계를 가능하게 합니다.
2020년 ECMAScript 2020(ES11)에서 클래스 내에서 해시(#
)를 사용하여 프라이빗 필드를 정의하는 기능이 도입되었습니다. 이것은 밑줄로 시작하는 변수명과 같은 기존의 자바스크립트 프라이빗 관례를 대체하며 더 명확한 방법을 제공합니다.
프라이빗 속성의 장점
다음은 private 속성의 장점입니다.
- 캡슐화: 내부 상태를 외부로부터 숨기고 데이터 일관성을 유지합니다.
- 보안: 속성이 외부 코드에 의해 의도치 않게 수정되는 것을 방지.
- 유지보수성 향상: 객체나 클래스의 구현을 숨기고 외부에 노출된 인터페이스를 명확히 합니다.
프라이빗 속성 사용 방법
클래스 내에서 프라이빗 속성 정의
프라이빗 필드는 #
으로 시작하는 이름을 사용하여 정의됩니다. 이 필드는 클래스의 인스턴스나 하위 클래스에서 직접 접근할 수 없습니다.
1class Person {
2 // Define private property
3 #name;
4
5 constructor(name) {
6 this.#name = name;
7 }
8
9 // Method to access the private property
10 getName() {
11 return this.#name;
12 }
13
14 // Method to change the private property
15 setName(newName) {
16 this.#name = newName;
17 }
18}
19
20const john = new Person("John");
21console.log(john.getName()); // John
22
23// Cannot access private property directly
24console.log(john.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class
위 코드에서 #name
은 Person
클래스 외부에서 직접 접근할 수 없는 프라이빗 속성입니다. getName
및 setName
메서드를 통해서만 이름에 접근하거나 변경할 수 있습니다.
프라이빗 메서드 정의
프라이빗 속성과 마찬가지로 프라이빗 메서드도 #
으로 시작하는 이름으로 정의됩니다. 프라이빗 메서드는 클래스 내부에서만 호출될 수 있습니다.
1class Counter {
2 #count = 0;
3
4 increment() {
5 this.#count++;
6 this.#logCount(); // Calling private method
7 }
8
9 // Private method
10 #logCount() {
11 console.log(`Current count: ${this.#count}`);
12 }
13}
14
15const counter = new Counter();
16counter.increment(); // Current count: 1
17
18// Cannot access private method directly
19counter.#logCount(); // SyntaxError: Private field '#logCount' must be declared in an enclosing class
여기서 #logCount
는 프라이빗 메서드로 정의되며 클래스 외부에서 접근할 수 없습니다. 이 메서드는 클래스 내부에서만 사용됩니다.
프라이빗 속성의 장점과 고려사항
장점
- 클래스 외부에서 직접 접근할 수 없기 때문에 의도하지 않은 변경이나 작업이 방지됩니다.
- 외부에서 보이지 않는 부분을 잘 숨길 수 있기 때문에 API로 노출시킬 부분을 명확히 관리할 수 있습니다.
노트
- 프라이빗 필드는 클래스 외부에서 완전히 숨겨져 있기 때문에 테스트와 디버깅이 어려울 수 있습니다. 따라서 설계 단계에서 철저히 테스트 가능한 API를 제공하는 것이 중요합니다.
- 프라이빗 필드는 각 인스턴스마다 고유하기 때문에 프로토타입 기반 특징을 가진 JavaScript의 다른 부분과 다르게 동작합니다.
기존의 프라이빗 속성의 가명 구현
#
를 사용한 프라이빗 필드가 도입되기 전에는 JavaScript에 공식적인 프라이빗 속성 문법이 없었습니다. 따라서 과거에는 다음과 같은 방식으로 의사 프라이빗 속성이 구현되었습니다.
밑줄(_) 사용 관례
개발자들은 밑줄을 변수 이름 앞에 붙여 '프라이빗'임을 관례적으로 나타냈습니다.
1class Car {
2 constructor(brand) {
3 this._brand = brand; // Using an underscore to indicate private
4 }
5
6 getBrand() {
7 return this._brand;
8 }
9}
10
11const car = new Car("Toyota");
12console.log(car.getBrand()); // Toyota
13console.log(car._brand); // Toyota (Accessible from outside)
이 방법은 단지 '관례'일 뿐 실제로는 외부에서 여전히 속성에 접근할 수 있습니다.
클로저를 사용한 프라이빗 속성 구현
함수 스코프와 클로저를 사용하여 프라이빗 속성을 구현하는 것도 가능합니다.
1function createPerson(name) {
2 let _name = name; // Private variable within function scope
3
4 return {
5 getName: function() {
6 return _name;
7 },
8 setName: function(newName) {
9 _name = newName;
10 }
11 };
12}
13
14const person = createPerson("Alice");
15console.log(person.getName()); // Alice
16person.setName("Bob");
17console.log(person.getName()); // Bob
18
19// Cannot access directly from outside
20console.log(person._name); // undefined
이 방법을 사용하면 변수 _name
이 함수 스코프 내에 감싸져 있어 외부에서 직접 접근할 수 없습니다.
요약
JavaScript의 프라이빗 속성은 클래스와 객체 설계에서 캡슐화를 제공하는 데 매우 효과적이며 데이터를 안전하게 보호하는 데 도움을 줍니다. ES2020에서 도입된 프라이빗 필드의 #
표기법은 기존 관례나 클로저와 비교하여 더 명확하고 안전한 프라이버시 관리 방법을 제공합니다.
JavaScript의 옵셔널 체이닝
옵셔널 체이닝은 깊게 중첩된 객체의 속성에 접근할 때 매우 유용한 JavaScript 문법입니다. 개별 속성의 존재 여부를 일일이 확인하지 않고 안전하게 접근할 수 있어 코드의 가독성과 유지보수성이 향상됩니다.
옵셔널 체이닝의 기본 문법
속성 접근을 위한 점(.
)이나 대괄호 표기법 앞에 ?
를 사용하여 옵셔널 체이닝을 사용할 수 있습니다. 이 표기법은 탐색된 속성이 null
또는 undefined
일 경우 undefined
를 반환하여 오류를 발생시키지 않고 프로그램이 안전하게 처리를 계속할 수 있게 합니다.
예제:
1const user = {
2 name: 'John',
3 address: {
4 street: '123 Main St',
5 city: 'New York'
6 }
7};
8
9// Without using optional chaining
10const city = user && user.address && user.address.city;
11console.log(city); // New York
12
13// Using optional chaining
14const cityWithOptionalChaining = user?.address?.city;
15console.log(cityWithOptionalChaining); // New York
이 예제에서는 user
객체의 address
및 그 속성인 city
에 접근하고 있습니다. 옵셔널 체이닝(Optional Chaining)을 사용하지 않으면 여러 번의 존재 여부 확인이 필요하지만, 옵셔널 체이닝을 사용하면 단일 구문으로 안전하게 속성에 접근할 수 있습니다.
배열과 함수에서의 옵셔널 체이닝 사용하기
옵셔널 체이닝은 객체 속성뿐 아니라 배열 요소와 함수 호출에서도 사용할 수 있습니다.
배열 사용 예시:
1const users = [{ name: 'Alice' }, { name: 'Bob' }];
2
3// Accessing the non-existent third element
4const thirdUser = users[2]?.name;
5console.log(thirdUser); // undefined
함수 사용 예시:
1const user = {
2 greet: function() {
3 return 'Hello!';
4 }
5};
6
7// Call the function only if greet exists
8const greeting = user.greet?.();
9console.log(greeting); // Hello!
10
11// Return undefined if greet does not exist
12const nonExistentGreeting = user.nonExistentMethod?.();
13console.log(nonExistentGreeting); // undefined
옵셔널 체이닝과 기본값을 함께 사용하기
옵셔널 체이닝을 사용할 때, 속성이 존재하지 않는 경우 기본값을 지정하기 위해 논리적 OR (||
) 또는 null 병합 연산자 (??
)를 사용하는 것이 일반적입니다.
예제:
1const user = {
2 name: 'John',
3 address: {
4 city: 'New York'
5 }
6};
7
8// Set a default value for a non-existent property
9const state = user?.address?.state || 'Unknown';
10console.log(state); // Unknown
11
12// Example using the nullish coalescing operator
13const zipCode = user?.address?.zipCode ?? '00000';
14console.log(zipCode); // 00000
||
연산자는 false
, 0
, ''
등도 falsy로 처리하는 반면, ??
연산자는 피연산자가 null
또는 undefined
일 때만 기본값을 사용합니다.
옵셔널 체이닝의 이점
- 중첩된 객체에 안전하게 접근: 옵셔널 체이닝을 사용하면 명시적인 존재 여부 확인을 할 필요가 없어 코드를 더 간결하게 작성할 수 있습니다.
- 오류 방지: 속성이
null
이거나undefined
인 경우에도 런타임 오류를 방지할 수 있습니다. - 읽기 및 유지보수성 향상: 특히 다수의 중첩 객체를 다룰 때 코드 가독성이 크게 향상됩니다.
옵셔널 체이닝 사용 시 주의사항
- 옵셔널 체이닝을 자주 사용하는 것은 데이터 구조 설계가 지나치게 복잡하다는 신호일 수 있습니다. 단순한 데이터 모델을 지향해야 합니다.
- 일부 구형 브라우저와 JavaScript 엔진은 이를 지원하지 않으므로, 폴리필(polyfill)이나 트랜스파일러를 사용해야 할 수도 있습니다.
결론
옵셔널 체이닝은 JavaScript에서 중첩 객체의 속성과 함수에 안전하게 접근하는 과정을 단순화해주는 강력한 기능입니다. 깊이 중첩된 데이터 구조에 접근할 때 특히 효과적이며, 오류 방지와 코드 가독성 향상에 기여합니다.
위의 기사를 보면서 Visual Studio Code를 사용해 우리 유튜브 채널에서 함께 따라할 수 있습니다. 유튜브 채널도 확인해 주세요.