자바스크립트 클래스의 추가 기능

자바스크립트 클래스의 추가 기능

이 기사에서는 자바스크립트 클래스의 추가 기능에 대해 설명합니다.

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

위 코드에서 #namePerson 클래스 외부에서 직접 접근할 수 없는 프라이빗 속성입니다. getNamesetName 메서드를 통해서만 이름에 접근하거나 변경할 수 있습니다.

프라이빗 메서드 정의

프라이빗 속성과 마찬가지로 프라이빗 메서드도 #으로 시작하는 이름으로 정의됩니다. 프라이빗 메서드는 클래스 내부에서만 호출될 수 있습니다.

 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를 사용해 우리 유튜브 채널에서 함께 따라할 수 있습니다. 유튜브 채널도 확인해 주세요.

YouTube Video