
📅 2025-09-18
➡️ JavaScript 동기/비동기, Promise에 대해 새롭게 알게 된 것 또는 헷갈리는 부분 정리 + 🤔❓

| 데이터 타입 | 저장 방식 | 불변성 여부 |
|---|---|---|
| 기본형(Primitive Type) == 원시값 | - 값 자체를 저장 - 값이 담긴 주소값을 바로 복제 | 불변성을 가짐 |
| 참조형(Reference Type) | - 값이 저장된 주소를 참조 - 값이 담긴 주소값을 복제 | 불변성을 가지지 않음 |
깊은 복사 함수 만들기
function copyObjectDeep(target) {
if (typeof target !== "object" || target === null) {
return target; // 기본형은 그대로 반환
}
const result = Array.isArray(target) ? [] : {};
for (let key in target) {
result[key] = copyObjectDeep(target[key]); // 재귀 복사
}
return result;
}
var post = {
title: "자바스크립트 기초",
category: "programming",
author: {
name: "철수",
email: "chul@example.com",
},
};
var post2 = copyObjectDeep(post);
post2.author.name = "영희";
post2.category = "advanced";
console.log(post.author.name); // 철수
console.log(post2.author.name); // 영희
console.log(post.category, post2.category); // programming advanced
JSON 활용
var post = {
title: "자바스크립트 기초",
category: "programming",
author: {
name: "철수",
email: "chul@example.com",
},
};
var post2 = JSON.parse(JSON.stringify(post));
post2.author.name = "영희";
console.log(post.author.name); // 철수
❗ 이 방법에 대한 문제점
- JSON을 이용한 깊은 복사는 모든 정보를 복사하지 않음. 함수, undefined, symbol 복사가 안됨
- 객체가 중복된 경우 복사 안됨
structuredClone()
📎 https://developer.mozilla.org/ko/docs/Web/API/Window/structuredClone
콜백이 많아지면? → 여러 동작을 순서대로 연결해야 할 문제가 생김
getUser(1, function(user){
getPosts(user.id, function(posts){
getComments(posts[0].id, function(comments){
console.log(`첫 번째 댓글 ${comments[0].text}`);
});
});
});
콜백만으로 복잡한 비동기 흐름을 관리하기 어려움 → Promise와 async/await
// async/await 예시
async function main() {
const user = await getUser(1);
const posts = await getPosts(user.id);
const comments = await getComments(posts[0].id);
console.log("첫 번째 댓글:", comments[0].text);
}
main();

console.log("A");
setTimeout(function() {
console.log("B");
}, 1000);
console.log("C");
/*
실행 결과
A
C
(1초뒤) B
*/
const getPromiseWork = new Promise((resolve, reject) => {
console.log("작업 시작!");
setTimeout(() => {
const success = false;
if (success) {
resolve("완료됨");
} else {
reject("실패");
}
}, 2000);
});
getPromsieWork
.then((result) => {
console.log("then:", result);
})
.catch((err) => {
console.error("catch:", err);
})
.finally(() => {
console.log("항상 실행되는 finally");
});new Promise를 호출하면 콜백 함수가 즉시 실행됨resolve(성공) 또는 **reject(실패)를 호출해야 다음 단계로 진행resolve/reject 호출 전까지는 .then(다음), .catch(오류)로 넘어가지 않음.finally는 성공/실패 상관없이 항상 실행됨Promise 상태
- Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
- Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
- Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태
new Promise() 를 호출하게 되면 대기 상태가 됨new Promise();
// 콜백 함수를 선언하고, 인자값으로 resolve(성공) / reject(실패)
new Promsie(function(resolve, reject){});resolve를 호출 하게 되면 상태가 Fulfilled로 전환new Promise(function(resolve, reject) {
resolve();
});.then을 통해 결과값을 받을 수 있음function getNumber() {
return new Promise(function (resolve, reject){
let result = 30;
resolve(result);
}
}
getNumber().then(function(value){
console.log( "결과 :" ,value);
});reject()를 호출하면 상태가 Rejected로 전환
.catch()를 통해 실패를 처리 할 수 있습니다.
function getDataWithError() {
return new Promise(function (resolve, reject) {
reject(new Error("데이터 요청 실패"));
});
}
getDataWithError()
.then(function (v) {
console.log("성공:", v);
})
.catch(function (err) {
console.error("에러 발생:", err.message); // 에러 발생: 데이터 요청 실패
});
.then()을 연속적으로 연결하는 방식function step1() {
return new Promise(function (resolve) {
setTimeout(function () {
console.log("1단계: 버거 빵 준비");
resolve("빵");
}, 500);
});
}
function step2(prev) {
return new Promise(function (resolve) {
setTimeout(function () {
console.log("2단계: 패티 굽고 추가 →", prev);
resolve(prev + " + 패티");
}, 500);
});
}
function step3(prev) {
return new Promise(function (resolve) {
setTimeout(function () {
console.log("3단계: 소스 뿌리기 →", prev);
resolve(prev + " + 소스");
}, 500);
});
}
// 체이닝
step1()
.then(step2)
.then(step3)
.then(function (result) {
console.log("최종 결과 완성된 버거 :", result);
});❗ 오직 프로퍼티만 담을 수 있음. 메서드는 담을 수 없음
❗ 문자열과 프로퍼티의 이름 작성 시 큰 따옴표만 사용해야 함
❗ 콤마나 클론을 잘 못 배치하는 사소한 실수로 작동하지 않을 수 있음
JSONLint → JSON 유효성 검사
const json = '{"result":true, "count":42}';
const obj = JSON.parse(json);
console.log(obj.count);
// Expected output: 42
console.log(obj.result);
// Expected output: true// 둘 다 SyntaxError
JSON.parse("[1, 2, 3, 4, ]");
JSON.parse('{"foo" : 1, }');JSON.stringify({}); // '{}'
JSON.stringify(true); // 'true'
JSON.stringify("foo"); // '"foo"'
JSON.stringify([1, "false", false]); // '[1,"false",false]'
JSON.stringify({ x: 5 }); // '{"x":5}'
JSON.stringify(new Date(2006, 0, 2, 15, 4, 5));
// '"2006-01-02T15:04:05.000Z"'undefined, 함수, 심볼(symbol)은 변환될 때 생략되거나(객체 안에 있을 경우) null 로 변환됨(배열 안에 있을 경우)// Symbols:
JSON.stringify({ x: undefined, y: Object, z: Symbol("") });
// '{}'
JSON.stringify({ [Symbol("foo")]: "foo" });
// '{}'📎 https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/JSON
📎 https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
📎 https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify