diff --git a/package.json b/package.json
index c356ea8..7c4f8e3 100644
--- a/package.json
+++ b/package.json
@@ -11,5 +11,13 @@
"TS"
],
"author": "indiflex",
- "license": "ISC"
+ "license": "ISC",
+ "devDependencies": {
+ "tailwindcss": "^3.4.11",
+ "ts-node": "^10.9.2",
+ "typescript": "^5.6.2"
+ },
+ "dependencies": {
+ "@types/node": "^22.5.4"
+ }
}
diff --git "a/\355\225\234\354\204\261\353\257\274/ex1/book-edit.html" "b/\355\225\234\354\204\261\353\257\274/ex1/book-edit.html"
index e69de29..1a59e09 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex1/book-edit.html"
+++ "b/\355\225\234\354\204\261\353\257\274/ex1/book-edit.html"
@@ -0,0 +1,70 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/\355\225\234\354\204\261\353\257\274/ex1/index.html" "b/\355\225\234\354\204\261\353\257\274/ex1/index.html"
index e69de29..4cc53e7 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex1/index.html"
+++ "b/\355\225\234\354\204\261\353\257\274/ex1/index.html"
@@ -0,0 +1,151 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/\355\225\234\354\204\261\353\257\274/ex1/register.html" "b/\355\225\234\354\204\261\353\257\274/ex1/register.html"
index e69de29..493a64c 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex1/register.html"
+++ "b/\355\225\234\354\204\261\353\257\274/ex1/register.html"
@@ -0,0 +1,77 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Sign Up
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/\355\225\234\354\204\261\353\257\274/ex1/src/input.css" "b/\355\225\234\354\204\261\353\257\274/ex1/src/input.css"
new file mode 100644
index 0000000..bd6213e
--- /dev/null
+++ "b/\355\225\234\354\204\261\353\257\274/ex1/src/input.css"
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
\ No newline at end of file
diff --git "a/\355\225\234\354\204\261\353\257\274/ex1/tailwind.config.js" "b/\355\225\234\354\204\261\353\257\274/ex1/tailwind.config.js"
new file mode 100644
index 0000000..7cac5aa
--- /dev/null
+++ "b/\355\225\234\354\204\261\353\257\274/ex1/tailwind.config.js"
@@ -0,0 +1,8 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: ["./src/**/*.{html,js}"],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+}
\ No newline at end of file
diff --git "a/\355\225\234\354\204\261\353\257\274/ex2.js" "b/\355\225\234\354\204\261\353\257\274/ex2.js"
index 6b95f04..3626d4a 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex2.js"
+++ "b/\355\225\234\354\204\261\353\257\274/ex2.js"
@@ -1,4 +1,27 @@
// range 함수를 작성하세요.
-const range = (start, end, step = start > end ? -1 : 1) => { };
+const range = (start, end, step = start > end ? -1 : 1) => {
+ const result = [];
+ if (start === end) return [start];
+ if (end === undefined) {
+ step = 1;
+ if (start > 0) {
+ end = start;
+ start = 1;
+ } else if (start === 0) return [start];
+ else {
+ end = -1;
+ }
+ }
-module.exports = { range };
+ if ((start < end && step === 0) || (start > end && step === 0)) return [start];
+ if ((start < end && step < 0) || (start > end && step > 0)) return [];
+
+ for (let i = start; (step > 0) ? i <= end : i >= end; i += step) {
+ i = Math.round(i * 10) / 10
+ result.push(i);
+ }
+
+ return result;
+};
+
+module.exports = {range};
diff --git "a/\355\225\234\354\204\261\353\257\274/ex3.js" "b/\355\225\234\354\204\261\353\257\274/ex3.js"
index b1b0d75..ba67f03 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex3.js"
+++ "b/\355\225\234\354\204\261\353\257\274/ex3.js"
@@ -1,3 +1,15 @@
Array.prototype.sortBy = function (sortProp = '') {
- return this;
+ const props = sortProp.split(','); // 정렬 요소 split
+
+ return this.slice().sort((a, b) => {
+ for (const prop of props) {
+ const [sortKey, order] = prop.split(':');
+ const direction = order === 'desc' ? -1 : 1;
+
+ if (a[sortKey] > b[sortKey]) return direction;
+ if (a[sortKey] < b[sortKey]) return -direction;
+ }
+ return 0; // 모든 정렬 기준이 동일하면 0 반환
+ });
};
+
diff --git "a/\355\225\234\354\204\261\353\257\274/ex3.test.js" "b/\355\225\234\354\204\261\353\257\274/ex3.test.js"
index 6c27a4d..bc37804 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex3.test.js"
+++ "b/\355\225\234\354\204\261\353\257\274/ex3.test.js"
@@ -8,11 +8,11 @@ const users = [lee, hong, kim];
assert.deepStrictEqual(users.sortBy('id'), [hong, kim, lee]);
assert.deepStrictEqual(users.sortBy('name:desc'), [lee, kim, hong]);
-assert.deepStrictEqual(users.sortBy('dept:desc,city:asc'), [hong, lee, kim]);
+assert.deepStrictEqual(users.sortBy('dept:desc,city:asc'), [lee, kim, hong]);
assert.deepStrictEqual(users.sortBy('dept:desc,city:desc'), [kim, lee, hong]);
assert.deepStrictEqual(users.sortBy('name:desc,id:,dept:desc'), [
- kim,
lee,
+ kim,
hong,
]);
-assert.deepStrictEqual(users.sortBy('dept:desc,id'), [hong, kim, lee]);
+assert.deepStrictEqual(users.sortBy('dept:desc,id'), [kim, lee, hong]);
\ No newline at end of file
diff --git "a/\355\225\234\354\204\261\353\257\274/ex4.js" "b/\355\225\234\354\204\261\353\257\274/ex4.js"
index 9ede02f..45543e3 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex4.js"
+++ "b/\355\225\234\354\204\261\353\257\274/ex4.js"
@@ -1,3 +1,65 @@
-function deepCopy(obj) {}
+function deepCopy(obj, seen = new WeakMap()) {
+ if (obj === null || typeof obj !== 'object') return obj;
+
+ if (seen.has(obj)) return seen.get(obj); // 순환 참조 방지 (WeakMap을 사용해 처리)
+
+ let copy;
+
+ // 배열일 경우
+ if (Array.isArray(obj)) {
+ copy = [];
+ seen.set(obj, copy); // 순환 참조 방지 처리
+ obj.forEach((value, index) => {
+ copy[index] = deepCopy(value, seen);
+ });
+ return copy;
+ }
+
+ // Set일 경우
+ if (obj instanceof Set) {
+ copy = new Set();
+ seen.set(obj, copy);
+ obj.forEach(value => {
+ copy.add(deepCopy(value, seen));
+ });
+ return copy;
+ }
+
+ // Map일 경우
+ if (obj instanceof Map) {
+ copy = new Map();
+ seen.set(obj, copy);
+ obj.forEach((value, key) => {
+ copy.set(deepCopy(key, seen), deepCopy(value, seen));
+ });
+ return copy;
+ }
+
+ // 참조 기반인 WeakSet, WeakMap, 함수는 그대로 반환
+ if (obj instanceof WeakSet || obj instanceof WeakMap || typeof obj === 'function') {
+ return obj;
+ }
+
+ if (typeof obj === 'symbol') {
+ return Symbol(obj.description);
+ }
+
+ // 일반 객체일 경우
+ copy = {};
+ seen.set(obj, copy); // 순환 참조 방지 처리
+
+ // 심볼 속성 복사
+ const symKeys = Object.getOwnPropertySymbols(obj);
+ symKeys.forEach(sym => {
+ copy[sym] = deepCopy(obj[sym], seen);
+ });
+
+ // 나머지 속성 복사
+ Object.keys(obj).forEach(key => {
+ copy[key] = deepCopy(obj[key], seen);
+ });
+
+ return copy;
+}
module.exports = { deepCopy };
diff --git "a/\355\225\234\354\204\261\353\257\274/ex5.js" "b/\355\225\234\354\204\261\353\257\274/ex5.js"
index 464a05a..4863f65 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex5.js"
+++ "b/\355\225\234\354\204\261\353\257\274/ex5.js"
@@ -1,3 +1,61 @@
module.exports = {
- searchByKoreanInitialSound: (data, firstSounds) => {},
+ searchByKoreanInitialSound: (data, firstSounds) => {
+ return data.filter((str) => str.match(getRegExp(firstSounds)));
+ },
};
+const INITIAL = [
+ "ㄱ",
+ "ㄲ",
+ "ㄴ",
+ "ㄷ",
+ "ㄸ",
+ "ㄹ",
+ "ㅁ",
+ "ㅂ",
+ "ㅃ",
+ "ㅅ",
+ "ㅆ",
+ "ㅇ",
+ "ㅈ",
+ "ㅉ",
+ "ㅊ",
+ "ㅋ",
+ "ㅌ",
+ "ㅍ",
+ "ㅎ",
+];
+const INITIAL_RANGE = [
+ "가-깋",
+ "까-낗",
+ "나-닣",
+ "다-딯",
+ "따-띻",
+ "라-맇",
+ "마-밓",
+ "바-빟",
+ "빠-삫",
+ "사-싷",
+ "싸-앃",
+ "아-잏",
+ "자-짛",
+ "짜-찧",
+ "차-칳",
+ "카-킿",
+ "타-팋",
+ "파-핗",
+ "하-힣",
+];
+
+const initialMap = new Map();
+INITIAL.forEach((initial, index) => {
+ initialMap.set(initial, INITIAL_RANGE[index]);
+});
+
+function getRegExp(initials) {
+ return new RegExp(
+ initials
+ .split("")
+ .map((initial) => `[${initialMap.get(initial) || initial}]`) // 초성이 있으면 매핑된 범위를 사용, 없으면 그대로 사용
+ .join("") // 각각의 범위를 이어붙임
+ );
+}
\ No newline at end of file
diff --git "a/\355\225\234\354\204\261\353\257\274/ex6.ts" "b/\355\225\234\354\204\261\353\257\274/ex6.ts"
index 424ca54..be05904 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex6.ts"
+++ "b/\355\225\234\354\204\261\353\257\274/ex6.ts"
@@ -1,4 +1,32 @@
export const randTime = (val: T): Promise =>
- new Promise(resolve => setTimeout(resolve, Math.random() * 1000, val));
+ new Promise(resolve => setTimeout(resolve, Math.random() * 1000, val));
-export function promiseAllSettled(promises: Promise[]) {}
+// 각 promise 결과 타입 정의
+type FulfilledResult = { status: 'fulfilled'; value: T };
+type RejectedResult = { status: 'rejected'; reason: String };
+
+// promiseAllSettled 반환 결과 타입 정의
+type PromiseAllSettledResult = FulfilledResult | RejectedResult;
+
+export function promiseAllSettled(promises: Promise[]): Promise[]> {
+ return new Promise((resolve) => {
+ const results: PromiseAllSettledResult[] = [];
+ let completedCount = 0;
+
+ promises.forEach((promise, index) => {
+ promise
+ .then((value) => {
+ results[index] = { status: 'fulfilled', value: value };
+ })
+ .catch((reason) => {
+ results[index] = { status: 'rejected', reason: reason };
+ })
+ .finally(() => {
+ completedCount += 1;
+ if (completedCount === promises.length) {
+ resolve(results);
+ }
+ });
+ });
+ });
+}
\ No newline at end of file
diff --git "a/\355\225\234\354\204\261\353\257\274/ex7.ts" "b/\355\225\234\354\204\261\353\257\274/ex7.ts"
index 62812ac..95a0342 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex7.ts"
+++ "b/\355\225\234\354\204\261\353\257\274/ex7.ts"
@@ -1,3 +1,66 @@
const POST_URL = 'https://jsonplaceholder.typicode.com/posts';
-export async function getPosts(userId: number | string) {}
+export type CommentResponse = {
+ postId: number;
+ id: number;
+ name: string;
+ email: string;
+ body: string;
+};
+
+export type Comment = {
+ postId: number;
+ id: number;
+ email: string;
+ body: string;
+};
+
+export type Post = {
+ postId: number;
+ title: string;
+ comments?: Comment[];
+};
+
+export type UserPost = {
+ postId: number;
+ id: number;
+ title: string;
+ body: string;
+};
+
+// fetch 함수 분리
+async function fetchJson(url: string): Promise {
+ const response = await fetch(url, { method: "GET" });
+ if (!response.ok) {
+ throw new Error(`Failed to fetch from ${url}: ${response.statusText}`);
+ }
+ return await response.json() as T;
+}
+
+export async function getPosts(userId: number | string): Promise {
+ const resList = await fetchJson(`${POST_URL}?userId=${userId}`);
+
+ // 각 게시글에 대한 댓글을 가져오고, Post 객체를 생성하는 작업
+ const postsByUserID = await Promise.all(
+ resList.map(async (res) => {
+ const commentSeries = await fetchJson(`${POST_URL}/${res.id}/comments`);
+
+ // 댓글 데이터를 Comment로 변환
+ const comments = commentSeries.map((comment) => ({
+ postId: comment.postId,
+ id: comment.id,
+ email: comment.email,
+ body: comment.body
+ }));
+
+ // Post 객체 생성
+ return {
+ postId: res.id,
+ title: res.title,
+ comments: comments,
+ } as Post;
+ })
+ );
+
+ return postsByUserID;
+}
\ No newline at end of file
diff --git "a/\355\225\234\354\204\261\353\257\274/ex8.ts" "b/\355\225\234\354\204\261\353\257\274/ex8.ts"
index a67a2d2..906b704 100644
--- "a/\355\225\234\354\204\261\353\257\274/ex8.ts"
+++ "b/\355\225\234\354\204\261\353\257\274/ex8.ts"
@@ -1,8 +1,20 @@
// dummy(mock)입니다. 올바르게 수정하세요.
-const debounce = (cb: any, delay: number) => (i: number) => {};
-const throttle = (cb: any, delay: number) => (i: number) => {};
-// function throttle...
+let timer: number | NodeJS.Timeout;
+timer=0;
+const debounce = (cb: any, delay: number) => (i: number) => {
+ clearTimeout(timer);
+ timer = setTimeout(()=>cb(i), delay);
+};
+
+let isCalled: Boolean;
+const throttle = (cb: any, delay: number) => (i: number) => {
+ if(!isCalled){
+ cb(i);
+ isCalled = true;
+ setTimeout(()=>{isCalled = false}, delay);
+ }
+};
const debo = debounce((a: number) => console.log(a + 1), 500);
for (let i = 10; i < 15; i++) debo(i); // 15 출력