Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1단계 - 지하철 노선도 미션] 미키(권세진) 미션 제출합니다. #21

Merged
merged 121 commits into from
Jun 19, 2021

Conversation

0307kwon
Copy link

@0307kwon 0307kwon commented Jun 1, 2021

1단계 - 지하철 미션 🚋

데모 페이지

스토리 북

안녕하세요 발리스타님! @SunYoungKwon 과 함께 지하철 미션으로 돌아온 ✨미키✨입니다!! 🐭🐭🐭

자동차 경주 미션 이후 처음이네요 😭😭😭😭

마지막 미션으로 발리스팀을 다시 만나게 되어 너무 기쁩니다!

마지막 미션인 만큼 열정을 담아 최선을 다해 배워가겠습니다!! 🔥🔥🔥

🙋‍♂️ 집중적으로 피드백 받고 싶은 부분

💕 커스텀 훅을 분리한 것이 적절할까요? 시도해보았습니다!

처음에는 formInput이라는 state로 모든 input을 하나로 묶어보려고 했는데

이건 너무 훅의 크기가 커지는 것 같아 포기하고

input에 관련된 변수와 로직들을 하나로 묶고 관심 있는 부분만 노출시키고 싶어

useNotificationInput과 useInput 커스텀 훅을 만들어 보았습니다!

이렇게 만들어보았더니 다음과 같은 장단점을 느꼈습니다.

  • 장점
    • 어떤 input의 errorMessage가 다른 input에 의존되어 동작할 때, useNotificationInput이 의존성을 인자로 받기 때문에 구현이 편했습니다.
    • input 상태와 해당 input과 관련된 로직을 한 곳에 묶어두어 가독성이 높아지는 것 같았습니다.
    • setInput,setErrorMessage 등을 내부적으로 숨기고 필요할 때만 제한적으로 사용하게하여 에러를 줄일 수 있지 않을까 생각합니다.
  • 단점
    • 자유도를 너무 빼앗아 가는 느낌이 들었습니다. 다양한 상황에 대처하기 어려웠습니다.
    • 이전에는 input 상태 선언들을 컴포넌트 상단에 모두 위치시켜 한눈에 어떤 input들이 있는지 확인할 수 있었는데 훅을 적용한 후에는 한눈에 보기가 어려워졌습니다.

의미가 있는 커스텀 훅이었을까요?! 더 좋은 방식으로 훅을 빼낼 수도 있을 것 같은데 아직 미흡하여 잘 모르겠습니다 ㅠㅜ

커스텀 훅에 대한 발리스타님의 의견이 궁금합니다! 😁

💕 생각보다 편하지 않았던 리덕스 툴킷

물론 리덕스만 사용하는 것보다는 리덕스 툴킷이

액션을 일일이 만들어주지 않아도 된다는 점,

그리고 관련된 액션과 리듀서의 코드가 가까이 있어 파악하기가 쉬웠다는 점이 좋았습니다.

하지만 리덕스 툴킷도 생각보다 불편했습니다.

새로운 요청을 위한 리덕스 썽크 함수를 매번 만들어야하는 등 반복적인 작업을 하는 것은 여전했습니다.

저희가 리덕스 툴킷을 처음 사용해보아 제대로 툴킷을 적용한 것인지 중점적으로 봐주시면 좋겠습니다 :)

💕 지하철 앱에 리덕스를 적용하는 것이 괜찮은 방식일까요?

우선 저희가 상태관리로 리덕스 툴킷을 적용한 이유는

  • 과도한 prop drilling 방지
  • fetch로 가져온 데이터를 리덕스 상태로 가지고 있으면 불필요한 fetch를 줄일 수 있을 것

이렇게 2가지가 있었습니다.

하지만 실제로는 prop drilling이 그렇게 심하게 일어나는 것 같지는 않았고

fetch도 Get 요청을 최대한 줄여보려 했지만 결국에는 서버 데이터와 동기화를 위해 매번 fetch하는 수 밖에 없어

리덕스 툴킷을 사용하면서 리덕스의 장점을 그렇게 살리지는 못했다는 생각이 듭니다.

(Redux DevTool로 상태 변화를 추적하는 것은 편했던 것 같습니다.)

이번 미션은 정말로 fetch만 사용했어도 되었을지도 모른다는 생각이 듭니다.

아직까지는 redux를 사용하는 이유가 그렇게 와닿지 않아서

혹시 현업에서는 어떤 이유로 redux를 많이 쓰는지 알고 싶습니다!

💕 아직 React Testing Library를 제대로 쓰지 못하는 것 같습니다

아직 단위 테스트와 E2E 테스트의 개념이 잘 잡히지 않는 것 같습니다.

이번 미션에서 저는 <Signup /> 이라는 컴포넌트를 테스트하기 위해

여러 input을 입력하고, submit 버튼을 누르고, request 함수가 제대로 실행되었는지

검증하였습니다.

그런데 이런 방식으로 테스트하니 E2E 테스트라는 생각이 들었습니다.

저는 처음에는 컴포넌트라는 단위를 테스트하는 것이 단위 테스트라는 생각을 하였는데

이런 방식으로 테스트하니 유저 입장에서 처음부터 끝까지 테스트하는 E2E 테스트라는 생각이 들었습니다.

그리고 cypress처럼 input에 입력값을 넣고 버튼을 누르는 동작들이 화면에 보이는 것도 아니라 cypress보다 더 답답했습니다. React Testing Library의 장점을 제대로 활용하지 못하고 있다는 생각이 들었습니다.

이에 대해 다른 크루의 의견도 물어보았는데 테스트할 기능 하나만 빼고 모두 mocking하여 테스트하는 방식으로 하고 있다고 대답을 들었습니다.

단위 테스트는 어디서부터 어디까지 mocking해야하는 것일까요? 궁금합니다! 🙋‍♂️

Copy link
Author

@0307kwon 0307kwon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요 발리스타님! 미키입니다 ㅎㅎ
어제 발리스타 님을 볼 수 있어서 너무 반가웠습니다 😊
이번 미션에서 모달 부분이 잘 이해가 안가서 어제 여쭤보았었는데요
사실 잘 이해가 안되었습니다...... ㅠㅜ 😭
그래서 모달 부분에 대한 질문Form을 context API로 만들어본 것
두가지가 피드백에 관한 가장 큰 질문입니다!
그 동안 정말 감사했습니다!! 🧡

피드백 관련 질문

모달 관련 질문1
모달 관련 질문2
@를 붙이므로써 더 의미가 강조되는게 있을까요?
Form을 context API로 구현

추가적인 질문

요즘 에러 핸들링을 어디서 해야하는 지 고민이 많습니다!
계속 코드를 짜면서도 에러 핸들링 코드가 너무 분산되는 느낌이 듭니다
고민을 하면서 스스로 생각해보았을 때
보통 fetch와 같은 비동기 요청에서 try catch로 핸들링 하는 경우가 많으므로
API 레이어에서 에러 핸들링을 마치고 추가적인 사이드 이펙트를 막아 최대한 정상 동작 시켜야한다고 생각합니다
그리고 나머지 에러들은 에러바운더리에서 한번에 핸들링하여
화면을 모두 날려버리지 않고, 준비된 화면을 보여주는 것이 맞지 않을까...? 라고 생각합니다!

보통 에러 핸들링은 어디서 처리를 해주는 것이 좋을까요?
발리스타님의 의견이 궁금합니다! 😁

.storybook/main.js Outdated Show resolved Hide resolved
package.json Outdated Show resolved Hide resolved
src/App.tsx Outdated Show resolved Hide resolved
src/App.tsx Outdated Show resolved Hide resolved
src/App.tsx Outdated Show resolved Hide resolved
src/hooks/useModal/useModal.ts Outdated Show resolved Hide resolved
import { LineColorContainer, LineForm, LineModalButtonContainer } from './LinesModal.styles';

interface Props {
onClose: () => void;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ㅠㅜ 다른 모달 관련 피드백과 같은 맥락이군용... 다른 피드백에 질문드렸습니다! 😭

const history = useHistory();
const [errorMessage, setErrorMessage] = useState('');

const onLogin: FormEventHandler<HTMLFormElement> = async (event) => {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어디서부터 어디까지 빼는 것이 좋을까 고민을 하다가 정말 최소한만 page에 남기고
모두 hooks/service 레이어로 빼주었습니다!
이렇게 하니 페이지에서는 마크업만이 남았고 service 레이어에서는 비즈니스 로직이 모두 들어가게 되어
좀 더 명확한 분리가 이루어지는 것 같았습니다.

이러한 방식으로 시도하는 것이 좋은 방향일까요?! 궁금합니다! 🙋‍♂️

src/components/LinesModal/LineAddModal.tsx Outdated Show resolved Hide resolved
src/api/lines.ts Outdated Show resolved Hide resolved
@0307kwon 0307kwon force-pushed the step1 branch 4 times, most recently from 1ba5f3a to 7d256dc Compare June 11, 2021 16:23
@Vallista
Copy link

일단 미키,

Page에서 Modal을 관리하고 있어 Page와 Modal을 연결해주기 위한 훅이었습니다!
Page에서 Modal을 사용할 때마다 공통적으로 isModalOpen 상태가 있고,
Modal을 열고 닫는 메서드가 있고, 모달로 가끔 데이터를 보내야할 일이 있어
(LineAddModal에서 targetLine을 넘겨주어야할때)
이렇게 사용하고 있습니다!

앞서 피드백 주신 Modal의 onClose 문제와 같은 결으로 보입니다
아직 저에게는 이해하기 어려운 부분인 것 같아용 ㅠㅜ 😭
이 부분에 대해 좀 더 자세히 여쭤봐도 될까요?! 🙋‍♂️

+ unknown 부분에 대해서는 제네릭으로 처리 했습니다!

요 답변에는 답변 안할께여! 스스로 알아보시길 권합니다... ㅋㅋ
이 것을 깨달으려면, onClose를 쓰고/안쓰고 시점에서 개발해보세요.
그리고 객체란 무엇이고 컴포넌트란 무엇인가?를 조금 더 고민해보시길 권합니다!

매일 바로 답을 줬지만, 만나서 설명했음에도 이해를 못했다는것은! 그 외적인 지식이 부족하다는 뜻입니다!!
그렇기 때문에 그 과정에서 지식을 얻을수 있을거라 생각합니다 👍

홧팅

@0307kwon
Copy link
Author

0307kwon commented Jun 15, 2021

@Vallista 발리스타님 마지막 피드백 감사합니다!
컴포넌트는 독립적으로 실행이 가능한 모듈이고 onClose에 의해 다른 컴포넌트에 종속되면
캡슐화에 있어서 좋지 않고 재사용성이 떨어진다는 것을 알게되었습니다!
객체 지향과 컴포넌트에 대해서 어느정도 알고 있다고 생각하고 있었는데 다시 공부를 해보니 모르는 내용이 많았습니다!
이를 공부하여 블로그에 정리해보았습니다!

객체 지향 프로그래밍 공부
객체 지향을 잘 구현하기 위한 5원칙 - SOLID

또한 onClose는 없어야 된다는 것은 이해가 갔지만 어떻게 구현해야하는가에 대해 고민이 많았습니다!
그런데 최근에 form을 context api로 구현해보라고 하신 발리스타님의 피드백을 보고
모달도 context api로 만들 수 있지 않을까? 라는 생각을 하였고, 이를 context api로 만들었더니
이제야 모달이 독립적인 컴포넌트의 모습으로 구현되었습니다.
이전에 필요없는 isModalOpen을 각 page마다 선언하고 이 때문에 page에 모달이 종속되는 형태보다
훨씬 깔끔하고 재사용성이 높은 형태인 것 같습니다. 감사합니다! 👍👍

이번에 context api의 역할이 그저 다크모드나 언어 선택 기능 정도에 국한되는 것은 아니라는 것을 알게되었습니다.
context api의 활용에 대해 더 넓은 시야를 가지게 된 것 같습니다! ㅎㅎ 감사합니다 😁

혹시 다음 단계로 넘어가도 괜찮을까요? 😊

@Vallista
Copy link

고고!

@Vallista Vallista merged commit b4f7b02 into woowacourse:0307kwon Jun 19, 2021
@0307kwon
Copy link
Author

학습로그

[테스트]{컴포넌트 테스트와 E2E 테스트의 차이점} - 4/5

내용

컴포넌트 테스트와 E2E 테스트가 헷갈렸던 경험

page 컴포넌트 단위로 테스트를 진행하면서 page 중에서도 signup 페이지를 테스트하면서
signup 페이지도 결국에는 사용자의 input을 받고, submit 버튼을 누르면 적절한 결과를 보여주는 점에서 E2E테스트와 다른 점이 없지 않나? 라는 생각이 들었다.

컴포넌트 테스트 vs E2E 테스트

컴포넌트 테스트와 E2E 테스트의 가장 큰 차이점은 관점 의 차이이다.
컴포넌트 테스트는 독립적인 컴포넌트의 관점에서 외부 요인과 관계없이 어떤 결과를 기대할 수 있는가를 테스트하는 것이고
E2E 테스트는 철저히 사용자의 관점에서 세워진 시나리오 하에서
어떠한 결과를 기대할 수 있는지에 대한 테스트이다.
(따라서 여러 컴포넌트에 걸쳐 테스트하여도 상관 x)

+컴포넌트에서의 단위 테스트와 통합 테스트

리액트 공식 문서에서 말하는 컴포넌트 테스트는 단위 테스트와 통합 테스트의 구분이 명확하지 않다고 한다.
예를 들어 form 컴포넌트에 대한 테스트를 작성한다고 가정했을 때

form 내부의 button 컴포넌트도 같이 테스트해야하는 것인가?
아니면 button 컴포넌트에 적합한 테스트를 따로 작성해야하는 것인가?

이러한 질문에 대한 답은 팀마다 다를 수 있지만, 어떤 답을 도출하느냐에 따라서
컴포넌트 테스트가 어떤 테스트의 성격을 띄는지가 달라진다.
따라서 컴포넌트 테스트는 단위 테스트와 통합 테스트가 혼재되어 있다고 볼수 있다.

✨ 유닛 테스트

로직을 가진 단일한 함수, 클래스 또는 객체에 대한 테스트.

✨ 통합 테스트

여러개의 유닛이 다른 유닛과 통합되는 과정에서 일어나는 일에 대한 테스트

링크

https://reactjs.org/docs/testing.html
https://kentcdodds.com/blog/the-testing-trophy-and-testing-classifications

[리액트]{객체 vs 컴포넌트} - 4/5

내용

객체와 컴포넌트. 같은 것이라 생각할 수 있지만 엄연히 다른 개념이다.

  • 객체

    하나의 클래스를 통해 실체화데이터와 메소드의 모음이다.
    메소드를 통해 외부와 상호작용 할 수 있으며 객체 지향 프로그래밍에서
    코드를 이루는 가장 작은 단위가 된다.
    자동차로 예를 든다면 작은 나사로 예를 들 수 있다.

  • 컴포넌트

    독립적으로 배포될 수 있고 조립/교환이 가능한 응집도가 높은 단위 모듈.
    많은 객체들로 구성되어 있다.
    많은 나사들과 엔진 등으로 이루어진 자동차를 컴포넌트의 예로 들 수 있다.

링크

https://www.geeksforgeeks.org/difference-between-component-and-object/

https://mckdh.tistory.com/entry/객체지향의-탄생-객체와-컴포넌트-아키첵처와-아키텍트

[js]{객체 지향 프로그래밍} - 5/5

내용

  • 객체 지향 프로그래밍 (Object-Oriented Promgramming)
    프로그램을 단순히 코드의 나열로만 봤던 시각을 벗어나
    프로그램을 객체 라는 기본 단위로 나누고 객체들 간의 상호 작용으로 문제를 해결하는 방식
    독립성이 높은 객체들을 작은 단위부터 만들고, 그 작은 단위들을 재사용해가며 더 큰 객체들을
    만드는 방식으로, 상향식(Bottom-up) 방식이라고 할 수 있다.
    (Top-down 방식은 객체 지향 이전의 구조적 프로그래밍 방식이라고 볼 수 있다.)

  • 객체 지향 프로그래밍의 구성 요소

    • 클래스
      같은 종류의 문제 해결을 위한 속성과 기능을 정의한 것.
      외부 요소와 독립적이고 추상적으로 만들어져야 한다.
      객체 지향 프로그래밍에서의 기본적인 설계도라고 할 수 있다.

    • 객체
      클래스라는 설계도를 통해 만들어진 실체라고 할 수 있다.
      객체는 자신 고유의 속성을 가지며 클래스로부터 만들어진 기능을 사용할 수 있다.

    • 메서드, 메시지
      클래스 내부에 정의된 함수를 메서드라고 한다.
      개발자는 클래스를 통해 객체를 생성하고
      객체의 외부로 공개된 메서드를 통해 해당 객체에 명령을 내릴 수 있는데 이렇게 메서드를 사용하는 행위를 메시지를 보낸다고도 할 수 있다.

  • 객체 지향 프로그래밍의 특징

    1. 캡슐화
      특정 모듈의 세부 구현을 감추고 외부로의 노출을 최소화하여
      모듈의 응집도를 높이고 모듈 간의 의존도를 떨어뜨려
      재사용할 수 있는 모듈으로 만드는 것.
      정보은닉과 추상화의 개념이 녹아있다고 생각하면 된다.

      ✨ 추상화 : 상세한 구현은 드러내지 않고 중요한 개념만 외부로 드러내는 것.

      ✨ 응집도 : 모듈의 요소들이 같이 속하는 정도를 의미한다.
      클래스의 목적을 나타낸 속성과 기능이 얼마나 서로 강하게 관계되어 있는지 측정하는 요소이다.

    2. 상속
      자식 클래스가 부모 클래스의 기능을 그대로 물려받는 것을 의미.
      자식 클래스는 부모 클래스의 기능을 물려받으며
      새로운 기능을 추가하거나
      기존에 부모 클래스가 가진 기능을 일부 수정하는 등(오버라이딩)
      캡슐화를 유지하면서 개념을 확장시킬 수 있다.

    3. 다형성
      클래스 상속 구조 내, 같은 이름의 메소드를 사용하더라도 맥락에 따라 다른 기능을 수행하는 것을 의미한다.
      예를 들어 단형성(다형성의 반대) 체계를 가진 프로그래밍 언어에서는
      다음과 같이 구현할 수 있다.

      //숫자를 문자열로 바꾸는 경우
      string = StringFromNumber(number);
      
      //날짜를 문자열로 바꾸는 경우
      string = StringFromDate(date);

      하지만 다형성 체계를 가진 프로그래밍 언어에서는 똑같은 메소드 이름으로 구현할 수 있다.

      //숫자를 문자열로 바꾸는 경우
      string = number.StringValue();
      
      //날짜를 문자열로 바꾸는 경우
      string = date.StringValue();
      

      이렇듯 객체의 타입과 상관없이 외부에서 객체의 메소드를 사용함에 있어 추상도가 높은 형식으로 구현할 수 있다.
      자바스크립트에서는 오버라이딩만 구현되어있고 오버 로딩은 불가하나 타입스크립트로 오버 로딩을 구현할 수 있어 이를 보완할 수 있다.

[js]{객체 지향 프로그래밍을 잘 하기 위한 5원칙 (SOLID)} - 5/5

  • SOLID란?
    소프트웨어 디자인을 더 이해하기 쉽고, 유연하고, 유지보수하기 좋은 형태로 만들기 위한 5가지의 디자인 원칙들의 앞 글자를 따 기억하기 쉽도록 만든 것.

  • S.O.L.I.D

    • Single-responsibility principle : 단일 책임 원칙
      클래스는 오직 하나의 액터에 대한 책임만을 가진다.

      여기서 액터는 같은 방향으로 클래스가 변화하기를 요구하는 이해관계자나 사용자 그룹을 의미한다.
      예를 들어 철수는 스마트폰을 동영상 재생을 위해 사용하고, 영희는 전화를 위해 사용한다면
      철수와 영희는 스마트폰이 각자 다른 방식으로 변하기를 바랄 것이다.
      철수는 동영상 감상을 위해 스마트폰이 더 커지길 원할 것이고
      영희는 전화 품질이 더 높아지길 원할 것이다.

      이렇게 되면 철수와 영희는 별개의 액터로 볼 수 있고,
      스마트폰이 두 액터 모두에게 책임을 가진다면 이는 단일 책임 원칙을 위반한다고 할 수 있다.
      따라서 단일 책임 원칙은 해당 클래스 내부 구현에만 관심을 가지는 것이 아니라
      해당 클래스를 사용하는 입장에서 바라보는 원칙이라고 할 수 있다.

      참고1

      참고2

    • Open-Closed Principle : 개방-폐쇄 원칙
      클래스는 확장에 대해서는 개방적이고 수정에 대해서는 폐쇄적이어야한다는 원칙이다.

      예를 들어 Animal이라는 클래스를 상속받는 Cat 클래스와 Chicken 클래스가 있다.
      Cat과 Chicken은 Animal의 walk 메서드를 물려받지만
      두 동물의 걷는 방식은 다르다. 하지만 Cat이 Chicken과
      걷는 방식이 다르다고 해서 Animal 클래스의 walk 메서드를 수정할 필요는 없다. 그저 Animal 클래스를 확장하여 walk 메서드만 재정의하면 된다.

      이를 보고 확장에 의한 재정의에는 개방적이고
      수정에 대해서는 폐쇄적이라고 한다.

    • Liskov Substitution Principle : 리스코프 치환 원칙
      자식 클래스는 언제나 부모 클래스를 대체할 수 있어야한다는 원칙이다.

      이를 지키지 못하면 부모 클래스가 가진 메서드를 자식 클래스가 가지지 않는다는 것이므로 자식 클래스가 부모 클래스와 다르게 변질되고 객체 지향이 가지는 상속의 특징도 잃게 된다.

    • Interface segregation principle: 인터페이스 분리 원칙
      클라이언트에서 필요하지 않는 요소를 구현하도록 강요하거나 사용하지 않는 요소에 의존하도록 만들어서는 안된다는 원칙이다.

      ISP는 일반적인 목적의 인터페이스 하나보다 클라이언트에 특화된 많은 인터페이스를 만들어 하나의 클래스의 목적에 맞지 않는 요소를 없애고 응집도를 높이기 위한 목적을 가지고 있다.
      이전의 예시와 같이 Animal 클래스를 상속받는 Cat과 Chicken 클래스를 만들고 Animal에 fly() 메서드를 정의한다고 가정해보자.
      이렇게 만들면 Cat은 날 수 없으므로 fly() 메서드를 오버라이딩하여 비워주어야할 것이다.
      그런데 Cat은 fly() 메서드를 가지고는 있으므로 메서드 호출은 가능할 것이다. 이렇게 만드는 방식은 Cat이 필요없는 메서드가 내부에 정의됨으로써 응집도를 떨어뜨린다.

      따라서 fly()메서드는 Animal 클래스에서 정의하는 것이 아니라
      좀 더 fly() 메서드가 어울리는 Chicken 클래스에서 정의하여 응집도를 높여야한다.

      ✨ 클라이언트 : 클라이언트-서버 구조에서 서버에서 클라이언트로 서비스를 요청하고 클라이언트는 요청에 맞게 사용자에게 적절한 형태로 표현하는 기능을 가진 프로그램을 뜻한다.
      메시지를 받는 클래스도 클라이언트라고 할 수 있다.

      ✨ 인터페이스: 어떤 객체와 상호 작용하는 형태를 의미. 자바에서는 인터페이스를 사용하는 클래스는 해당 인터페이스에 정의된 메소드를 반드시 오버라이딩해야한다.
      상속과는 조금 다르지만 자바에서는 상속과 같은 개념으로 사용하고 있으며 이를 통해 다중 상속이 가능하다.

    • Dependency inversion principle
      상위 계층이 하위 계층(세부 사항)에 의존하는 전통적인 의존 관계를 역전시켜 상위 계층이 하위 계층의 구현으로 부터 독립되도록 하는 원칙. 이를 통해 하위 계층의 변경이 상위 계층으로 전파되는 것을 막아 유지보수 측면에서 큰 이점이 있다.

      상위 클래스일수록, 추상 클래스일수록 변하지 않을 가능성이 높기 때문에 이를 의존하라는 것이 의존 역전 원칙이다.

      예를 들어 자동차라는 클래스가 스노우 타이어라는 하위 클래스에 의존되어 있다고 가정해보자.
      만약 스노우 타이어가 아닌, 일반 타이어로 바꾸려고 한다면 자동차 클래스의 코드까지 고쳐야하는 상황이 발생할 것이다.
      여기서 자동차가 스노우 타이어 같은 구체적인 클래스에 의존하지 않고 타이어 라는 추상적인 클래스에 의존하고,
      스노우 타이어 같은 구체적인 클래스는 상위 클래스인 타이어 를 의존한다면 어떨까?

      타이어 클래스의 자식 클래스인 스노우 타이어는, 같은 자식 클래스인 일반 타이어로 바뀌어도 자동차는 정상 작동할 것이다.
      자동차가 추상 클래스인 타이어 클래스에 의존되어 있기 때문이다.
      여기서 구체적인 스노우 타이어와 자동차 사이에 추상적인 타이어 클래스를 추가적으로 두어 스노우 타이어의 의존 관계를 역전시키고 있으므로 이를 의존 역전 원칙이라고 한다.

      참고(https://server-engineer.tistory.com/228)

링크

https://velog.io/@thms200/SOLID-원칙w.OOP

https://ko.wikipedia.org/wiki/SOLID_(객체_지향_설계)

https://hckcksrl.medium.com/solid-원칙-182f04d0d2b

https://ko.wikipedia.org/wiki/객체_지향_프로그래밍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants