7. 깊은 복사와 얕은 복사의 차이는 무엇이고 JS에서 각각을 구현하는 방법은 어떻게 되는지 설명해주세요.
🔍 깊은 복사(Deep Copy) vs 얕은 복사(Shallow Copy)
✅ 개념 정리
- 얕은 복사(Shallow Copy): 객체의 참조 값만 복사하여 원본과 복사본이 동일한 메모리 주소를 공유함.
- 깊은 복사(Deep Copy): 객체의 모든 속성을 새로운 메모리 공간에 복사하여 원본과 독립적인 객체를 생성함.
🛠 JavaScript에서 구현 방법
✏️ 얕은 복사(Shallow Copy)
✔️ 대표적인 얕은 복사 방법
- Object.assign()
- 전개 연산자 { ...obj }
- Array.prototype.slice() (배열 복사)
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
shallowCopy.b.c = 99;
console.log(obj.b.c); // 99 (원본도 변경됨)
❌ 문제점: 중첩 객체(내부 객체)의 변경이 원본에도 영향을 미침.
✏️ 깊은 복사(Deep Copy)
✔️ 대표적인 깊은 복사 방법
방법 | 장점 | 단점 |
JSON.parse(JSON.stringify(obj)) | 간단하고 빠름 | undefined, Symbol, Function 미포함 |
structuredClone(obj) | 최신 브라우저 지원, Map, Set도 복사 가능 | 브라우저 최신 버전에서만 가능 |
lodash.cloneDeep() | 모든 데이터 타입 완벽 지원 | 외부 라이브러리 필요 |
재귀 함수 | 직접 구현 가능, 순환 참조 해결 가능 | 코드가 길어질 수 있음 |
Object.create() + Object.assign() | 프로토타입 유지 가능 | 중첩 객체는 복사 안됨 |
🎯 추천 사용 시나리오
사용 상황 | 추천 방법 |
단순 객체 복사 (JSON 변환 가능) | JSON.parse(JSON.stringify(obj)) |
브라우저 환경에서 최신 기능 활용 | structuredClone(obj) |
Node.js / 브라우저에서 완전한 복사 | lodash.cloneDeep() |
순환 참조 및 특정 데이터 타입 직접 관리 | 재귀 함수 구현 |
프로토타입 유지 필요 | Object.create() + Object.assign() |
💡 깊은 복사(Deep Copy) 방법 및 코드 예제
1️⃣ JSON 방식 (간단하지만 일부 데이터 손실 가능)
const obj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.b.c = 99;
console.log(obj.b.c); // 2 (원본 유지)
✅ 장점: 간단함
❌ 단점: undefined, Symbol, Function 미포함, 순환 참조 불가능
2️⃣ structuredClone(obj) (최신 브라우저 지원)
const obj = { a: 1, b: { c: 2 }, d: new Date(), e: [1, 2, 3] };
const deepCopy = structuredClone(obj);
deepCopy.b.c = 99;
console.log(obj.b.c); // 2 (원본 유지)
✅ 장점: 최신 브라우저에서 안정적 사용 가능
❌ 단점: Node.js에서는 기본적으로 지원 안 됨
3️⃣ lodash.cloneDeep() (완벽한 깊은 복사)
const _ = require('lodash');
const obj = { a: 1, b: { c: 2 }, d: function () { return 42; } };
const deepCopy = _.cloneDeep(obj);
deepCopy.b.c = 99;
console.log(obj.b.c); // 2 (원본 유지)
console.log(typeof deepCopy.d); // "function" (함수도 복사됨)
✅ 장점: 모든 데이터 타입 복사 가능
❌ 단점: lodash 라이브러리 설치 필요 (npm install lodash
4️⃣ 재귀 함수 (순환 참조 해결 가능)
function deepClone(obj, hash = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj; // 원시 값 반환
if (hash.has(obj)) return hash.get(obj); // 순환 참조 방지
const copy = Array.isArray(obj) ? [] : {};
hash.set(obj, copy);
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepClone(obj[key], hash); // 재귀 호출
}
}
return copy;
}
const obj = { a: 1, b: { c: 2 }, d: [1, 2, { e: 3 }] };
const deepCopy = deepClone(obj);
deepCopy.b.c = 99;
console.log(obj.b.c); // 2 (원본 유지)
✅ 장점: 직접 구현 가능, 순환 참조 문제 해결 가능
❌ 단점: 코드가 길어질 수 있음
5️⃣ Object.create() + Object.assign() (프로토타입 유지)
function deepCloneWithPrototype(obj) {
if (obj === null || typeof obj !== 'object') return obj;
const copy = Object.create(Object.getPrototypeOf(obj));
Object.assign(copy, obj);
return copy;
}
const obj = new Date();
const deepCopy = deepCloneWithPrototype(obj);
console.log(deepCopy instanceof Date); // true
✅ 장점: 프로토타입 유지 가능
❌ 단점: 중첩 객체는 완전한 깊은 복사가 안 됨
🚀 결론
방법 | 추천 상황 |
JSON.parse(JSON.stringify(obj)) | 가장 간단한 방법 |
lodash.cloneDeep() | 가장 강력한 방법 |
structuredClone() | 최신 브라우저에서 사용 가능 |
재귀 함수 | 가장 커스텀 가능한 방법 |
꼬리 질문 (Follow-up Questions)
- 얕은 복사가 위험한 상황은?
- 원본 객체가 중첩된 객체(중첩 배열 포함)를 가질 경우, 얕은 복사를 하면 내부 객체의 변경이 원본에도 영향을 줌.
- JSON.stringify() 방식의 깊은 복사 단점?
- undefined, Symbol, Function은 무시됨.
- 순환 참조(Circular Reference)가 있으면 오류 발생.
- 객체 순환 참조가 있는 경우 깊은 복사하는 방법은?
- lodash.cloneDeep()
- structuredClone()
- 재귀적으로 객체 복사하는 커스텀 함수 작성
8. JWT에 대해 설명해주세요. 구체적으로 JWT를 어디서 처리하는지, 어떠한 방식으로 검증하는지, 재발급 방식과 주기는 어떻게 처리하는지, 다른 API 서비스 호출 시 어떻게 잡아서 인증 처리하는지 말씀해주세요.
🛡️ JWT (JSON Web Token)
✅ JWT란?
- 사용자의 인증 정보를 포함하는 토큰 기반 인증 방식.
- JSON 포맷으로 Base64Url로 인코딩되어 전송됨.
- Stateless(상태 비저장) 방식이므로 세션 저장소가 필요 없음.
- 구성 요소: Header + Payload + Signature
- Header: 토큰 유형과 해싱 알고리즘 (HS256, RS256 등)
- Payload: 사용자 정보 (sub, role, exp 등)
- Signature: 비밀키를 사용해 생성된 서명 (위변조 방지)
✅ JWT 처리 방식
📌 JWT 발급 과정
const jwt = require('jsonwebtoken');
const payload = { userId: 123, role: 'admin' };
const secretKey = 'your-secret-key';
// JWT 생성 (15분 유효기간)
const token = jwt.sign(payload, secretKey, { expiresIn: '15m' });
console.log(token);
✔️ 서버에서 로그인 성공 시 비밀키(Secret Key) 를 사용해 Access Token을 생성하여 클라이언트에 전달.
✔️ 발급된 JWT 를 클라이언트는 localStorage, sessionStorage, HttpOnly Cookie 등에 저장 가능.
📌 JWT 검증 과정
try {
const decoded = jwt.verify(token, secretKey);
console.log(decoded); // { userId: 123, role: 'admin', iat: ..., exp: ... }
} catch (error) {
console.log('Invalid token');
}
✔️ 서버는 클라이언트가 보낸 JWT를 비밀키로 검증하여 유효한지 확인.
Authorization: Bearer <JWT>형태로 헤더에 포함되어 요청
✔️ 만료된 경우 Refresh Token을 통해 재발급.
🔄 JWT 재발급 방식과 주기
토큰 종류 | 유효 기간 | 설명 |
Access Token | 15~30분 | API 호출 시 사용, 짧은 유효기간 |
Refresh Token | 7~30일 | Access Token이 만료되면 새로운 토큰 발급 |
// Refresh Token을 사용해 Access Token 재발급
const newAccessToken = jwt.sign({ userId: 123 }, secretKey, { expiresIn: '15m' });
✔️ Access Token이 만료되면 Refresh Token을 검증하여 새로운 Access Token을 발급.
✔️ Refresh Token도 만료되면 재로그인 필요.
🔗 다른 API 서비스 호출 시 인증 처리
✔️ 마이크로서비스 환경에서는 API Gateway를 통해 JWT를 검증
✔️ 각 서비스는 JWT 내 정보를 활용하여 요청을 처리
✔️ 서명 검증을 위해 공개 키(Public Key)를 사용하여 검증 가능 (RS256)
🚀 결론
- 간단한 깊은 복사 → JSON.parse(JSON.stringify(obj))
- 완벽한 깊은 복사 → lodash.cloneDeep()
- 최신 브라우저 지원 깊은 복사 → structuredClone()
- 커스텀 깊은 복사 → 직접 재귀 함수 구현
- JWT는 세션보다 확장성이 뛰어난 인증 방식
- Access Token은 짧게, Refresh Token은 길게 설정하여 보안 강화
꼬리 질문 (Follow-up Questions)
- JWT를 세션 방식과 비교하면 어떤 장단점이 있는가?
- 장점: 상태를 서버에 저장할 필요 없음(Stateless), 확장성이 좋음
- 단점: 크기가 커서 네트워크 부하가 있을 수 있음, 토큰 탈취 시 보안 위험
- JWT가 탈취되었을 때 어떻게 대처할 수 있는가?
- Refresh Token을 짧게 설정하고, 중요 요청에는 추가 보안 체크
- 탈취된 토큰을 차단하는 블랙리스트 관리
- JWT의 서명을 검증하지 않으면 어떤 문제가 발생하는가?
- 악의적인 사용자가 조작된 토큰을 서버로 보내면 검증 없이 무단 접근 가능
- 따라서 서명 검증이 필수
- JWT를 안전하게 저장하는 방법은?
- HttpOnly 쿠키 사용 (XSS 방지)
- localStorage에 저장하면 XSS 공격에 취약
※ 참고
7. 얕은 복사(Shallow Copy) vs 깊은 복사(Deep Copy)
Shallow copy :
- https://developer.mozilla.org/en-US/docs/Glossary/Shallow_copy
Deep copy :
- https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy
8. JWT : https://jwt.io/
-
'게임서버-스파르타코딩NodeJs_7기 > 모의면접' 카테고리의 다른 글
면접카타 -알고리즘 (0) | 2025.02.17 |
---|---|
면접카타 9,10 - Node.js, 이벤트 루프 (0) | 2025.02.14 |
면접카타 5,6 - TIL 250212 (0) | 2025.02.12 |
면접카타 3,4번 - TIL250211 (0) | 2025.02.11 |
면접카타 1,2번 - TIL 250210 (0) | 2025.02.10 |