diff --git "a/Chapter_19/GeonHo/\354\240\225\353\246\254.md" "b/Chapter_19/GeonHo/19.1~19.7 \354\240\225\353\246\254.md"
similarity index 100%
rename from "Chapter_19/GeonHo/\354\240\225\353\246\254.md"
rename to "Chapter_19/GeonHo/19.1~19.7 \354\240\225\353\246\254.md"
diff --git "a/Chapter_19/GeonHo/19.8~19.14 \354\240\225\353\246\254.md" "b/Chapter_19/GeonHo/19.8~19.14 \354\240\225\353\246\254.md"
new file mode 100644
index 0000000..668508d
--- /dev/null
+++ "b/Chapter_19/GeonHo/19.8~19.14 \354\240\225\353\246\254.md"
@@ -0,0 +1,183 @@
+## 19.8 오버라이딩과 프로퍼티 섀도잉
+
+`오버라이딩`이란?
+
+- 상위 클래스의 메서드를 하위 클래스에서 재정의하는 것을 말한다.
+
+`프로퍼티 섀도잉`이란?
+
+- 프로토타입 프로퍼티와 같은 이름의 프로퍼티를 인스턴스에 추가하면, 프로토타입 프로퍼티를 덮어쓰는 것이 아닌 인스턴스 프로퍼티로 추가된다.
+- 이렇게 프로퍼티를 오버라이딩하여 상속 관계에 의한 프로퍼티가 가려지는 현상이 프로퍼티 섀도잉이다.
+
+
+
+**인스턴스 등의 하위 객체를 통해 상위 프로토타입의 프로퍼티를 변경 또는 삭제하는 것은 불가능하다.**
+다시 말해, get은 허용되나 set은 허용되지 않는다
+
+
+
+## 19.9 프로토타입의 교체
+
+프로토타입은 임의의 다른 객체로 변경할 수 있다.
+생성자 함수의 prototype 또는 인스턴스의 **proto** 접근자 프로퍼티를 통해 프로토타입을 교체할 수 있다.
+
+```js
+const Person = (function () {
+ function Person(name) {
+ this.name = name;
+ }
+
+ // Person 생성자 함수의 프로토타입을 아래 객체로 교체하였다.
+ Person.prototype = {
+ sayHello() {
+ console.log(`Hi! My name is ${this.name}`);
+ },
+ };
+
+ return Person;
+})();
+
+const me = new Person("Lee");
+```
+
+위 코드에서 Person 생성자 함수의 프로토타입을 새로운 객체로 교체했다.
+다만, 위 프로토타입 객체는 constructor 프로퍼티가 없다.
+때문에 인스턴스 me는 생성자 함수가 Person이 아닌 Object다.
+
+```js
+console.log(me.constructor === Person); // false
+console.log(me.constructor === Object); // true
+```
+
+
+
+생성자 함수가 Person을 가르키게하려면 아래와 같이 객체를 수정하면 된다.
+
+```js
+Person.prototype = {
+ constructor: Person,
+ sayHello() {
+ console.log(`Hi! My name is ${this.name}`);
+ },
+};
+```
+
+위와 같이 생성자 함수를 활용한 프로토타입 교체 방식과 인스턴스의 **proto** 접근자 프로퍼티를 활용한 프로토타입 교체 방식은 조금 다르다.
+생성자 함수의 경우, 생성자함수는 생성자 함수.prototype을 가르키지만 인스턴스의 **proto** 접근자 프로퍼티를 사용한 방식은 그렇지 않다.
+
+
+
+## 19.10 instanceof 연산자
+
+```js
+객체 instanceof 생성자 함수
+```
+
+instanceof 연산자는 생성자 함수의 prototype에 바인딩된 객체가 객체의 프로토타입 체인 상에 존재하면 true를 반환한다.
+
+
+
+## 19.11 직접 상속
+
+## 19.12 정적 프로퍼티/메서드
+
+어떤 생성자 함수 객체가 소유한 프로퍼티/메서드를 뜻한다.
+
+정적 프로퍼티/메서드는 new로 생성된 인스턴스도 참조할 수 없다.
+왜냐하면 인스턴스로 참조할 수 있는 프로퍼티/메서드는 프로토타입 체인 상에 존재해야하기 때문인데,
+정적 프로퍼티/메서드는 생성자 함수 객체에 바인딩되어 있기 때문이다.
+
+정적 프로퍼티/메서드와 프로토타입 프로퍼티/메서드의 차이점은
+`생성자함수.fn()` 인지 `생성자함수.prototype.fn()` 로 구분할 수 있다.
+
+
+
+## 19.13 프로퍼티 존재 확인
+
+### in
+
+in 연산자는 확인 대상 객체 뿐 아니라, 상속받은 모든 프로토타입 프로퍼티를 확인한다.
+
+```js
+const person = {
+ name: "Lee",
+ address: "Seoul",
+};
+
+console.log("name" in person); // true
+console.log("address" in person); // true
+console.log("age" in person); // false
+console.log("toString" in person); // true
+// toString은 Object.prototype의 메서드이다.
+// person 객체가 Object.prototype을 상속받았으므로 true를 리턴한다.
+```
+
+### hasOwnProperty
+
+상속받은 프로퍼티의 경우 false를 리턴, 고유 프로퍼티의 key인 경우에만 true를 리턴한다.
+
+
+
+## 19.14 프로퍼티 열거
+
+### for...in
+
+for...in 문은 객체의 프로퍼티를 열거할 때 사용한다.
+in 연산자와 마찬가지로 상속받은 프로토타입의 프로퍼티까지 열거한다.
+
+해서 vsc의 for...in 문의 snippet을 보면 다음과 같이 hasOwnProperty 메서드가 포함되어 있다.
+
+```js
+for (const key in object) {
+ if (Object.hasOwnProperty.call(object, key)) {
+ const element = object[key];
+ ...
+ }
+}
+```
+
+다만, Object.prototype의 toString 같은 프로퍼티는 열거하지 않는다.
+
+왜일까?
+이는 프로퍼티의 열거 가능 여부를 판별하는 `내부 슬롯 [[Enumerable]]`이 false이기 때문이다.
+
+또한, for...in은 열거시 순서를 보장하지 않는다.
+다만, 대부분의 브라우저에서는 순서를 보장하고, *숫자인 프로퍼티 키에 대해서는 정렬*을 한다.
+
+
+
+객체 자신의 고유 프로퍼티만 열거하기 위해서는 for...in 문 보다는 Object.keys / values / entries 메서드를 사용하는 것이 좋다.
+
+### Object.keys
+
+```js
+const person = {
+ name: "Lee",
+ address: "Seoul",
+ __proto__: { age: 20 },
+};
+
+console.log(Object.keys(person)); // ['name', 'address']
+```
+
+객체 자신의 열거 가능한 프로퍼티 키를 **배열**로 반환한다.
+
+
+
+### Object.values
+
+```js
+console.log(Object.values(person)); // ['Lee', 'Seoul']
+```
+
+'' value를 배열로 반환한다.
+
+
+
+### Object.entries
+
+```js
+console.log(Object.entries(person)); // [['name', 'Lee'], ['address', 'Seoul']]
+```
+
+'' key, value를 배열로 반환한다.
diff --git a/Chapter_23/GeonHo/img/image-1.png b/Chapter_23/GeonHo/img/image-1.png
new file mode 100644
index 0000000..39a046f
Binary files /dev/null and b/Chapter_23/GeonHo/img/image-1.png differ
diff --git a/Chapter_23/GeonHo/img/image-2.png b/Chapter_23/GeonHo/img/image-2.png
new file mode 100644
index 0000000..a058c4c
Binary files /dev/null and b/Chapter_23/GeonHo/img/image-2.png differ
diff --git a/Chapter_23/GeonHo/img/image-3.png b/Chapter_23/GeonHo/img/image-3.png
new file mode 100644
index 0000000..dd94144
Binary files /dev/null and b/Chapter_23/GeonHo/img/image-3.png differ
diff --git a/Chapter_23/GeonHo/img/image-4.png b/Chapter_23/GeonHo/img/image-4.png
new file mode 100644
index 0000000..1c5271e
Binary files /dev/null and b/Chapter_23/GeonHo/img/image-4.png differ
diff --git a/Chapter_23/GeonHo/img/image.png b/Chapter_23/GeonHo/img/image.png
new file mode 100644
index 0000000..02a0fcf
Binary files /dev/null and b/Chapter_23/GeonHo/img/image.png differ
diff --git "a/Chapter_23/GeonHo/\354\240\225\353\246\254.md" "b/Chapter_23/GeonHo/\354\240\225\353\246\254.md"
new file mode 100644
index 0000000..28ed6ab
--- /dev/null
+++ "b/Chapter_23/GeonHo/\354\240\225\353\246\254.md"
@@ -0,0 +1,83 @@
+# 23장 실행 컨텍스트
+
+1. 소스코드의 타입
+ - 전역 코드
+ - 함수 코드
+ - eval 코드
+ - 모듈 코드
+2. 소스코드의 평가와 실행
+ 모든 소스코드는 실행 전 평과 과정을 거친다.
+ 즉 JS 엔진은 소스코드를 '평가' 와 '실행' 과정으로 나누어 처리한다.
+
+ '평가'과정에서는 실행 컨텍스트를 생성하고, 변수나 함수 선언문만 실행하여
+ 실행 컨텍스트가 관리하는 스코프(렉시컬 환경의 환경 레코드)에 등록한다
+
+ 평가 과정 이후 '실행'과정이 시작된다. 즉 런타임이 시작된다.
+ 변수나 함수에 대한 정보는 실행 컨텍스트가 관리하는 스코프에서 가져온다.
+ 또 변수 값의 변경 등은 다시 스코프에 등록한다.
+
+3. 실행 컨텍스트의 역할
+
+ 
+
+ 위와 같은 상황에서, 각 코드들을 스코프에 맞게 구분하여 관리하게 위하여
+ 스코프, 식별자, 코드 실행 순서 등의 관리가 필요하다.
+
+ 이를 위해 실행 컨텍스트가 존재한다.
+
+ 실행 컨텍스트는 식별자를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 매커니즘으로,
+ 모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다.
+
+ 식별자와 스코프는, 실행 컨텍스트의 렉시컬 환경으로 관리하고,
+ 코드 실행 순서는 실행 컨텍스트 스택으로 관리한다.
+
+4. 실행 컨텍스트의 스택
+ JS 엔진은 먼저 전역 코드를 평가하여 '전역' 실행 컨텍스트를 생성한다.
+ 그러다 함수가 호출되면, 함수 코드를 평가하여 '함수' 실행 컨텍스트를 생성한다.
+ 이렇게 생성된 실행 컨텍스트는 스택 자료구조로 관리되는데, 이를 실행 컨텍스트 스택이라고 한다.
+5. 렉시컬 환경
+ 실행 컨텍스트가 코드 실행 순서를 관리한다면,
+ 렉시컬 환경은 스코프와 식별자를 관리한다.
+ 
+
+ 사진과 같이, 렉시컬 환경은 key | value 형태의 객체 스코프이다.
+ 실행 컨텍스트는 렉시컬 환경과 변수 환경으로 구성되어있는데,
+ 일단 간략하게 배우기 위해, 두개를 합쳐 렉시컬 환경이라 하겠다.
+
+ 렉시컬 환경은 두 개의 컴포넌트로 구성된다.
+
+ 
+
+ 1. 환경레코드
+ 스코프에 포함된 식별자와 바인딩 된 값을 관리한다.
+
+ 2. 외부 렉시컬 환경에 대한 참조
+ 상위 스코프, 즉 해당 실행 컨텍스트를 생성한 소스코드를 포함하는 렉시컬 환경을 가르킨다.
+
+6. 실행 컨텍스트의 생성과 식별자 검색 과정
+
+ 
+
+ 위 코드의 실행 컨텍스트와 렉시컬 환경에 대해 아라보자.
+
+ 
+
+ 우선 전역 먼저.
+ 전역 실행 환경에서 전역 렉시컬 환경을 생성하고 전역 렉시컬 환경을 바인딩.
+ 전역 환경 레코드는 var같은 객체 환경 레코드와 const, let 같은 선언 환경 레코드를 분리해서 바인딩한다.
+ var의 경우 변수의 선언 단계와 초기화 단계가 동시에 진행되다보니 전역 객체에 바로 undefined가 할당된다.
+
+ 허나 let, const는 선언 단계 후 초기화 단계가 분리되어 실행되기에,
+ 런타임이 변수 선언문에 닿아 값이 할당되기 전 까지, 변수에 접근할 수 없는 일시적 사각지대에 빠지게 된다.
+ 때문에 y에 가 바인딩되어있다.
+
+ this도 전역 환경 레코드 내부 슬롯에 바인딩 된다.
+
+ 외부 렉시컬 환경 참조에는 null 이 할당된다. 왜냐면 전역이라 참조할 곳이 없기 때문.
+
+ 이렇게 전역 실행 컨텍스트와 렉시컬 환경에 대하여 알아보았다.
+ 마지막으로 전역 코드가 실행되면 x, y에 값이 할당되고, foo 함수가 호출된다.
+
+ 소스코드를 보면, 동일한 이름의 식별자가 각기 다른 스코프에 존재할 수 있다.
+ 이럴때 JS는 식별자 결정을 위해 실행중인 실행 컨텍스트에서부터 식별자를 검색하기 시작한다.
+ 이때 식별자를 못찾으면, 외부 렉시컬 환경이 가르키는 상위 스코프로 이동하여 식별자를 검색한다.
diff --git "a/Chapter_24/GeonHo/\354\240\225\353\246\254.md" "b/Chapter_24/GeonHo/\354\240\225\353\246\254.md"
new file mode 100644
index 0000000..3d46346
--- /dev/null
+++ "b/Chapter_24/GeonHo/\354\240\225\353\246\254.md"
@@ -0,0 +1,229 @@
+# 클로저
+
+### 24.1 렉시컬 스코프
+
+자바스크립트 엔진은 함수를 어디서 호출하는지가 아니라 어디에 정의 했는지에 따라 상위 스코프가 결정된다.
+
+그리고 객체가 생성되는 시점에 상위 스코프가 결정된다.([[Environment]] 내부 슬롯에 저장)
+이후 함수가 호출되고 함수 몸체 코드가 평가되는 시점에 외부 렉시컬 환경에 대한 참조에 객체가 생성될때 저장한 상위 스코프를 참조값을 저장한다.
+
+
+
+### 24.2 함수 객체의 내부 슬롯[[Environment]]
+
+함수 정의가 평가되어 함수 객체를 생성할 때 자신이 정의된 환경(위치)에 의해 결정된 상위 스코프의 참조를 함수 객체 자신의 내부 슬롯[[Environment]]에 저장한다.
+[[Environment]]내부 슬롯에 저장된 상위 스코프의 참조는 현재 실행 중인 실행 컨텍스트의 렉시컬 환경을 가리킨다.
+
+함수 객체의 [[Environment]] 내부 슬롯에 저장된 상위 스코프는 자신이 호출되었을 때 생성될 함수 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장될 참조 값이다.
+
+```js
+const x = 1;
+
+function foo() {
+ const x = 10;
+
+ // 상위 스코프는 함수 정의 환경(위치)에 따라 결정된다.
+ // 함수 호출 위치와 상위 스코프는 아무런 관계가 없다.
+ bar();
+}
+
+// 함수 bar는 자신의 상위 스코프, 즉 전역 렉시컬 환경을 [[Environment]]에 저장하여 기억한다.
+function bar() {
+ console.log(x);
+}
+
+foo(); // 1
+bar(); // 1
+```
+
+### 24.3 클로저와 렉시컬 환경
+
+외부 함수보다 중첩 함수가 더 오래 유지되는 경우, 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다.
+이러한 중첩 함수를 클로저(closure)라고 부른다.
+
+JS의 모든 함수는 자신의 상위 스코프를 기억한다고 했다.
+모든 함수가 기억하는 상위 스코프는 함수를 어디서 호출하든 상관없이 유지된다.
+
+따라서 함수를 어디서 호출하든 상관없이 함수는 언제나 자신이 기억하는 상위 스코프의 식별자를 참조할 수 있으며 식별자에 바인딩된 값을 변경할 수도 있다.
+
+### 24.4 클로저의 활용
+
+클로저는 상태state를 안전하게 변경하고 유지하기 위해 사용된다.
+
+상태를 안전하게 은닉(information hiding)하고 특정 함수에게만 상태 변경을 허용하기 위해 사용된다.
+
+1.전역 변수로 관리
+
+```js
+// 카운트 상태 변수
+let num = 0;
+
+// 카운트 상태 변경 함수
+const increase = function () {
+ // 카운트 상태를 1만큼 증가 시킨다.
+ return ++num;
+};
+
+console.log(increase()); // 1
+console.log(increase()); // 2
+console.log(increase()); // 3
+```
+
+위 코드는 오류의 가능성이 있어 좋지 않은 코드다.
+num 전역 변수에 언제든지 누구나 접근하여 변경이 가능하기 때문이다.
+
+2.함수의 지역 변수로 관리
+
+```js
+// 카운트 상태 변경 함수
+const increase = function () {
+ // 카운트 상태 변수
+ let num = 0;
+
+ // 카운트 상태를 1만큼 증가 시킨다.
+ return ++num;
+};
+
+// 이전 상태를 유지하지 못한다.
+console.log(increase()); // 1
+console.log(increase()); // 1
+console.log(increase()); // 1
+```
+
+지역 변수로 활용하여 첫 번째 예제보다는 좋아 보이지만 함수가 호출될 때마다 지역 변수num은 다시 선언되어 0으로 초기화되기 때문에 상태를 유지하지 못한다.
+
+3.클로저 활용
+
+```js
+// 카운트 상태 변경 함수
+const increase = (function () {
+ // 카운트 상태 변수
+ let num = 0;
+
+ // 클로저
+ return function () {
+ // 카운트 상태를 1만큼 증가 시킨다.
+ return ++num;
+ };
+})();
+
+console.log(increase()); // 1
+console.log(increase()); // 2
+console.log(increase()); // 3
+```
+
+위 코드는 클로저다.
+
+클로저로 num의 상태state를 은닉하여 의도치 않게 변경되지 않도록 안전하게 관리하고
+특정 함수에게만 상태 변경을 허용하여 상태를 안전하게 변경하고 유지한다.
+
+4.감소 기능 추가(클로저)
+
+```js
+const counter = (function () {
+ // 카운트 상태 변수
+ let num = 0;
+
+ // 클로저인 메서드를 갖는 객체를 반환한다.
+ // 객체 리터럴은 스코프를 만들지 않는다.
+ // 따라서 아래 메서드들의 상위 스코프는 즉시 실행 함수의 렉시컬 환경이다.
+ return {
+ // num: 0, // 프로퍼티는 public하므로 은닉되지 않는다.
+ increase() {
+ return ++num;
+ },
+ decrease() {
+ return num > 0 ? --num : 0;
+ },
+ };
+})();
+
+console.log(counter.increase()); // 1
+console.log(counter.increase()); // 2
+
+console.log(counter.decrease()); // 1
+console.log(counter.decrease()); // 0
+```
+
+5.생성자 함수로 표현(클로저)
+increase, decrease 메서드는 프로토타입 메서드이다.
+이 메서드들이 평가되어 함수 객체가 생성될 때 실행 중인 실행 컨텍스트는 즉시 실행 함수의 실행 컨텍스트이다. 따라서 increase, decrease메서드는 즉시 실행 함수의 실행 컨텍스트의 렉시컬 환경을 기억하는 클로저 이다.
+
+```js
+const Counter = (function () {
+ // ① 카운트 상태 변수
+ let num = 0;
+
+ function Counter() {
+ // this.num = 0; // ② 프로퍼티는 public하므로 은닉되지 않는다.
+ }
+
+ Counter.prototype.increase = function () {
+ return ++num;
+ };
+
+ Counter.prototype.decrease = function () {
+ return num > 0 ? --num : 0;
+ };
+
+ return Counter;
+})();
+
+const counter = new Counter();
+
+console.log(counter.increase()); // 1
+console.log(counter.increase()); // 2
+
+console.log(counter.decrease()); // 1
+console.log(counter.decrease()); // 0
+```
+
+6.고차 함수 활용한 클로저(클로저)
+
+```js
+// 함수를 인수로 전달받고 함수를 반환하는 고차 함수
+// 이 함수는 카운트 상태를 유지하기 위한 자유 변수 counter를 기억하는 클로저를 반환한다.
+function makeCounter(predicate) {
+ // 카운트 상태를 유지하기 위한 자유 변수
+ let counter = 0;
+
+ // 클로저를 반환
+ return function () {
+ // 인수로 전달 받은 보조 함수에 상태 변경을 위임한다.
+ counter = predicate(counter);
+ return counter;
+ };
+}
+
+// 보조 함수
+function increase(n) {
+ return ++n;
+}
+
+// 보조 함수
+function decrease(n) {
+ return --n;
+}
+
+// 함수로 함수를 생성한다.
+// makeCounter 함수는 보조 함수를 인수로 전달받아 함수를 반환한다
+const increaser = makeCounter(increase); // ①
+console.log(increaser()); // 1
+console.log(increaser()); // 2
+
+// increaser 함수와는 별개의 독립된 렉시컬 환경을 갖기 때문에 카운터 상태가 연동하지 않는다.
+const decreaser = makeCounter(decrease); // ②
+console.log(decreaser()); // -1
+console.log(decreaser()); // -2
+```
+
+### 24.5 캡슐화와 정보 은닉
+
+캡슐화(encapsulation)는 객체의 상태(state)를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것을 말한다.
+
+캡슐화는 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용하기도 하는데 이를 정보 은닉(information hiding)이라 한다.
+
+정보 은닉은 외부에 공개할 필요가 없는 구현의 일부를 외부에 공개되지 않도록 감추어 적절치 못한 접근으로부터 객체의 상태가 변경되는 것을 방지해 정보를 보호하고, 객체 간의 상호 의존성, 즉 결합도(coupling)를 낮추는 효과가 있다.
+
+대부분의 객체지향 프로그래밍 언어는 public, private, protected와 같은 접근 제한자(access modifier)를 제공하지만 자바스크립트는 제공하지 않는다.
+즉 모든 프로퍼티와 메서드는 public이다.