SW개발/Javascript

[Javascript]Javascript 멋지게 쓰기, 프로처럼 쓰기

저번 포스팅에 이어서 Javascirpt를 멋지게, 그리고 프로답게 쓰는 법에 대해서 알아보도록 하겠습니다. 이번 포스팅도 대부분 가독성에 중점을 두었습니다.

 

1. Nullish Coalescing Operator ( ?? ) - Null 병합 연산자

// ❌ bad 💥
function printName(text) {
  let message = text;
  if (text === null || text === undefined) {
    message = "No Message";
  }
  console.log(message);
}

전달받은 텍스트가 null 이거나 undefined인 경우에 No Message를, 텍스트가 있는 경우라면 message를 출력하는 함수입니다.

위처럼 작성하게 되면 간단한 역할을 하는 함수에도 불구하고 코드가 매우 길어집니다.

// ⭕️ better 🌈
function printMessage(text) {
  const message = text ?? 'No Message';
  console.log(message);
}

이럴 경우에 Nullish Coalescing Operator?? 를 사용하게 되면 보다 직관적이고 깔끔하게 작성할 수 있습니다. null 이거나 undefined인 경우에만 ?? 오른쪽 코드가 실행됩니다.

 

1-1. Default Parameter 와의 차이점

// vs DefaultParameter
function printMessage(text = 'No Message') {
  console.log(text);
}
// text가 undefined인 경우에만 No Message 출력

여기서 Default Paramter를 사용하면 똑같이 구현할 수 있다는 생각이 들 수 있습니다. Default Paramter는 undefined인 경우에만 해당되고 null 인 경우는 해당되지 않습니다.

 

1-2. Logical Operator ( || ) 와의 차이점 

// vs LogicalOperator
function printMessage(text) {
  const message = text || 'No Message';
  console.log(message);
}
// null, undefined 이외에 false면 전부 No Message

Logical Operatorfalse에 해당하는(Nan, '', null, undefined 등)값이 오게되면 || 오른쪽의 코드가 실행되는 차이점을 가지고 있습니다.

 

2. Object Destructuring - 구조 분해 할당

// ❌ bad 💥
const blog = {
  name: 'leffept',
  link: 'leffept.tistory.com',
};
fucntion displayBlog(blog) {
  displayName(blog.name);
  displayLink(blog.link);
}

위 코드의 경우에는 blog. 코드가 반복되어 사용되고 있습니다. 반복되는 횟수가 늘어나면 상당히 지저분한 코드가 됩니다.

// ⭕️ better 🌈
function displayBlog(blog){
  const { name, link } = blog;
  displayName(name);
  displayLink(link);
}

Object Destructuring을 활용할 경우 위의 코드처럼 보기 좋게 작성할 수 있습니다. blog object 안의 name, link 값을 변수로서 구조 분해 할당 해주는 방식입니다.

 

3. Spread Syntax ( ...  ) -  전개 구문

// ❌ bad 💥
const blog = { name: 'leffe', link: 'leffept.tistory.com' };
const post = { title: 'javascirpt', view: 777 };

const newObj = {
  name: blog.name,
  link: blog.link,
  title: post.title,
  view: post.view,
};

두개의 objcet가 있을 때 합해서 새로운 object를 만들어야 하는 경우에 Spread Syntax를 활용하여 간단하게 할 수 있습니다.

// ⭕️ better 🌈
const newObj = { ...blog, ...post };
const newObj2 = { ...blog, ...post, title: 'pretty Javascript' }; // title update

수동적으로 값을 할당해 줄 필요없이 보기 좋게 변경되었습니다. 또한 뒤에 key, value를 적어주면 해당 key에 대한 value를 update할 수도 있습니다. 이 외에도 Array와 같은 다양한 곳에서 사용됩니다.

 

4. Optional Chaining ( ? )

// ❌ bad 💥
const blog = { 
  name: 'leffe', 
  link: 'leffept.tistory.com', 
  post: {
   title: 'Javascript'
  },
};
const blog2 = { 
  name: 'leffe2', 
  link: 'blog2.tistory.com', 
};

function displayBlogPost(blog) {
  if (blog.post && blog.post.title) {
    console.log(blog.post.title);
  }
}

 

하나는 새로 개설한 blog라 post가 존재하지 않고, 다른 blog는 존재한다고 하였을 때 blog의 title을 보여주는 코드입니다. 마찬가지로 코드가 길어진다면 지저분해 보일 가능성이 높습니다.

// ⭕️ better 🌈
function displayBlogPost(blog) {
  if (blog.post?.title) {
    console.log(blog.post.title);
  }
}

? 라는 Optional Chaining을 사용하면 post 라는 object가 있는 지를 체크한 후 있다면 title을, 없다면 바로 false를 반환합니다.

// ⭕️ better 🌈
function displayBlogPost(blog) {
  const title = blog.post?.title ?? 'No Post Yet;
  console.log(title);
}

또한, 앞서 소개한 Nullish Coalescing Operator을 사용하여 더 보기좋게 만들 수 있습니다.

 

5. Template Literals - 템플릿 리터럴

// ❌ bad 💥
const blog = { name: 'leffe', link: 'leffept.tistory.com' };
console.log('Hello, This is ' + blog.name + ', link is : ' + blog.link);

문자열을 이어서 출력할 때 일반적으로 + 연산자를 사용하여 할 수 있습니다. 하지만, 작성하기에 불편합니다.

// ⭕️ better 🌈
const blog = { name: 'leffe', link: 'leffept.tistory.com' };
const { name, link } = blog;
console.log(`Hello, This is ${blog.name}, link is : ${blog.link}`);

Template Literals를 사용하면 더 간편하게 작성할 수 있습니다.

 

6. Array Operator (filter, map, reduce 등) & chaining

// ❌ bad 💥
function getEvenNumber(items) {
  return items.filter((num) => num & 2 === 0);
}
function mutiplyBySeven(items) {
  return items.map((num) => num * 7);
}
function sumArray(items){
  return items.reduce((a, b) => a + b, 0);
}

const evens = getEvenNumber(items);
const multiple = multiplyBySeven(items);
const sum = sumArray(multiple);

console.log(sum);

배열과 관련된 연산을 하는 경우에 Array Opterator를 활용하면 좋습니다. 하지만, 사용하는 빈도에 비해 함수가 너무 많아 보이고, 할당 해주는 부분이 불필요해 보입니다.

// ⭕️ better 🌈
const result = items
  .filter((num) => num & 2 === 0)
  .map((num) => num * 7)
  .reduce((a, b) => a + b, 0);

console.log(result);

위와 같이 연속성을 갖는 경우에 Array Operator을 chaining 해줌으로써 꽤나 보기 좋게 만들 수 있습니다.

 

7. Async / Await 

// ❌ bad 💥
function displayBlogName() {
  fetchBlog() 
    .then((blog) => {
      fetchDetail(blog)
        .then((name) => {
          updateUI(blog, name);
        });
    });
}

Promise를 중첩하여 사용하는 경우에 코드는 매우 길어지고 가독성 또한 떨어지게 됩니다.

// ⭕️ better 🌈
async function displayBlogName() {
  const blog = await fetchBlog();
  const name = await fetchDetail(blog);
  updateUI(blog, name);
}

두 가지 이상의 Promise를 연결해서 사용할 경우에는 async / await 을 사용하면 좋은 코드를 만들 수 있습니다. 이전 코드에 비해 한눈에 이해하기 쉬워진 것을 확인할 수 있습니다.

 

최근에 Javascirpt를 공부하면서 도움이 될만한 내용들을 정리해보았습니다. 위에 적힌 예시가 무조건 좋은 것만은 아니지만, 대부분의 상황에서는 좋을 것이라고 생각됩니다. 읽기 좋은 코드가 잘 만든 코드라는 말이 이러한 곳에서 나오는 것 같습니다. 

 

읽어주셔서 감사합니다.

 

728x90