[JS : CLEAN CODE] 객체와 자료구조

이인송·2021년 4월 8일
0
post-thumbnail

왜 이 글을 쓰는가?

글을 쓸 때 내가 항상 이 글을 왜 쓰는지 질문을 던진 이후에 글을 써야
조금 더 글을 쓰는 방향이 명확해지는 거 같다.

SOPT 에서 저번 주 토요일부터 클린코드 / 최적화 스터디를 시작했다.
React 를 이제 막 공부하기 시작하면서, JS 를 기본적인 개념보다
조금 더 딥하게 공부하는 경험이 도움이 될 거 같다고 생각해서 스터디에 참여했다.

그리고 혼자 이해하고 끝내기 보다는 나의 지식을 누군가에게 알려주면서
나도 학습의 효율을 증진시킬 수 있고, 같이 성장할 수 있다고 생각했다.
작년 겨울방학때부터 같이 성장하는 경험을 하는건 너무나도 재밌다는걸 느꼈고,
이번 스터디 또한 그러한 경험이 될 수 있게 준비해봐야겠다!
나만의 언어로 정리하고, 모르는 부분은 좀 더 깊게 공부하는 경험을 해보자

이번 글은 goormedu 의 CLEAN CODE JAVASCRIPT 를 공부하고, 해당 챕터에 대한
내용을 작성하는 방식으로 정리할 것이다.

이 강의는 소프트웨어 방법론에 관한 책들 중 Robert C. Martin's 의 책인 Clean Code에 있는 내용을
Javascript 언어에 적용시켜 적은 문서 형식의 강의이다.

먼저, 객체와 자료구조에 공부해보자

강의의 내용을 적으면서 모르는 부분은 하이라이트를 통해 체크하고,
바로 밑에 따로 키워드 식으로 정리하고, 내가 이해한 내용을 나만의 언어로 정리하려고 한다




객체와 자료구조

1. getter 와 setter 을 사용하세요

JavaScript는 인터페이스와 타입을 가지고있지 않고 이러한 패턴을 적용하기가 힘듭니다.
왜냐하면 public이나 private같은 키워드가 없기 때문이죠.
그렇기 때문에 getter 및 setter를 사용하여 객체의 데이터에 접근하는 것이
객체의 속성을 찾는 것보다 훨씬 낫습니다.
"왜요?"라고 왜 그런지에 대해서 몇 가지 이유를 두서없이 적어봤습니다.

객체의 속성을 얻는 것 이상의 많은 것을 하고싶을 때,
코드에서 모든 접근자를 찾아 바꾸고 할 필요가 없습니다.

  • set할때 검증로직을 추가하는 것이 코드를 더 간단하게 만듭니다.
  • 내부용 API를 캡슐화 할 수 있습니다.
  • getting과 setting할 때 로그를 찾거나 에러처리를 하기 쉽습니다.
  • 서버에서 객체 속성을 받아올 때 lazy load 할 수 있습니다.

인터페이스와 타입

위에서 살펴봤듯이 JS 에서는 인터페이스와 타입이 존재하지않는다!

대신 TypeScript 을 예시로 인터페이스와 타입을 살짝 알아보자
인터페이스로 타입을 정의하기 위해 interface 키워드를 사용했다

Java 에서 인터페이스는 클래스를 구현하기 전에 필요한 메서드를 정의

interface Person {
    name: string;
    age: number
}

const p1: Person = { name: 'mike', age: 23};

getter 및 setter

짧게 예시 코드만 다뤄보자

let user = {
  name: "John",
  surname: "Smith",

  get fullName() {
    return `${this.name} ${this.surname}`;
  },

  set fullName(value) {
    [this.name, this.surname] = value.split(" ");
  }
};

이렇게 getter와 setter 메서드를 구현하면 객체엔 fullName이라는 '가상’의 프로퍼티가 생긴다.
가상의 프로퍼티는 읽고 쓸 순 있지만 실제로는 존재하지 않는다.

set 할때 검증로직을 추가

let user = {
  get name() {
    return this._name;
  },

  set name(value) {
    if (value.length < 4) {
      alert("입력하신 값이 너무 짧습니다. 네 글자 이상으로 구성된 이름을 입력하세요.");
      return;
    }
    this._name = value;
  }
};

user.name = "Pete";
alert(user.name); // Pete

user.name = ""; // 너무 짧은 이름을 할당하려 함

setter 메서드 내부에 value 의 길이가 4보다 작을 경우 alert 가 실행되게 검증 로직을 추가하였다

내부용 API 를 캡슐화한다

API 를 왜 사용하는지에 대해 알아보자!

API 를 이용하면 내부 개발자의 리소스를 감소시키지 않으면서 제품에 대한 관심을 높이고,
기존 기능을 강화하고, 새로운 능력을 구축할 수 있는 효율적이고 비용 효과를 높일 수 있다!

즉, API는 데이터를 빠르고 안전하게 전달하고 처리하면서
애플리케이션 및 데이터베이스 사이에서 커뮤니케이션 레이어로 기능한다.

물론 우리가 개발할 때 사용할 때의 API 와는 다르게 와닿을 수 도 있지만, API 의 용도는 큰 틀에서 다르지 않다


✋ 캡슐화란 무엇일까?
일반적으로 연관 있는 변수와 함수를 클래스로 묶는 작업을 말한다.
캡슐화에는 은닉성이란게 있어서
클래스에 담는 내용 중 중요한 데이터나 기능을 외부에서 접근하지 못하게 할 수 있다.


자바스크립트에서 캡슐화하는 예제 코드를 통해 이해해보자

function MyClass() { 
  //public 프로퍼티 
  this.프로퍼티이름 =; 
  //private/protected 프로퍼티 
  this._프로퍼티이름 =; 
} 

// public 메서드 
MyClass.prototype.메서드이름 = function() { 

} 

// private/protected 메서드 
// _를 붙이는 것은 외부에서 언더바를 붙힌 프로퍼티나 메서드에 접근하여 사용하지 말라는 암묵적인 약속
MyClass.prototype._메서드이름 = function() { 

}

내가 이해한 바로는 내부용 API 를 캡슐화하는 것은 함수 내부에서 사용하는 API 를 변수와 함께 묶고
해당 API 를 외부에서 사용자가 임의로 접근 및 변경하지 못하게 하는 것이다.


레이지로딩

사이즈가 큰 데이터를 로딩할 때, 사용자의 브라우저 화면에 나타나지 않은 이미지까지 로딩을 하면 페이지 로딩이 느려질 수 있다.

Lazy Loading 은 사용자 브라우저에 보이는 이미지만 로딩하고, 다른 이미지들은 사용자가
스크롤하면서 이미지에 가까워질 시 로딩된다!

😎 그렇다면 getter 와 setter 를 통해 속성에 접근하는 것이 어떻게 lazyloading 하게 하는 것일까?

원래는 서버에서 객체를 받아오면 모든 속성들을 다 받아와야 하는데, 예를들어
Person 안에 age, name, gender가 있으면 Person 자체를 return 해오게 되면 모든 속성을 한번에 다 로드해야하는데,

getName 이런식으로 getter로 받아오면, 처음부터 모든 속성을 다 로드할 필요없이 그때그때 접근하고 싶은 속성에 대해서만 getName 으로 접근할 수 있다



예제코드

용어에 대해 어느 정도 이해했고, 개념이 이해됐다면
안좋은 예시와 위 사항을 적용한 좋은 예시를 살펴보자!

안좋은 예

function makeBankAccount() {
  // ...

  return {
    // ...
    balance: 0
  };
}

const account = makeBankAccount();
account.balance = 100;

좋은 예

function makeBankAccount() {
  // private으로 선언된 변수
  let balance = 0;

  // 아래 return을 통해 public으로 선언된 "getter"
  function getBalance() {
    return balance;
  }

  // 아래 return을 통해 public으로 선언된 "setter"
  function setBalance(amount) {
    // ... balance를 업데이트하기 전 검증로직
    balance = amount;
  }

  return {
    // ...
    getBalance,
    setBalance
  };
}

const account = makeBankAccount();
account.setBalance(100);


2. 객체에 비공개 멤버를 만드세요

클로져를 이용함으로써 구현할 수 있다.
employee.name 을 delete 했지만, 여전히 남아있는 걸 확인할 수 있다

안좋은 예:

const Employee = function(name) {
  this.name = name;
};

Employee.prototype.getName = function getName() {
  return this.name;
};

const employee = new Employee('John Doe');
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined

좋은 예:

function makeEmployee(name) {
  return {
    getName() {
      return name;
    },
  };
}

const employee = makeEmployee('John Doe');
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
profile
프론트 엔드와 심리학을 공부하는 대학생입니다 :)

1개의 댓글

comment-user-thumbnail
2021년 4월 9일

저도 클린코드 관심있는데, 포스팅 보고 많은 공부가 됐어요 감사합니다 😁

답글 달기