JavaScript 객체 키 소문자 변환

Beginner

This tutorial is from open-source community. Access the source code

소개

이 랩에서는 JavaScript 를 사용하여 객체의 모든 키를 소문자로 변환하는 방법을 배웁니다. 이 기술은 객체 키의 대소문자가 일관되지 않을 수 있는 다양한 소스에서 데이터를 사용할 때 특히 유용합니다.

이 작업을 수행하기 위해 다음과 같은 여러 JavaScript 메서드를 활용합니다.

  • Object.keys(): 객체에서 모든 키를 가져옵니다.
  • Array.prototype.reduce(): 데이터를 새로운 객체로 변환합니다.
  • String.prototype.toLowerCase(): 문자열을 소문자로 변환합니다.

이 랩을 마치면, 값을 유지하면서 모든 객체의 키를 소문자로 변환할 수 있는 재사용 가능한 함수를 만들 수 있습니다.

JavaScript 객체 이해하기

객체 키를 소문자로 변환하기 전에, JavaScript 객체가 무엇인지, 그리고 어떻게 작업할 수 있는지 이해해 보겠습니다.

JavaScript 에서 객체는 키 - 값 쌍의 모음입니다. 키는 문자열 (또는 Symbol) 이며, 값은 다른 객체를 포함하여 모든 데이터 유형이 될 수 있습니다.

Node.js 대화형 셸을 열어 시작해 보겠습니다.

  1. WebIDE 에서 터미널을 엽니다.
  2. node를 입력하고 Enter 키를 누릅니다.

이제 JavaScript 코드를 직접 입력할 수 있는 Node.js 프롬프트 (>) 가 표시됩니다.

대소문자가 혼합된 키를 가진 간단한 객체를 만들어 보겠습니다.

const user = {
  Name: "John",
  AGE: 30,
  Email: "john@example.com"
};

이 코드를 Node.js 프롬프트에 입력하고 Enter 키를 누릅니다. 객체를 보려면 user를 입력하고 Enter 키를 누릅니다.

user;

다음과 같은 출력을 볼 수 있습니다.

{ Name: 'John', AGE: 30, Email: 'john@example.com' }

보시다시피, 이 객체는 서로 다른 대소문자 스타일의 키를 가지고 있습니다. 다음 단계에서는 이러한 키에 액세스하고 소문자로 변환하는 방법을 배웁니다.

객체 키에 접근하기

객체 키를 변환하기 전에, 키에 접근하는 방법을 이해해야 합니다. JavaScript 는 객체의 모든 키를 포함하는 배열을 반환하는 Object.keys() 메서드를 제공합니다.

Node.js 대화형 셸에서 다음을 시도해 보세요.

Object.keys(user);

다음과 같은 출력을 볼 수 있습니다.

[ 'Name', 'AGE', 'Email' ]

이제 toLowerCase() 메서드를 사용하여 각 키를 소문자로 변환해 보겠습니다. map() 메서드를 사용하여 각 키를 변환할 수 있습니다.

Object.keys(user).map((key) => key.toLowerCase());

출력은 다음과 같아야 합니다.

[ 'name', 'age', 'email' ]

훌륭합니다! 이제 모든 키가 소문자로 변환된 배열이 있습니다. 그러나 이러한 소문자 키와 원래 값을 가진 새로운 객체를 만들어야 합니다. 이를 위해 다음 단계에서 reduce() 메서드를 사용합니다.

계속 진행하기 전에 reduce() 메서드를 이해해 보겠습니다. 이 메서드는 배열의 각 요소에 대해 리듀서 함수를 실행하여 단일 출력 값을 생성합니다.

다음은 reduce()의 간단한 예입니다.

const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
}, 0);

sum;

출력은 배열의 모든 숫자의 합인 10이 됩니다. reduce() 메서드의 0은 누산기 (accumulator) 의 초기 값입니다.

소문자 변환 함수 만들기

이제 객체 키에 접근하고 reduce() 메서드를 사용하는 방법을 이해했으므로, 객체의 모든 키를 소문자로 변환하는 함수를 만들어 보겠습니다.

Node.js 대화형 셸에서 다음 함수를 정의합니다.

const lowerizeKeys = (obj) => {
  return Object.keys(obj).reduce((acc, key) => {
    acc[key.toLowerCase()] = obj[key];
    return acc;
  }, {});
};

이 함수가 수행하는 작업을 자세히 살펴보겠습니다.

  1. Object.keys(obj)는 입력 객체의 모든 키를 가져옵니다.
  2. .reduce()는 이러한 키를 새로운 객체로 변환합니다.
  3. 각 키에 대해, 누산기 객체 (acc) 에 다음을 사용하여 새로운 항목을 만듭니다.
    • key.toLowerCase()를 사용하여 소문자로 변환된 키
    • 입력 객체 (obj[key]) 의 원래 값
  4. 누산기의 초기 값으로 빈 객체 {}로 시작합니다.
  5. 마지막으로, 소문자 키가 있는 새로운 객체인 누산기를 반환합니다.

이제 앞에서 만든 user 객체로 함수를 테스트해 보겠습니다.

const lowercaseUser = lowerizeKeys(user);
lowercaseUser;

다음과 같은 출력을 볼 수 있습니다.

{ name: 'John', age: 30, email: 'john@example.com' }

완벽합니다! 이제 모든 키가 소문자로 되어 있습니다.

함수가 제대로 작동하는지 확인하기 위해 다른 예제를 시도해 보겠습니다.

const product = {
  ProductID: 101,
  ProductName: "Laptop",
  PRICE: 999.99
};

lowerizeKeys(product);

출력은 다음과 같아야 합니다.

{ productid: 101, productname: 'Laptop', price: 999.99 }

함수는 다양한 키 대소문자 스타일을 가진 다른 객체에 대해 올바르게 작동합니다.

엣지 케이스 처리

우리의 함수는 간단한 객체에 대해서는 잘 작동하지만, 더 복잡한 경우에는 어떨까요? 몇 가지 엣지 케이스를 살펴보고 함수가 어떻게 처리하는지 살펴보겠습니다.

빈 객체

먼저, 빈 객체로 테스트해 보겠습니다.

lowerizeKeys({});

출력은 빈 객체여야 합니다.

{}

중첩된 객체가 있는 객체

객체에 중첩된 객체가 포함되어 있다면 어떨까요? 시도해 보겠습니다.

const nestedObject = {
  User: {
    Name: "John",
    Contact: {
      EMAIL: "john@example.com",
      PHONE: "123-456-7890"
    }
  }
};

lowerizeKeys(nestedObject);

출력은 다음과 같습니다.

{ user: { Name: 'John', Contact: { EMAIL: 'john@example.com', PHONE: '123-456-7890' } } }

최상위 키 User만 소문자로 변환된 것을 확인하세요. 중첩된 객체 내부의 키는 변경되지 않습니다.

중첩된 객체를 처리하려면, 모든 객체를 재귀적으로 처리하도록 함수를 수정해야 합니다. 향상된 버전을 만들어 보겠습니다.

const deepLowerizeKeys = (obj) => {
  return Object.keys(obj).reduce((acc, key) => {
    const value = obj[key];
    // Check if the value is an object and not null
    const newValue =
      value && typeof value === "object" && !Array.isArray(value)
        ? deepLowerizeKeys(value)
        : value;

    acc[key.toLowerCase()] = newValue;
    return acc;
  }, {});
};

이 향상된 함수는 다음을 수행합니다.

  1. 각 값이 객체인지 확인합니다 (배열 또는 null 이 아닌지 확인).
  2. 객체인 경우, 해당 중첩된 객체에 대해 자체적으로 재귀적으로 호출합니다.
  3. 그렇지 않은 경우, 원래 값을 사용합니다.

중첩된 객체로 테스트해 보겠습니다.

const deepLowerizedObject = deepLowerizeKeys(nestedObject);
deepLowerizedObject;

이제 중첩된 객체에서도 모든 키가 소문자로 변환된 것을 볼 수 있습니다.

{ user: { name: 'John', contact: { email: 'john@example.com', phone: '123-456-7890' } } }

잘하셨습니다! 중첩된 객체를 처리할 수 있는 고급 함수를 만들었습니다.

재사용 가능한 모듈 만들기

이제 작동하는 함수가 있으므로, 다른 프로젝트로 가져올 수 있는 재사용 가능한 JavaScript 모듈 파일을 만들어 보겠습니다.

먼저, Ctrl+C 를 두 번 누르거나 .exit를 입력하고 Enter 키를 눌러 Node.js 대화형 셸을 종료합니다.

이제 프로젝트 디렉토리에 object-utils.js라는 새 파일을 만듭니다.

  1. WebIDE 에서 왼쪽의 파일 탐색기 패널로 이동합니다.
  2. 프로젝트 디렉토리에서 마우스 오른쪽 버튼을 클릭하고 "New File"을 선택합니다.
  3. 파일 이름을 object-utils.js로 지정합니다.
  4. 파일에 다음 코드를 추가합니다.
/**
 * Converts all keys of an object to lowercase
 * @param {Object} obj - The input object
 * @returns {Object} A new object with all keys in lowercase
 */
const lowerizeKeys = (obj) => {
  return Object.keys(obj).reduce((acc, key) => {
    acc[key.toLowerCase()] = obj[key];
    return acc;
  }, {});
};

/**
 * Recursively converts all keys of an object and its nested objects to lowercase
 * @param {Object} obj - The input object
 * @returns {Object} A new object with all keys in lowercase (including nested objects)
 */
const deepLowerizeKeys = (obj) => {
  return Object.keys(obj).reduce((acc, key) => {
    const value = obj[key];
    // Check if the value is an object and not null
    const newValue =
      value && typeof value === "object" && !Array.isArray(value)
        ? deepLowerizeKeys(value)
        : value;

    acc[key.toLowerCase()] = newValue;
    return acc;
  }, {});
};

// Export the functions
module.exports = {
  lowerizeKeys,
  deepLowerizeKeys
};

이제 모듈이 제대로 작동하는지 확인하기 위해 테스트 파일을 만들어 보겠습니다. test.js라는 새 파일을 만듭니다.

  1. WebIDE 에서 왼쪽의 파일 탐색기 패널로 이동합니다.
  2. 프로젝트 디렉토리에서 마우스 오른쪽 버튼을 클릭하고 "New File"을 선택합니다.
  3. 파일 이름을 test.js로 지정합니다.
  4. 파일에 다음 코드를 추가합니다.
// Import the functions from our module
const { lowerizeKeys, deepLowerizeKeys } = require("./object-utils");

// Test with a simple object
const user = {
  Name: "John",
  AGE: 30,
  Email: "john@example.com"
};

console.log("Original object:");
console.log(user);

console.log("\nObject with lowercase keys:");
console.log(lowerizeKeys(user));

// Test with a nested object
const nestedObject = {
  User: {
    Name: "John",
    Contact: {
      EMAIL: "john@example.com",
      PHONE: "123-456-7890"
    }
  }
};

console.log("\nNested object:");
console.log(nestedObject);

console.log("\nNested object with lowercase keys (shallow):");
console.log(lowerizeKeys(nestedObject));

console.log("\nNested object with lowercase keys (deep):");
console.log(deepLowerizeKeys(nestedObject));

이제 테스트 파일을 실행해 보겠습니다.

node test.js

다음과 유사한 출력을 볼 수 있습니다.

Original object:
{ Name: 'John', AGE: 30, Email: 'john@example.com' }

Object with lowercase keys:
{ name: 'John', age: 30, email: 'john@example.com' }

Nested object:
{
  User: {
    Name: 'John',
    Contact: { EMAIL: 'john@example.com', PHONE: '123-456-7890' }
  }
}

Nested object with lowercase keys (shallow):
{
  user: {
    Name: 'John',
    Contact: { EMAIL: 'john@example.com', PHONE: '123-456-7890' }
  }
}

Nested object with lowercase keys (deep):
{
  user: {
    name: 'John',
    contact: { email: 'john@example.com', phone: '123-456-7890' }
  }
}

축하합니다! 객체 키를 소문자로 변환하는 함수가 있는 재사용 가능한 JavaScript 모듈을 성공적으로 만들었습니다. 이 모듈은 이제 JavaScript 프로젝트에 가져올 수 있습니다.

요약

이 랩에서는 JavaScript 에서 객체 키를 소문자로 변환하는 방법을 배웠습니다. 다음을 수행했습니다.

  1. JavaScript 객체를 탐색하고 키에 접근하는 방법을 배웠습니다.
  2. Object.keys() 메서드를 사용하여 객체에서 모든 키를 가져왔습니다.
  3. reduce() 메서드를 활용하여 객체를 변환했습니다.
  4. 객체의 모든 키를 소문자로 변환하는 함수를 만들었습니다.
  5. 중첩된 객체를 재귀적으로 처리하도록 함수를 개선했습니다.
  6. 두 함수를 모두 포함하는 재사용 가능한 JavaScript 모듈을 만들었습니다.

이러한 기술은 객체 키의 대소문자가 일관되지 않을 수 있는 다양한 소스의 데이터를 사용할 때 유용합니다. 여러분이 만든 함수는 데이터를 정규화하고 더 쉽게 작업할 수 있도록 도와줍니다.

다음과 같은 더 많은 함수를 추가하여 이러한 유틸리티를 더욱 확장할 수 있습니다.

  • 객체 키를 대문자로 변환
  • 키를 camelCase 또는 snake_case 로 변환
  • 키 또는 값 기준에 따라 객체 필터링
  • 객체의 동일성을 깊이 비교

JavaScript 프로그래밍에 능숙해지려면 객체와 객체 조작을 계속 연습하십시오.