- [JavaScript] 객체 유효성 검사로 Proxy 이해하기2025년 04월 23일 09시 54분 46초에 업로드 된 글입니다.작성자: DandyNow728x90반응형
객체 유효성 검사로 Proxy 이해하기
JavaScript로 개발할 때 객체 데이터의 무결성을 지키는 것은 중요하다. 예를 들어 사용자 정보 객체에서 나이는 양수여야 하고, 이름은 빈 문자열이 아니어야 하는 규칙이 있을 수 있다. 이런 유효성 검사 로직을 깔끔하게 구현하는 방법이 필요하다.
이 글에서는 JavaScript의
Proxy객체를 사용하여 객체 유효성 검사를 구현하는 방법을 소개하고자 한다.Proxy를 이용하면 객체 접근을 중간에서 제어하여 유효성 검사 로직을 더 체계적이고 우아하게 작성할 수 있다.1. JavaScript Proxy란 무엇인가?
Proxy객체는 다른 객체(대상 target)를 감싸는 래퍼(wrapper)이다. 이 래퍼를 통해 대상 객체에 대한 기본적인 동작(속성 접근, 할당, 함수 호출 등)을 가로채고(intercept) 개발자가 정의한 방식으로 동작을 재정의할 수 있다. 즉, 객체와 상호작용하는 모든 과정을 중간에서 대리인(proxy)이 먼저 확인하고 처리하도록 만드는 것이다.2. Proxy와 유효성 검사:
set핸들러 활용객체의 속성에 특정 값을 할당하는 시점에 그 값이 유효한지 검사하고 싶을 때,
Proxy의set핸들러(트랩)가 매우 유용하다.set핸들러는 객체의 속성에 값을 할당하려고 시도할 때 자동으로 호출되는 함수이다.set핸들러는 다음 네 개의 인자를 받는다.target: 원본 대상 객체이다.property: 값을 할당하려는 속성의 이름이다.value: 할당하려는 새로운 값이다.receiver: 최초 작업이 수행된 객체 (대개 프록시 객체 자신)이다.
set핸들러는 반드시 불리언 값을 반환해야 한다.true를 반환하면 할당이 성공적으로 처리되었음을 나타낸다.false를 반환하면 할당이 실패했음을 나타내며, 엄격 모드(strict mode)에서는TypeError가 발생한다. 또는, 유효성 검사에 실패했을 때 직접 에러를 발생시킬 수도 있다.3. 예제: 사용자 정보 유효성 검사 (switch 사용)
이제 사용자 정보 객체(
name,age)에 대해Proxy를 이용한 유효성 검사를 구현한다.name은 비어 있지 않은 문자열이어야 하고,age는 0 이상 150 미만의 정수여야 한다는 규칙을switch문을 사용하여 적용해 본다.// 1. 유효성 검사 핸들러 정의이다. const userValidator = { set(target, property, value) { // console.log는 설명을 위해 유지한다. 실제 코드에서는 필요에 따라 제거하거나 로깅 라이브러리를 사용한다. console.log(`[Proxy] 속성 '${property}'에 값 '${value}' 할당 시도.`); // 속성 이름(property)에 따라 유효성 검사를 분기한다. switch (property) { case 'name': if (typeof value !== 'string' || value.trim() === '') { // 유효하지 않으면 에러를 발생시킨다. throw new Error('유효성 오류: 이름(name)은 비어 있지 않은 문자열이어야 한다.'); } console.log(`[Proxy] 이름(name) 유효성 검사 통과.`); break; // switch 문을 탈출한다. case 'age': if (typeof value !== 'number' || !Number.isInteger(value) || value < 0 || value >= 150) { // 유효하지 않으면 에러를 발생시킨다. throw new Error('유효성 오류: 나이(age)는 0 이상 150 미만의 정수여야 한다.'); } console.log(`[Proxy] 나이(age) 유효성 검사 통과.`); break; // switch 문을 탈출한다. default: // 'name', 'age' 외 다른 속성은 별도 검사 없이 통과시킨다. console.log(`[Proxy] '${property}' 속성은 별도 유효성 검사 없다.`); break; } // 모든 유효성 검사를 통과했거나 해당 없으면 실제 값 할당을 한다. // Reflect.set을 사용하는 것이 권장된다. console.log(`[Proxy] '${property}' 속성에 값 할당 완료.`); return Reflect.set(target, property, value); // 성공 시 true를 반환한다. } }; // 2. 원본 데이터 객체이다. const user = { name: '김개발', age: 28 }; // 3. Proxy 객체 생성이다. const validatedUser = new Proxy(user, userValidator); // 4. Proxy를 통한 사용 테스트이다. console.log("--- 유효한 할당 테스트 ---"); try { validatedUser.name = '이코드'; // 성공이다. validatedUser.age = 35; // 성공이다. validatedUser.email = 'lee.code@example.com'; // 'email'은 검사 규칙 없으므로 성공이다. console.log("현재 validatedUser:", validatedUser); console.log("현재 원본 user:", user); // 원본 객체도 변경된다. } catch (e) { console.error(e.message); } console.log("\n--- 유효하지 않은 할당 테스트 ---"); try { console.log("\n테스트: 빈 이름 할당 시도."); validatedUser.name = ' '; // 공백 문자열 -> 에러 발생이다. } catch (e) { console.error(e.message); } try { console.log("\n테스트: 음수 나이 할당 시도."); validatedUser.age = -10; // 음수 -> 에러 발생이다. } catch (e) { console.error(e.message); } try { console.log("\n테스트: 너무 큰 나이 할당 시도."); validatedUser.age = 150; // 150 이상 -> 에러 발생이다. } catch (e) { console.error(e.message); } console.log("\n--- 에러 발생 후 객체 상태 확인 ---"); // 에러가 발생한 할당은 적용되지 않는다. console.log("최종 validatedUser:", validatedUser);4. 코드 해설
userValidator객체: 이것은Proxy의 핸들러 객체이다. 핵심 로직은set메서드 안에 있다.set메서드: 속성 할당 시도가 있을 때마다 호출된다.switch (property): 할당하려는 속성 이름(property)에 따라 검사 로직을 분기한다.case 'name',case 'age': 각 속성에 맞는 유효성 검사를 수행한다. 조건에 맞지 않으면throw new Error()를 통해 즉시 에러를 발생시키고 실행을 중단한다.default:name이나age가 아닌 다른 속성이 들어오면 별다른 검사 없이 통과시킨다.Reflect.set(target, property, value): 모든 검사를 통과하면Reflect.set을 사용하여 원본 객체(target)에 안전하게 값을 할당한다. 이 메서드는 할당 성공 여부를 불리언 값으로 반환하며,Proxy의set핸들러에서 이 반환 값을 그대로 사용하는 것이 좋다.
user객체: 유효성 검사의 대상이 되는 평범한 JavaScript 객체이다.validatedUser:new Proxy(user, userValidator)를 통해 생성된 프록시 객체이다. 앞으로validatedUser를 통해user객체에 접근하면userValidator의 규칙이 적용된다.- 테스트 코드:
validatedUser에 유효한 값과 유효하지 않은 값을 할당해보며 프록시가 잘 작동하는지, 에러 처리가 올바른지 확인한다. 유효하지 않은 값 할당 시try...catch를 사용하여 에러 메시지를 출력한다.
5. 결론
일반적인 데이터 구조 및 타입 검증에는 스키마 라이브러리(Zod 등)가 더 보편적으로 사용된다.
Proxy는 런타임 중 객체와의 상호작용 시점에 유효성 규칙을 동적으로 적용해야 하는 특정 요구사항이 있을 때 강력한 도구가 된다.Proxy를 사용하면 객체의 속성 할당과 같은 기본적인 동작에 개입하여 유효성 검사 로직을 객체 자체의 코드와 분리하여 더 깔끔하고 중앙 집중적으로 관리할 수 있다. 이는 코드의 유지보수성을 높이고 데이터의 무결성을 보장하는 데 큰 도움이 된다.Proxy에는set외에도get(속성 읽기),has(in 연산자),deleteProperty(속성 삭제) 등 다양한 동작을 가로챌 수 있는 핸들러들이 있다. 필요에 따라 다른 핸들러들도 활용하여 더욱 강력한 객체 제어를 구현해 보기 바란다.728x90반응형'언어·프레임워크 > JavaScript' 카테고리의 다른 글
[JavaScript] 프로토타입 이해하기 (1) 2025.06.10 [JavaScript] 커링 함수 이해하기 (0) 2025.06.10 [JavaScript] 리플렉트(Reflect) 완벽 정복: JavaScript 메타 프로그래밍의 숨겨진 능력 (1) 2025.04.21 [JavaScript] JavaScript 배열 메서드, 무엇을 바꾸고 무엇을 반환할까? (0) 2025.04.18 [JavaScript] 안정 정렬 vs 불안정 정렬: JavaScript `sort()` 메서드의 숨겨진 진실 (0) 2025.04.18 다음글이 없습니다.이전글이 없습니다.댓글