|
| 1 | +# 11. 네임스페이스 패턴 |
| 2 | + |
| 3 | +- 자바스크립트의 네임스페이스 |
| 4 | + - 전역 네임스페이스 내에 존재하는 다른 객체나 변수와의 충돌을 방지함에 있어 유용함 |
| 5 | + - 프로그램의 기능들을 체계적으로 구성하여 코드의 재사용성과 관리의 편의성을 높여줌 |
| 6 | + |
| 7 | +## 네임스페이스 패턴 |
| 8 | + |
| 9 | +### 네임스페이스 패턴 종류 |
| 10 | + - 단일 전역 변수 |
| 11 | + - 접두사 네임스페이스 |
| 12 | + - 객체 리터럴 표기법 |
| 13 | + - 중첩 네임스페이스 |
| 14 | + - 즉시 실행 함수 표현식 |
| 15 | + - 네임스페이스 주입 |
| 16 | + |
| 17 | +## 단일 전역 변수 패턴 |
| 18 | + |
| 19 | +- 하나의 전역 변수를 주요 참조 객체로 사용하는 방식 |
| 20 | + |
| 21 | + ```tsx |
| 22 | + const myUniqueApplication = (() => { |
| 23 | + function myMethod() { |
| 24 | + // 코드 |
| 25 | + return; |
| 26 | + } |
| 27 | + |
| 28 | + return { |
| 29 | + myMethod, |
| 30 | + }; |
| 31 | + })(); |
| 32 | + |
| 33 | + myUniqueApplication.myMethod(); |
| 34 | + ``` |
| 35 | + |
| 36 | +- 단일 전역 변수 패턴의 가장 큰 문제점은 다른 개발자가 같은 이름의 전역 변수를 이미 사용하고 있을 가능성이 있다는 것 |
| 37 | + |
| 38 | +## 접두사 네임스페이스 패턴 |
| 39 | + |
| 40 | +- 고유한 접두사를 선정한 다음에 모든 메서드, 변수, 객체를 이 접두사 뒤에 붙여서 정의 |
| 41 | + ```tsx |
| 42 | + const myApplication_propertyA = {}; |
| 43 | + const myApplication_propertyB = {}; |
| 44 | + function myApplication_myMethod() { |
| 45 | + // ... |
| 46 | + } |
| 47 | + ``` |
| 48 | +- 접두사 네임 스페이스 패턴은 전역에서 특정 변수와 이름이 겹칠 가능성을 효과적으로 줄이지만 스스로 고유한 이름을 가진 객체도 같은 효과를 낼 수 있음 |
| 49 | +- 가장 큰 문제점은 애플리케이션이 커짐에 따라 많은 전역 객체가 생성된다는 점 |
| 50 | + |
| 51 | +## 객체 리터럴 표기법 패턴 |
| 52 | + |
| 53 | +- 객체 리터럴 표기법은 일종의 객체로, 키와 값으로 이뤄진 집합을 가지며, 각각의 키와 값은 콜론으로 구분됨 |
| 54 | +- 또한 키 자체가 새로운 네임스페이스가 될 수 있음 |
| 55 | + |
| 56 | + ```tsx |
| 57 | + const myApplication = { |
| 58 | + getInfo() { |
| 59 | + // ... |
| 60 | + }, |
| 61 | + models: {}, |
| 62 | + views: { |
| 63 | + pages: {}, |
| 64 | + }, |
| 65 | + collections: {}, |
| 66 | + }; |
| 67 | + ``` |
| 68 | + |
| 69 | +- 네임스페이스에 속성을 직접 추가하는 방법도 있음 |
| 70 | + |
| 71 | + ```tsx |
| 72 | + myApplication.foo = () => "bar'; |
| 73 | + |
| 74 | + myApplication.utils = { |
| 75 | + tostring(){ |
| 76 | + //... |
| 77 | + }, |
| 78 | + export(){ |
| 79 | + //... |
| 80 | + }, |
| 81 | + }; |
| 82 | + ``` |
| 83 | + |
| 84 | +- 객체 리터럴 표기법 패턴은 전역 네임스페이스를 오염시키지 않으면서도 코드와 매개변수를 논리적으로 구성하는 데 도움을 줌 |
| 85 | +- 특히 쉽게 읽을 수 있고, 깊은 중첩까지 지원하는 구조를 구현할 때 매우 유용 |
| 86 | +- 또한, 일반적인 전역 변수들과 달리 동일한 이름의 변수가 있는지 검사하도록 설계되는 경우가 많아 충돌 가능성을 크게 줄여줌 |
| 87 | +- 객체 리터럴의 장점은 키 - 값 구조라 쉽게 알아보기 가능, 덕분에 애플리케이션 내의 서로 다른 로직이나 기능을 쉽게 캡슐화하여 깔끔하게 분리하고, 코드 확장에 있어 든든한 기반을 제공 |
| 88 | + |
| 89 | +## 중첩 네임스페이스 패턴 |
| 90 | + |
| 91 | +- 객체 리터럴 패턴을 발전시킨 형태가 바로 중첩 네임스페이스 패턴 |
| 92 | +- 중첩 네임스페이스 패턴은 같은 이름의 네임스페이스가 존재한다고 하더라도, 하위에 중첩된 네임스페이스까지 정확하게 일치할 가능성은 낮기 때문에 다른 패턴에 비해 충돌 위험이 낮은 편 |
| 93 | + |
| 94 | +## 즉시 실행 함수 표현식 패턴 |
| 95 | + |
| 96 | +- 자바스크립트에서는 즉시 실행 함수로 정의된 내부의 변수와 함수 모두 외부에서 접근 할 수 없음. 따라서 함수를 호출하는 것만으로도 쉽게 코드의 은닉성을 구현할 수 있음 |
| 97 | +- 즉시 실행 함수는 애플리케이션의 로직을 캡슐화하여 전역 네임스페이스로부터 보호하는 데 널리 사용되는 방법 |
| 98 | + |
| 99 | +## 네임 스페이스 주입 패턴 |
| 100 | + |
| 101 | +- 네임 스페이스 주입 패턴은 즉시 실행 함수 패턴의 또 다른 변형 |
| 102 | +- 이 패턴에서는 함수 내에서 this를 네임스페이스의 프록시로 활용하여 특정 네임스페이스에 메서드와 속성을 주입 |
| 103 | +- 네임스페이스 주입 패턴의 장점은 여러 객체나 네임스페이스에 기능적인 동작을 쉽게 적용할 수 있다는 점. 또한 이후에 확장될 기본 메서드에 적용할 때 유용 |
| 104 | +- 네임 스페이스 주입 패턴의 단점은, 같은 목적을 달성하는 더 쉽고 효율적인 방법이 존재할 수도 있다는 것 |
| 105 | + |
| 106 | +## 고급 네임스페이스 패턴 |
| 107 | + |
| 108 | +### 중첩 네임스페이스 자동화 패턴 |
| 109 | + |
| 110 | +- 중첩 네임스페이스는 코드에 체계적이고 계층적인 구조를 만들어 줌 |
| 111 | + |
| 112 | + ```tsx |
| 113 | + // 최상위 네임스페이스에 객체 리터렬을 할당합니다 |
| 114 | + const myApp = {}; |
| 115 | + |
| 116 | + // 문자열 형식의 네임스페이스튤 파싱하고 |
| 117 | + // 자동으로 중첩 네임스페이스를 생성해주는 간편한 함수입니다. |
| 118 | + function extend(ns, ns_string) { |
| 119 | + const parts = ns_string.split("."); |
| 120 | + let parent = ns; |
| 121 | + let pl; |
| 122 | + |
| 123 | + pl = parts.length; |
| 124 | + |
| 125 | + for (let i = 6; i < pl; i++) { |
| 126 | + // 프로퍼티가 존재하지 않을 경우에만 생성합니다. |
| 127 | + if (typeof parent[parts[i]] === "undefined") { |
| 128 | + parent[parts[i]] = {}; |
| 129 | + } |
| 130 | + |
| 131 | + parent = parent[parts[i]]; |
| 132 | + } |
| 133 | + return parent; |
| 134 | + } |
| 135 | + ``` |
| 136 | + |
| 137 | +### 의존성 선언 패턴 |
| 138 | + |
| 139 | +- 객체에 대한 로컬 참조가 전체적인 조회 시간을 단축 |
| 140 | + |
| 141 | +> 이거 보니까 v8 엔진의 인라인 캐싱, 히든 클래스가 생각남 (그냥 생각난거임. 맥락이 비슷하진 않음) |
| 142 | +
|
| 143 | + ```tsx |
| 144 | + // 중첩된 네입스떼이스에 접근하는 일반적인 방법입니다. |
| 145 | + myApp.utilities.math.fibonacci(25); |
| 146 | + myApp.utilities.math.sin(56); |
| 147 | + myApp.utilities.drawing.plot(98, 50, 60); |
| 148 | + |
| 149 | + // 로컬 변수에 캐싱한 참조를 사용합니다. |
| 150 | + const utils = myApp.utilities; |
| 151 | + |
| 152 | + const maths = utils.math; |
| 153 | + const drawing = utils.drawing; |
| 154 | + |
| 155 | + // 이렇게 하면 네임스페이스에 더 쉽게 접근할 수 밌습니다. |
| 156 | + maths.fibonacci(25); |
| 157 | + maths.sin(56); |
| 158 | + drawing.plot(98, 50, 60); |
| 159 | + |
| 160 | + // 로컬 변수믈 사용하는 이 방식은 중첩 네입스페이스에 |
| 161 | + // 수백, 수천번 호풀이 발생하는 경우에만 성능이 향상됩니다. |
| 162 | + ``` |
| 163 | + |
| 164 | +- 로컬 변수를 사용하는 것이 전역 변수를 매번 사용하는 것보다 더 빠름 |
| 165 | +- 또한 후속 작업에서 중첩된 속성이나 하위 네임스페이스에 매번 접근하는 것보다 더 편리하고 성능이 뛰어남 |
| 166 | +- 특히 복잡한 애플리케이션에서는 가독성을 높일 수 있음 |
| 167 | + |
| 168 | +### 심층 객체 확장 패턴 |
| 169 | + |
| 170 | +- 객체 리터럴 표기법으로 선언된 네임스페이스는 다른 객체와 쉽게 확장될 수 있음 |
| 171 | +- 병합 이후에는 두 네임스페이스의 속성과 함수 모두를 동일한 네임스페이스에서 접근할 수 있음 |
| 172 | + |
| 173 | + ```tsx |
| 174 | + // 사용 예시 |
| 175 | + const myNamespace = myNamespace || {}; |
| 176 | + |
| 177 | + extendObjects(myNamespace, { |
| 178 | + utils: {}, |
| 179 | + }); |
| 180 | + |
| 181 | + console.log("test 1", myNamespace); |
| 182 | + |
| 183 | + extendObjects(myNamespace, { |
| 184 | + hello: { |
| 185 | + world: { |
| 186 | + wave: { |
| 187 | + test() { |
| 188 | + //... |
| 189 | + }, |
| 190 | + }, |
| 191 | + }, |
| 192 | + }, |
| 193 | + }); |
| 194 | + |
| 195 | + myNamespace.hello.test1 = "this is a test"; |
| 196 | + myNamespace.hello.world.test2 = "this is another test"; |
| 197 | + console.log("test 2", myNamespace); |
| 198 | + |
| 199 | + myNamespace.library = { |
| 200 | + foo() {}, |
| 201 | + }; |
| 202 | + |
| 203 | + extendObjects(myNamespace, { |
| 204 | + library: { |
| 205 | + bar() { |
| 206 | + //... |
| 207 | + }, |
| 208 | + }, |
| 209 | + }); |
| 210 | + |
| 211 | + console.log("test 3", myNamespace); |
| 212 | + |
| 213 | + const shorterNamespaceAccess = myNamespace.hello.world; |
| 214 | + shorterNamespaceAccess.test3 = "hello again"; |
| 215 | + console.log("test 4", myNamespace); |
| 216 | + ``` |
| 217 | + |
| 218 | +> 글쓴이는 가능하다면 중첩 네임스페이스 자동화 패턴을 구현해서 적용하겠다고 함 |
0 commit comments