[SOLID] I - Interface Segregation Principle

ChoiYongHyeun·2024년 3월 28일
0

프로그래밍 공부

목록 보기
12/15
post-thumbnail

Interpace Segregation Principle (ISP)

ISP 란 구현에 의존하고 있는 인터페이스가 Compact 해야 한다는 것을 의미한다.

React 에서 사용되는 ISP 에 대한 원칙을 하기 전 , 객체 지향에서 이야기 하는 ISP 에 대해 먼저 이야기 한 후 React 에서 사용되는 ISP 원칙에 대해이야기 해보자

일반적인 객체지향에서의 ISP

class Calculator {
  introduce() {
    console.log('안녕하세요 저는 계산기입니다');
  }

  add(num1, num2) {
    return num1 + num2;
  }

  subtract(num1, num2) {
    return num1 - num2;
  }

  multiply(num1, num2) {
    return num1 * num2;
  }

  devide(num1, num2) {
    return num1 / num2;
  }
}

const adder = new Calculator();
const subtracter = new Calculator();
const multiplier = new Calculator();
const devider = new Calculator();

다음과 같이 Calculator 라는 추상화 된 인터페이스를 사용하는 adder , subtracter , mutiplier , devider 객체들이 존재한다고 이야기 해보자

각 객체들은 객체명에서 알 수 있듯이 한 가지 기능만을 하는 객체이다.

현재 아키텍쳐의 관계는 객체의 기능은 제한적임에도 불가하고 다양한 기능이 있는 Calculator 인터페이스에 의존성을 가지고 있는 모습을 볼 수 있다.

이렇게 사용하는 인터페이스가 무거워질 수록 (교재에서는 fat 이라는 표현을 한다.) 아키텍쳐의 구조를 명확하게 아는 것이 힘들다.

뚱뚱한 인터페이스를 수정하던 과정에서 예기치 못한 다른 메소드에도 영항을 미쳐 오류들이 범잡을 수 없이 늘어나기도 하고 말이다.

또한 우리는 현재 런타임 시 컴파일 되는 자바스크립트 언어를 이용하고 있지만 만약 컴파일을 사용하는 언어를 사용 할 시 뚱뚱한 인터페이스인 Calculator 에 새 기능이 추가되거나 객체와 상관없는 메소드가 수정되게 되면

수정된 부분과 상관 없는 객체들 마저도 다시 컴파일 해줘야 한다는 단점이 존재한다.

올바른 ISP

추상화된 클래스와 해당 클래스를 이용해 만든 객체의 관계가 1:1로 잘 대응 될 수록 아키텍쳐의 구조를 명확하게 보는 것이 쉽고

객체와 클래스를 관리하는 것이 더 용이해진다.

class Calculator {
  introduce() {
    console.log('안녕하세요 저는 계산기입니다');
  }
}

class Adder extends Calculator {
  add(num1, num2) {
    return num1 + num2;
  }
}

class Subtracter extends Calculator {
  subtract(num1, num2) {
    return num1 - num2;
  }
}

...

class Devider extends Calculator {
  devide(num1, num2) {
    return num1 / num2;
  }
}

const adder = new Adder();
const subtracter = new Subtracter();
const multiplier = new Multiplier();
const devider = new Devider();

다음처럼 인터페이스와 객체의 관계가 1:1로 잘 대응 될 수록 하여 클래스와 객체 간의 관계를 명확하게 이해하는 것이 가능하다.

항상 기억하자 , 뚱뚱한 인터페이스는 관리하기가 매우 힘들다.


React 에서의 ISP

React 에서의 ISP 는 객체지향에서의 ISP 와 깊은 연관은 없지만

뚱뚱한 요소들과 의존성을 갖고 있는 경우는 자주 볼 수 있다. 예를 들어

props 가 뚱뚱한 경우

const users = {
  lastName: 'dongdong',
  age: 20,
};

export default function GreetingName ({users}) {
  return <h1>안녕하세요 {users.lastName}</h1>
}


export default function GreetingAge ({users}) {
  return <h1>안녕하세요 {users.age} 살이시군요 </h1>
}

GreetingName , GreetingAge 컴포넌트의 경우는 props 로 뚱뚱한 users 객체를 받는다.

실제 필요한 기능은 users 객체의 일부 정보인데 말이다.

이 때 users 에 새로운 값이 추가되거나 , 기존의 값이 수정이 되게 된다면

본인이 사용하지 않는 property 일지라도 객체가 변경됨에 따라 각 컴포넌트는 불필요한 리렌더링을 겪게 된다.

const users = {
  lastName: 'dongdong',
  age: 20,
};

export default function GreetingName ({lastName}) {
  return <h1>안녕하세요 {lastName}</h1>
}


export default function GreetingAge ({age}) {
  return <h1>안녕하세요 {age} 살이시군요 </h1>
}

뚱뚱한 props 를 받는 것이 아니라 본인에게 필요한 내용만 props 를 받음으로서 의존성의 관계를

뚱뚱한 props 가 아닌 필요한 부분에만 의존성을 갖도록 변경해줄 수 있다.

추가적으로 불필요한 state 문이나 context 를 컴포넌트 내부에서 불러오는 등의 경우도 ISP 를 지키지 못한 경우로 생각 할 수 있을 것이다.

profile
빨리 가는 유일한 방법은 제대로 가는 것이다

0개의 댓글