diff --git "a/10\354\240\234\353\204\244\353\246\255-12IDE\352\270\260\353\212\245\354\202\254\354\232\251/\353\205\270\354\234\244\354\247\200.md" "b/10\354\240\234\353\204\244\353\246\255-12IDE\352\270\260\353\212\245\354\202\254\354\232\251/\353\205\270\354\234\244\354\247\200.md"
new file mode 100644
index 0000000..ad9eedf
--- /dev/null
+++ "b/10\354\240\234\353\204\244\353\246\255-12IDE\352\270\260\353\212\245\354\202\254\354\232\251/\353\205\270\354\234\244\354\247\200.md"
@@ -0,0 +1,1058 @@
+
+
+
10. 제네릭
+
+
+
+- ts는 `제네릭`을 사용해 타입 간의 관계를 알아냄
+
+# 10.1 제네릭 함수
+
+- 함수의 매개변수나 반환값의 타입을 호출 시점에 결정할 수 있게 해주는 함수
+- 타입 안전성을 유지하면서 다양한 타입 처리 가능
+- ``와 같은 제네릭 타입 매개변수를 선언 (T는 함수 내부에서 사용할 타입)
+
+```ts
+function identity(input: T): T {
+ return input;
+}
+
+const numeric = identity("me"); // 타입: "me"
+const stringy = identity(123); // 타입: 123
+
+// 화살표 함수 예시
+const identity = (input: T): T => input;
+
+identity(123); // 타입: 123
+```
+
+ - 제네릭 화살표 함수 구문은 .tsx 파일에서 JSX 구문과 충동하므로 일부 제한 있음
+
+## 10.1.1 명시적 제네릭 호출 타입
+
+- ts 대부분의 경우 함수가 호출되는 방식을 보고 타입을 유추하지만, 때로는 ts가 타입을 유추할 수 없는 경우에는 타입을 지정해줘야 함
+ ```ts
+ logWrapper((input) => {
+ console.log(input.length); // 타입: (input: string) => void
+ });
+ ```
+- 제네릭 구조체에 두 개보다 많은 매개변수를 사용하지 않는 것을 권장
+
+## 10.1.2 다중 함수 타입 매개변수
+
+```ts
+function makeTuple(first: First, second: Second) {
+ return [first, second] as const;
+}
+
+let tuple = makeTuple(true, "abc"); // value: readonly [boolean, string] 타입
+```
+
+- 여러 개의 타입 매개변수를 선언하면, 해당 함수에 대한 호출은 명시적으로 모든 제네릭 타입을 선언하지 않거나 모두 선언해야 함
+
+ ```ts
+ function makePair(key: Key, value: Value) {
+ return { key, value };
+ }
+
+ // Ok: 타입 인수가 둘 다 제공되지 않음
+ makePair("abc", 123); // 타입: { key: string; value: number }
+
+ // Ok: 두 개의 타입 인수가 제공됨
+ makePair("abc", 123); // 타입: { key: string; value: number }
+ makePair<"abc", 123>("abc", 123); // 타입: { key: "abc"; value: 123 }
+
+ // Error: Expected 2 type arguments, but got 1.
+ makePair("abc", 123);
+ ```
+
+# 10.2 제네릭 인터페이스
+
+```ts
+let stringyBox: Box = {
+ inside: "abc"
+};
+
+let numberBox: Box = {
+ inside: 123
+};
+
+let incorrectBox: Box = {
+ inside: false
+ // Error: Type 'boolean' is not assignable to type 'number'.
+};
+```
+
+- 내장 Array 인터페이스
+
+ ```ts
+ interface Array {
+ /**
+ * 배열에서 마지막 요소를 제거하고 그 요소를 반환합니다.
+ * 배열이 비어 있는 경우 undefined를 반환하고 배열은 수정되지 않습니다.
+ */
+ pop(): T | undefined;
+
+ /**
+ * 배열의 끝에 새로운 요소를 추가하고 배열의 길이를 반환합니다.
+ * @param items 배열에 추가된 새로운 요소
+ */
+ push(...items: T[]): number;
+ }
+ ```
+
+# 10.2.1 유추된 제네릭 인터페이스 타입
+
+```ts
+interface LinkedNode {
+ next?: LinkedNode;
+ value: Value;
+}
+
+function getlast(node: LinkedNode): Value {
+ return node.next ? getlast(node.next) : node.value;
+}
+
+let lastDate = getlast({
+ value: new Date("09-13-1993")
+});
+
+let lastFruit = getlast({
+ next: {
+ value: "banana"
+ },
+ value: "apple"
+});
+
+let lastMismatch = getlast({
+ next: {
+ value: 123
+ },
+ value: false
+});
+```
+
+- 인터페이스가 제네릭 타입을 선언하면, 타입 인수를 제공해야 함
+
+```ts
+interface Cratelike {
+ contents: T;
+}
+
+let missingGeneric: Cratelike = {
+ contents: "??"
+};
+// Error: Generic type 'Crate' requires 1 type argument(s).
+```
+
+# 10.3 제네릭 클래스
+
+- 인터페이스와 마찬가지로 클래스도 타입 매개 변수를 선언하여 나중에 사용할 수 있음
+
+```ts
+class Secret {
+ key: Key;
+ value: Value;
+
+ constructor(key: Key, value: Value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ getValue(key: Key): Value | undefined {
+ return this.key === key ? this.value : undefined;
+ }
+}
+
+const storage = new Secret(12345, "luggage"); // 타입: Secret
+const result = storage.getValue(1987); // 타입: string | undefined
+```
+
+## 10.3.1 명시적 제네릭 클래스 타입
+
+- 셍성자에 전달된 매개변수의 타입으로부터 타입 인수를 유추할 수 있음
+- 유추할 수 없는 경우, 타입 인수의 기본값은 `unknown`
+
+```ts
+class CurriedCallback {
+ #callback: (input: Input) => void;
+
+ constructor(callback: (input: Input) => void) {
+ this.#callback = (input: Input) => {
+ console.log("Input: ", input);
+ callback(input);
+ };
+ }
+
+ call(input: Input) {
+ this.#callback(input);
+ }
+}
+
+// 타입: CurriedCallback
+new CurriedCallback((input: string) => {
+ console.log(input.length);
+});
+
+// 타입: CurriedCallback
+new CurriedCallback((input) => {
+ console.log(input.length);
+ // Error: Property 'length' does not exist on type 'unknown'.
+});
+```
+
+## 10.3.2 제네릭 클래스 확장
+
+- `extends` 키워드로 확장 가능
+
+```ts
+class Quote {
+ lines: T;
+
+ constructor(lines: T) {
+ this.lines = lines;
+ }
+}
+
+class SpokenQuote extends Quote {
+ speak() {
+ console.log(this.lines.join("\n"));
+ }
+}
+
+const spoken = new SpokenQuote([
+ "Greed is so destructive.",
+ "It destroys everything"
+]);
+spoken.speak(); // 출력: Greed is so destructive.\nIt destroys everything
+```
+
+- 제네릭 파생 클래스는 자체 타입 인수를 기본 클래스에 전달 가능 (타입 이름은 일치하지 않아도 됨)
+
+```ts
+class AttributedQuote extends Quote {
+ speaker: string;
+
+ constructor(value: Value, speaker: string) {
+ super(value);
+ this.speaker = speaker;
+ }
+}
+
+// 타입: AttributedQuote
+const attributed = new AttributedQuote(
+ "The road to success is always under construction.",
+ "Lily Tomlin"
+);
+console.log(attributed.lines); // 출력: The road to success is always under construction.
+console.log(attributed.speaker); // 출력: Lily Tomlin
+```
+
+## 10.3.3 제네릭 인터페이스 구현
+
+- 제네릭 인터페이스를 구현할 때도 마찬가지로 기본 인터페이스의 모든 타입 매개변수는 클래스에 선언되어야 함
+
+```ts
+interface ActingCredit {
+ role: Role;
+}
+
+class MoviePart implements ActingCredit {
+ role: string;
+ speaking: boolean;
+
+ constructor(role: string, speaking: boolean) {
+ this.role = role;
+ this.speaking = speaking;
+ }
+}
+
+const part = new MoviePart("Miranda Priestly", true);
+console.log(part.role); // 출력: Miranda Priestly
+
+// 타입 오류
+class IncorrectExtension implements ActingCredit {
+ role: boolean;
+ // Error: Property 'role' in type 'IncorrectExtension' is not
+ // assignable to the same property in base type 'ActingCredit'.
+ // Type 'boolean' is not assignable to type 'string'.
+}
+```
+
+## 10.3.4 메서드 제네릭
+
+- 클래스 메서드는 클래스 인스턴스와 별개로 자체 제네릭 타입 선언 가능
+
+```ts
+class CreatePairFactory {
+ key: Key;
+
+ constructor(key: Key) {
+ this.key = key;
+ }
+
+ createPair(value: Value) {
+ return { key: this.key, value };
+ }
+}
+
+// 타입: CreatePairFactory
+const factory = new CreatePairFactory("role");
+
+// 타입: { key: string, value: number }
+const numberPair = factory.createPair(10);
+console.log(numberPair); // 출력: { key: 'role', value: 10 }
+
+// 타입: { key: string, value: string }
+const stringPair = factory.createPair("Sophie");
+console.log(stringPair); // 출력: { key: 'role', value: 'Sophie' }
+```
+
+## 10.3.4 정적 클래스 제네릭
+
+- `static` 멤버는 인스턴스 멤버와 구별되며, 특정 인스턴스와 연결되지 않음
+- 정적 클래스 메서드는 자체 타입 매개변수를 선언할 수 있지만, 클래스에 선언된 어떤 타입 매개변수에도 접근 불가능
+
+```ts
+class BothLogger {
+ instancelog(value: OnInstance) {
+ console.log(value);
+ return value;
+ }
+
+ static staticlog(value: OnStatic) {
+ // let fromInstance: OnInstance; // Error: Static members cannot reference class type arguments.
+ console.log(value);
+ return value;
+ }
+}
+
+// 타입: BothLogger
+const logger = new BothLogger();
+logger.instancelog([1, 2, 3]); // 출력: [1, 2, 3]
+
+// 유추된 OnStatic 타입 인수: boolean[]
+BothLogger.staticlog([false, true]); // 출력: [false, true]
+
+// 유추된 OnStatic 타입 인수: string
+BothLogger.staticlog("You can't change the music of your soul."); // 출력: You can't change the music of your soul.
+```
+
+# 10.4 제네릭 타입 별칭
+
+```ts
+type Nullish = T | null | undefined;
+
+type CreatesValue = (input: Input) => Output;
+
+// 타입: (input: string) => number
+let creator: CreatesValue;
+
+// 올바른 할당
+creator = (text) => text.length; // Ok
+
+// 타입 오류: 반환 타입이 맞지 않음
+creator = (text) => text.toUpperCase();
+// Error: Type 'string' is not assignable to type 'number'.
+```
+
+## 10.4.1 제네릭 판별된 유니언
+
+- 타입 내로잉을 통해 특정 타입을 좁히는 데 사용되는 패턴
+- 성공적인 결과와 오류를 나타내는 제네릭 **결과** 타입을 만들기 위해 자주 사용됨
+
+```ts
+type Result = FailureResult | SuccessfulResult;
+
+interface FailureResult {
+ error: Error;
+ succeeded: false;
+}
+
+interface SuccessfulResult {
+ data: Data;
+ succeeded: true;
+}
+
+function handleResult(result: Result) {
+ if (result.succeeded) {
+ // result: SuccessfulResult 타입
+ console.log(`We did it! ${result.data}`);
+ } else {
+ // result: FailureResult 타입
+ console.error(`Awww... ${result.error}`);
+ }
+}
+
+// 사용 예제
+const successResult: Result = { data: "Success!", succeeded: true };
+const failureResult: Result = {
+ error: new Error("Failure"),
+ succeeded: false
+};
+
+handleResult(successResult); // 출력: We did it! Success!
+handleResult(failureResult); // 출력: Awww... Error: Failure
+```
+
+# 10.5 제네릭 제한자
+
+## 10.5.1 제네릭 기본값
+
+- 타입 인수가 명시적으로 제공되지 않거나, 유추할 수 없는 경우에 사용
+
+```ts
+interface Quote {
+ value: T;
+}
+
+// 명시적으로 number 타입 지정
+let explicit: Quote = { value: 123 };
+
+// 기본값 string 사용
+let implicit: Quote = {
+ value: "Be yourself. The world worships the original."
+};
+
+// 타입 오류: number는 string에 할당할 수 없음
+let mismatch: Quote = { value: 123 };
+// Error: Type 'number' is not assignable to type 'string'.
+```
+
+- 기본값이 있는 제네릭 타입 매개변수는 선언 목록의 마지막에 위치해야 함
+
+```ts
+function inTheEnd() {} // Ok
+function inTheMiddle() {}
+// Error: Required type parameters may not follow optional type parameters.
+```
+
+# 10.6 제한된 제네릭 타입
+
+- `extends` 키워드로 제한할 타입을 명시
+
+```ts
+interface WithLength {
+ length: number;
+}
+
+function logWithLength(input: T) {
+ console.log(`Length: ${input.length}`);
+ return input;
+}
+
+logWithLength("No one can figure out your worth but you."); // 타입: string
+logWithLength([false, true]); // 타입: boolean[]
+logWithLength({ length: 123 }); // 타입: { length: number }
+logWithLength(new Date()); // 타입 오류: Date는 length 속성이 없음
+// Error: Argument of type 'Date' is not assignable to parameter of type 'WithLength'.
+// Property 'length' is missing in type 'Date' but required in type 'WithLength'.
+```
+
+## 10.6.1. keyof와 제한된 타입 매개변수
+
+- `extends`와 `keyof`를 함께 사용하면 타입 매개변수를 이전 타입 매개변수의 키로 제한 가능
+- 제네릭 타입의 키를 지정하는 유일한 방법
+
+```ts
+function get(container: T, key: Key) {
+ return container[key];
+}
+
+const roles = {
+ favorite: "Fargo",
+ others: ["Almost Famous", "Burn After Reading", "Nomadland"]
+};
+
+const favorite = get(roles, "favorite"); // 타입: string
+const others = get(roles, "others"); // 타입: string[]
+const missing = get(roles, "extras"); // 타입 오류: 'extras'는 'roles'의 키가 아님
+// Error: Argument of type '"extras"' is not assignable to parameter of type '"favorite" | "others"'.
+```
+
+- `keyof` 없이 사용하면 제네릭 `key` 매개변수를 올바르게 입력할 방법이 없음
+
+ ```ts
+ function get(container: T, key: keyof T) {
+ return container[key];
+ }
+
+ const roles = {
+ favorite: "Fargo",
+ others: ["Almost Famous", "Burn After Reading", "Nomadland"]
+ };
+
+ // 모든 속성 값에 대한 유니언 타입이 됨
+ const found = get(roles, "favorite"); // 타입: string | string[]
+ ```
+
+# 10.7 Promise
+
+- `Promise`는 네트워크 요청과 같은 비동기 작업을 처리하기 위해 사용됨
+- 성공적으로 완료되면 `resolve`를, 오류가 발생하면 `reject`를 호출함
+
+- `Promise`는 제네릭 타입을 사용하여 최종적으로 `resolve`된 값의 타입을 나타냄
+
+## 10.7.1 Promise 생성
+
+- `Promise` 생성자는 단일 매개변수를 받고, 이 매개변수 타입은 제네릭 `Promise` 클래스에 선언된 타입 매개변수에 의존함
+
+ ```ts
+ class Promiselike {
+ constructor(
+ executor: (
+ resolve: (value: Value) => void,
+ reject: (reason: unknown) => void
+ ) => void
+ ) {
+ // ...
+ }
+ }
+
+ // 타입: Promise
+ const resolvesUnknown = new Promise((resolve) => {
+ setTimeout(() => resolve("Done!"), 1000);
+ });
+
+ // 타입: Promise
+ const resolvesString = new Promise((resolve) => {
+ setTimeout(() => resolve("Done!"), 1000);
+ });
+ ```
+
+ - `Promise`의 제네릭 `then` 메서드는 반환되는 `Promise`의 `resolve`된 값을 나타내는 새로운 타입 매개변수를 받음
+
+ ```ts
+ // 타입: Promise
+ const textEventually = new Promise((resolve) => {
+ setTimeout(() => resolve("Done!"), 1000);
+ });
+
+ // 타입: Promise
+ const lengthEventually = textEventually.then((text) => text.length);
+ ```
+
+## 10.7.2 Async 함수
+
+- `async` 키워드를 사용해 선언한 함수는 항상 `Promise`를 반환함 (반환타입은 항상 `Promise` 형태여야 함)
+- `async` 함수는 반환된 값이 `Thenable`인 경우, `Promise.resolve`를 래핑함
+
+```ts
+// 타입: (text: string) => Promise
+async function lengthAfterSecond(text: string): Promise {
+ await new Promise((resolve) => setTimeout(resolve, 1000));
+ return text.length;
+}
+
+// 타입: (text: string) => Promise
+async function lengthImmediately(text: string): Promise {
+ return text.length;
+}
+
+// Ok => Promise.resolve("Done!")으로 래핑
+async function givesPromiseForString(): Promise {
+ return "Done!";
+}
+
+// 타입 오류: 반환 타입이 Promise가 아님
+async function givesString(): string {
+ // Error: The return type of an async function or method must be the global Promise type.
+ return "Done!";
+}
+```
+
+# 10.8 제네릭 올바르게 사용하기
+
+- 제네릭 무지성 사용 금지 (코드가 복잡해질 가능성 큼)
+- 유틸리티 라이브러리에 대한 타입, 특히 범용 모듈은 경우에 따라 제네릭을 많이 사용할 수도 있음
+
+## 10.8.1 제네릭 황금률
+
+- 타입 매개변수가 최소 두 번 이상 사용되면 제네릭이 필요하다는 것
+- 각 함수 타입 매개변수는 매개변수에서 사용되어야 하고, 그다음 적어도 하나의 다른 매개변수 또는 함수의 반환 타입에서도 사용되어야 함
+
+- 잘못된 제네릭 사용 예제
+
+ ```ts
+ function logInput(input: Input) {
+ console.log("Hi!", input);
+ }
+ ```
+
+ - Input 타입 매개변수가 선언하기 위해서만 사용되므로, 제네릭 X
+
+ ```ts
+ function logInput(input: string) {
+ console.log("Hi!", input);
+ }
+ ```
+
+- 유용한 제네릭 사용 예제
+
+ ```ts
+ function identity(arg: T): T {
+ return arg;
+ }
+ ```
+
+ - T가 선언, 반환 타입 모두 사용되므로, 제네릭 Good
+
+## 10.8.1 제네릭 명명 규칙
+
+- 첫 번째 타입 인수는 T를, 그다음은 U, V 등이 사용됨
+
+ ```ts
+ function map(array: T[], transform: (item: T) => U): U[] {
+ return array.map(transform);
+ }
+ ```
+
+- 타입 인수가 어떻게 사용되어야 하는지 맥락과 관련된 정보가 알려진 경우, 명명 규칙은 해당 용어의 첫 글자를 사용함
+
+ ```ts
+ interface State {
+ state: S;
+ }
+
+ interface KeyValuePair {
+ key: K;
+ value: V;
+ }
+ ```
+
+- 제네릭의 의도가 단일 문자에서 명확하지 않을 경우, 타입이 사용되는 용도를 가리키는 이름을 사용
+
+ ```ts
+ function labelBox