Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[박상범] 챕터 11: 네임스페이스 패턴 #95

Merged
merged 1 commit into from
Nov 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 218 additions & 0 deletions 챕터_11/상범.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# 11. 네임스페이스 패턴

- 자바스크립트의 네임스페이스
- 전역 네임스페이스 내에 존재하는 다른 객체나 변수와의 충돌을 방지함에 있어 유용함
- 프로그램의 기능들을 체계적으로 구성하여 코드의 재사용성과 관리의 편의성을 높여줌

## 네임스페이스 패턴

### 네임스페이스 패턴 종류
- 단일 전역 변수
- 접두사 네임스페이스
- 객체 리터럴 표기법
- 중첩 네임스페이스
- 즉시 실행 함수 표현식
- 네임스페이스 주입

## 단일 전역 변수 패턴

- 하나의 전역 변수를 주요 참조 객체로 사용하는 방식

```tsx
const myUniqueApplication = (() => {
function myMethod() {
// 코드
return;
}

return {
myMethod,
};
})();

myUniqueApplication.myMethod();
```

- 단일 전역 변수 패턴의 가장 큰 문제점은 다른 개발자가 같은 이름의 전역 변수를 이미 사용하고 있을 가능성이 있다는 것

## 접두사 네임스페이스 패턴

- 고유한 접두사를 선정한 다음에 모든 메서드, 변수, 객체를 이 접두사 뒤에 붙여서 정의
```tsx
const myApplication_propertyA = {};
const myApplication_propertyB = {};
function myApplication_myMethod() {
// ...
}
```
- 접두사 네임 스페이스 패턴은 전역에서 특정 변수와 이름이 겹칠 가능성을 효과적으로 줄이지만 스스로 고유한 이름을 가진 객체도 같은 효과를 낼 수 있음
- 가장 큰 문제점은 애플리케이션이 커짐에 따라 많은 전역 객체가 생성된다는 점

## 객체 리터럴 표기법 패턴

- 객체 리터럴 표기법은 일종의 객체로, 키와 값으로 이뤄진 집합을 가지며, 각각의 키와 값은 콜론으로 구분됨
- 또한 키 자체가 새로운 네임스페이스가 될 수 있음

```tsx
const myApplication = {
getInfo() {
// ...
},
models: {},
views: {
pages: {},
},
collections: {},
};
```

- 네임스페이스에 속성을 직접 추가하는 방법도 있음

```tsx
myApplication.foo = () => "bar';

myApplication.utils = {
tostring(){
//...
},
export(){
//...
},
};
```

- 객체 리터럴 표기법 패턴은 전역 네임스페이스를 오염시키지 않으면서도 코드와 매개변수를 논리적으로 구성하는 데 도움을 줌
- 특히 쉽게 읽을 수 있고, 깊은 중첩까지 지원하는 구조를 구현할 때 매우 유용
- 또한, 일반적인 전역 변수들과 달리 동일한 이름의 변수가 있는지 검사하도록 설계되는 경우가 많아 충돌 가능성을 크게 줄여줌
- 객체 리터럴의 장점은 키 - 값 구조라 쉽게 알아보기 가능, 덕분에 애플리케이션 내의 서로 다른 로직이나 기능을 쉽게 캡슐화하여 깔끔하게 분리하고, 코드 확장에 있어 든든한 기반을 제공

## 중첩 네임스페이스 패턴

- 객체 리터럴 패턴을 발전시킨 형태가 바로 중첩 네임스페이스 패턴
- 중첩 네임스페이스 패턴은 같은 이름의 네임스페이스가 존재한다고 하더라도, 하위에 중첩된 네임스페이스까지 정확하게 일치할 가능성은 낮기 때문에 다른 패턴에 비해 충돌 위험이 낮은 편

## 즉시 실행 함수 표현식 패턴

- 자바스크립트에서는 즉시 실행 함수로 정의된 내부의 변수와 함수 모두 외부에서 접근 할 수 없음. 따라서 함수를 호출하는 것만으로도 쉽게 코드의 은닉성을 구현할 수 있음
- 즉시 실행 함수는 애플리케이션의 로직을 캡슐화하여 전역 네임스페이스로부터 보호하는 데 널리 사용되는 방법

## 네임 스페이스 주입 패턴

- 네임 스페이스 주입 패턴은 즉시 실행 함수 패턴의 또 다른 변형
- 이 패턴에서는 함수 내에서 this를 네임스페이스의 프록시로 활용하여 특정 네임스페이스에 메서드와 속성을 주입
- 네임스페이스 주입 패턴의 장점은 여러 객체나 네임스페이스에 기능적인 동작을 쉽게 적용할 수 있다는 점. 또한 이후에 확장될 기본 메서드에 적용할 때 유용
- 네임 스페이스 주입 패턴의 단점은, 같은 목적을 달성하는 더 쉽고 효율적인 방법이 존재할 수도 있다는 것

## 고급 네임스페이스 패턴

### 중첩 네임스페이스 자동화 패턴

- 중첩 네임스페이스는 코드에 체계적이고 계층적인 구조를 만들어 줌

```tsx
// 최상위 네임스페이스에 객체 리터렬을 할당합니다
const myApp = {};

// 문자열 형식의 네임스페이스튤 파싱하고
// 자동으로 중첩 네임스페이스를 생성해주는 간편한 함수입니다.
function extend(ns, ns_string) {
const parts = ns_string.split(".");
let parent = ns;
let pl;

pl = parts.length;

for (let i = 6; i < pl; i++) {
// 프로퍼티가 존재하지 않을 경우에만 생성합니다.
if (typeof parent[parts[i]] === "undefined") {
parent[parts[i]] = {};
}

parent = parent[parts[i]];
}
return parent;
}
```

### 의존성 선언 패턴

- 객체에 대한 로컬 참조가 전체적인 조회 시간을 단축

> 이거 보니까 v8 엔진의 인라인 캐싱, 히든 클래스가 생각남 (그냥 생각난거임. 맥락이 비슷하진 않음)

```tsx
// 중첩된 네입스떼이스에 접근하는 일반적인 방법입니다.
myApp.utilities.math.fibonacci(25);
myApp.utilities.math.sin(56);
myApp.utilities.drawing.plot(98, 50, 60);

// 로컬 변수에 캐싱한 참조를 사용합니다.
const utils = myApp.utilities;

const maths = utils.math;
const drawing = utils.drawing;

// 이렇게 하면 네임스페이스에 더 쉽게 접근할 수 밌습니다.
maths.fibonacci(25);
maths.sin(56);
drawing.plot(98, 50, 60);

// 로컬 변수믈 사용하는 이 방식은 중첩 네입스페이스에
// 수백, 수천번 호풀이 발생하는 경우에만 성능이 향상됩니다.
```

- 로컬 변수를 사용하는 것이 전역 변수를 매번 사용하는 것보다 더 빠름
- 또한 후속 작업에서 중첩된 속성이나 하위 네임스페이스에 매번 접근하는 것보다 더 편리하고 성능이 뛰어남
- 특히 복잡한 애플리케이션에서는 가독성을 높일 수 있음

### 심층 객체 확장 패턴

- 객체 리터럴 표기법으로 선언된 네임스페이스는 다른 객체와 쉽게 확장될 수 있음
- 병합 이후에는 두 네임스페이스의 속성과 함수 모두를 동일한 네임스페이스에서 접근할 수 있음

```tsx
// 사용 예시
const myNamespace = myNamespace || {};

extendObjects(myNamespace, {
utils: {},
});

console.log("test 1", myNamespace);

extendObjects(myNamespace, {
hello: {
world: {
wave: {
test() {
//...
},
},
},
},
});

myNamespace.hello.test1 = "this is a test";
myNamespace.hello.world.test2 = "this is another test";
console.log("test 2", myNamespace);

myNamespace.library = {
foo() {},
};

extendObjects(myNamespace, {
library: {
bar() {
//...
},
},
});

console.log("test 3", myNamespace);

const shorterNamespaceAccess = myNamespace.hello.world;
shorterNamespaceAccess.test3 = "hello again";
console.log("test 4", myNamespace);
```

> 글쓴이는 가능하다면 중첩 네임스페이스 자동화 패턴을 구현해서 적용하겠다고 함
Loading