JavaScript

구조 분해 할당 Destructuring assignment으로 가독성 높이기

남희정 2023. 8. 31. 02:37

이전에 배열을 공부하면서 구조 분해 할당을 배웠는데 실제로 적용해 보는 거랑은 또 다른 것 같다. 코드 구조를 보다가 가독성을 높일 수 있게 바꿀 수 있는 방법으로 쓸 수 있을 것 같아 리팩토링 해보았다.

 


 

먼저 구조 분해 할당에 대해 알아보고, 어떻게 적용했는지 말하겠다!

 

구조 분해 할당 Destructuring assignment

구조 분해 할당 구문은 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript 표현식이다. 

이를 통해 데이터 뭉치(그룹화)를 쉽게 만들 수 있다!

 

변수에 나머지 할당하기

구조 분해 할당의 구문은 할당문의 좌변 => 원래 변수로 어떤 값을 분해하여 할당할지 정의한다.

 

const people = ["😎", "😡", "🥸", "🥶", "😳"];
const [first, second, ...others] = people;

console.log(first);	// 😎
console.log(second);	// 😡
console.log(others);	// [ '🥸', '🥶', '😳' ]

 

구조 분해 할당은 Perl이나 Python 등 다른 언어가 갖고 있는 기능!

 

기본값

분해한 값이 undefined일 때를 대비하여 기본값을 설정해둘수도 있다.

const point = [1, 2];
const [x, y, z = 0] = point;

console.log(x);	// 1
console.log(y);	// 2
console.log(z);	// 0

 

함수가 반환한 배열 분석

함수는 이전부터 배열을 반환할 수 있었다. 구조 분해를 사용하면 반환된 배열에 대한 작업을 더 간결하게 수행할 수 있다.

function createEmoji() {
  return ["thirsty", "🥵"];
}
const [title, emoji] = createEmoji();

console.log(title);	// thirsty
console.log(emoji);	// 🥵

 

객체 구조 분해

const nami = { name: "Nami", age: 100, job: "s/w engineer" };
function display({ name, age, job }) {
  console.log("이름", name);	// 이름 Nami
  console.log("나이", age);	// 나이 100
  console.log("직업", job);	// 직업 s/w engineer
}
display(nami);

객체 내부 구조에 새로운 값을 추가하는 방법도 있다.

const { name, age, job: occupation, pet = "강아지" } = nami;
console.log(name);	// Nami
console.log(age);	// 100
console.log(occupation);	// s/w engineer
console.log(pet);	// 강아지

객체 중첩 구조에서 속성의 값을 바꾸려면..?!

const property = {
  nickName: "dot pattern shoes",
  styles: {
    size: 225,
    color: "red",
  },
};

function changeColor({ styles: { color } }, colorChange) {
  color = colorChange;
  console.log(color);	// skyblue
}

changeColor(property, "skyblue");

 

Refactoring 해보기

리팩토링 해볼 코드는 날씨 API를 적용하고 경도 위도를 기반으로 해당 위치와 실시간 날씨 이미지와 온도를 알려주는 영역이다.

 

우선 이건 강의를 베이스로 작성한 코드였는데, 그 코드에 날씨 코드를 인식하여 img를 불러오는 기능을 추가했던 터라 더욱 지저분해 보인다.

 

Before

const API_KEY = "****";
function onGeoOK(position) {
  const lat = position.coords.latitude;
  const lon = position.coords.longitude;
  const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`;
  fetch(url)
    .then((response) => response.json())
    .then((data) => {
      const weather = document.querySelector("#weather");
      const weatherImg = document.createElement("img");
      weatherImg.src = `../img/icons/${data.weather[0].icon}.png`;
      weather.prepend(weatherImg);
      const weatherTxt = weatherImg.nextElementSibling;
      weatherTxt.innerText = `${data.weather[0].description} · ${Math.round(
        data.main.temp
      )}°C `;
      const city = weather.querySelector("span:last-child");
      city.innerText = `· 📍 ${data.name}`;
    });
}
function onGeoError() {
  alert("Can't find you");
}

After

const API_KEY = "****";

const weather = document.querySelector("#weather");

function displayWeather(data) {
  const { name } = data;
  const { description, icon } = data.weather[0];
  const { temp } = data.main;

  const weatherImg = document.createElement("img");
  weatherImg.src = `../img/icons/${icon}.png`;

  const weatherTxt = document.createElement("span");
  weatherTxt.innerText = `${description} · ${Math.round(temp)}°C `;

  const city = document.createElement("span");
  city.innerText = `· 📍 ${name}`;

  weather.appendChild(weatherImg);
  weather.appendChild(weatherTxt);
  weather.appendChild(city);
}

function onGeoOK(position) {
  const { latitude: lat, longitude: lon } = position.coords;
  const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`;

  fetch(url)
    .then((response) => response.json())
    .then(displayWeather)
    .catch(onGeoError);
}

function onGeoError() {
  alert("Sorry, we couldn't find your location.");
}

navigator.geolocation.getCurrentPosition(onGeoOK, onGeoError);

다른 부분도 변경해서 어떻게 변경되었는지 확인하기 어려우니 똑 떼어서 비교해 보겠다!

// Before
const lat = position.coords.latitude;
const lon = position.coords.longitude;

// After
const { latitude: lat, longitude: lon } = position.coords;

반복되는 부분을 한 줄로 합칠 수 있어서 훨씬 가독성이 좋아졌다.

// Before

const weather = document.querySelector("#weather");
const weatherImg = document.createElement("img");
weatherImg.src = `../img/icons/${data.weather[0].icon}.png`;
weather.prepend(weatherImg);
const weatherTxt = weatherImg.nextElementSibling;
weatherTxt.innerText = `${data.weather[0].description} · ${Math.round(data.main.temp)}°C `;
const city = weather.querySelector("span:last-child");
city.innerText = `· 📍 ${data.name}`;
    
// After

const { name } = data;
const { description, icon } = data.weather[0];
const { temp } = data.main;

const weatherImg = document.createElement("img");
weatherImg.src = `../img/icons/${icon}.png`;

const weatherTxt = document.createElement("span");
weatherTxt.innerText = `${description} · ${Math.round(temp)}°C `;

const city = document.createElement("span");
city.innerText = `· 📍 ${name}`;

 

구조도 바꿔서 다른 것도 많이 바뀌었지만 구조 분해 할당에 초점을 맞추어보겠다.

경로 설정을 보기 힘들었던 반면에 상단에 변수에 반복되는 속성값을 할당해 주어서 훨씬 보기 편하게 리팩토링할 수 있었다.

 

복습 겸 정리했는데 코드는 역시 직접 적용해 보아야 연결이 된다. 더욱 연습하겠다.

 

 


[구조 분해 할당]

[드림 코딩 아카데미 - 자바스크립트 마스터리 (ES6+)]

ChatGPT 🤖