티스토리 뷰

정신없이 한 주가 또 지나갔다. 

이번 주차는 알고리즘 주차! 내가 선택한 언어를 통해 열심히 알고리즘을 풀고, 시험까지 봤다.

 

하필 구름이가 옷에 오줌을 싸서 옷에 스며들기 전에 빨리 풀어야 한다는 압박감을 가지고 풀어서

의도치 않은 타임어택을 하게 되었다.

 

여튼! 알고리즘은 뭐 앞으로 계속 풀어나갈 것이고 재밌기도 하니까.

(사실 머리채 부여잡고 다른 사람들 풀이 보면서 한숨쉴 때가 더 많았음 ^0^)

 

그것보다도 이번주의 큰 수확은 자바에 대해 조금 더 친숙해졌다는 것이다.

지난 주 정리내용을 보면 내가 DIP를 언급하면서 의존성이 무엇인지를 써논 내용이 있다.

 

단순히 글로만 보았을 때에는 그냥 그런갑다 하고 지나가게 되는데, 이번에 인터페이스 구현 예제를 풀어보니 100%는 아니지만 아주 조오오오오금은 감이 온 듯 해서 쥐콩만한 뇌가 잊어버리기 전에 기록을 해 두려고 한다!

(하지만 이건 내 모자란 실력에 공부한 내용을 뇌피셜을 섞어 만든 가짜뉴스에 가까운 내용이니, 더 공부해서 더 그럴듯한 말로 나중에 더 정리할 필요가 있다 ㅠ)

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////

먼저 상황을 가정해 보자.

"내가 어떤 객체를 수정해야 한다면?"

 

사용자가 어떤 요청을 하고, 그 요청을 수반하는 데이터를 받는다고 하자.

요청을 받는 코드가 있고, 요청을 받아 처리하는 삼식이라는 코드와 미숙이라는 코드가 있다. 

그런데 무언의 사정이 생겨 미숙이라는 코드를 변경해야 하는 일이 생기고 말았다!

 

그럼 이 미숙이라는 코드를 수정하기 위한 방법으로는 

- 그냥 미숙이를 뜯어 고치기

- 미숙이 ver2를 새로 만들어서 덮어씌우기

정도가 있다고 생각한다.

 

먼저 미숙이를 뜯어 고치려면 소스코드가 필요하고 전반적인 수정이 필요할 것이다.

 

그렇다면 소스코드 없이 미숙이 ver2 코드를 준비한다고 했을 때, 요청을 받아서 넘기는 코드를 수정하지 않을 수 있을까?

생각해 보면 수정하지 않을 수는 없을 것이다.

 

요청을 받아서 넘기는 애는 뭐 대략

private Misook misook = new Misook();

misook.getAge();

뭐 이런 느낌으로 쓰고 있을텐데,

 

미숙이 ver2 코드를 추가하면 요청을 받아서 넘기는 코드에서 객체를

private Misook2 misook2 = new misook2();

misook2.getAge()

요런 식으로 바꿔줘야 하기 때문이다.

 

이 상태에서는 결국 미숙이를 고치냐, 요청을 받아주는 코드를 고치냐의 차이로 돌아오고, 결국 소스코드를 받아 수정해야 한다는 것에서는 차이가 없다. 

 

여기에서 "결합"이 등장한다!!! 

의존성과 관련있는 이 결합!

 

내가 요청을 받아넘기는 코드와 미숙이 코드는 결합력이 높다고 볼 수 있다.

왜냐면 수정이 일어났을 때, 소스코드를 받아서 요청을 받아넘기는 코드를 수정해야만 미숙이 ver2로 바꿀 수 있기 때문이다.

 

이 부분에서 결합력을 낮추기 위해 사용되는 것이 바로 "인터페이스"이다.

여기에서 요청을 받아 넘기는 코드에서 미숙이 코드를 misook, misook2로 나누는 것이 아니라

humanMisook과 같은 것으로 두는 것이다! 이게 바로 인터페이스!

 

사용자의 요청을 받았을 때, 이것이 misook, misook2로 분산되지 않고, humanMisook을 통해 다른 결과값을 얻어낼 수 있는 것이다!!

 

다만!! 여기에서 이런 궁금증이 생겼다.

"그런데 이러면 어짜피 사용자 요청을 넘기는 코드에서 new 생성자로 생성되는 객체부분을 수정해야 되는 거 아닌가?

 예를들면 위 과정대로라면, 어짜피 인터페이스를 써도

HumanMisook humanMisook = new misook();을 HumanMisook humanMisook = new misook2();로 바꿔줘야 하는 거 아닌가?

 

여기에서는 의존성 주입, 즉 DI라는 것이 등장한다.

DI는 의존관계를 외부에서 결정하는 것인데, 스프링의 도움을 받는 이 부분은 조금 더 공부하고 이해한 다음 추가 작성하고자 한다.

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

이제 대략적인 이해가 끝났으니, 마무리 정리를 해 보자.

 

자바에는 상속이라는 개념이 있다.

이는 부모클래스의 속성을 자식 클래스가 이어받을 수 있다는 것이다.

 

이렇게 되면 한 번 작성한 클래스를 활용할 수 있어 효율적이고 개발 시간을 줄일 수 있다.

 

더불어 인터페이스란 상수 필드를 가지거나 메소드가 모두 추상 메소드인 것이다.

 

이는 추상 클래스와 유사하지만, 각자의 용도가 다르다.

두 가지 모두 추상 메소드를 가지고 있기 때문에 이를 반드시 구현해야 하기 때문에 '하는 일' 자체는 비슷해 보일 수 있다.

 

다만 추상 클래스는 해당되는 추상 클래스의 기능을 이어받아 그 기능을 사용하고 확장하는 것이 목적이다.

 

반면에 인터페이스는 껍데기와 같다.

인터페이스는 인터페이스를 통해 생성된 객체가 어떤 것을 해야하는지를 적어둔 것이다.

 

이는 해당 인터페이스를 구현한 객체들에 대해서 동일한 동작을 약속하여 같은 동작을 보장할 수 있다.

이를 통해 소스코드를 수정하지 않고 사용하는 객체를 변경하여 결합력을 낮출 수 있는 장점을 가지게 된다.

 

 

이렇게 명확히 다른 존재 이유를 가지면서도 서로 겹쳐져 보이는 것은 자바가 다중 상속을 지원하지 않는 것 때문일 수 있다.

 

자바에서는 extends로 여러개의 super 클래스를 상속받는 것을 지원하지 않는다.

이는 super 클래스에서 동일한 메소드를 가지고 있을때, 어떤 메소드를 실행해야 하는지에 대해 모호함이 있기 때문이다.

 

반면에 인터페이스는 여러개를 구현하는 것이 가능한데,

이는 다중 상속의 문제를 해결하기 위한 것이 아니라,  단지 해당 객체가 여러 인터페이스를 구현해야 할 필요가 있었을 뿐일 것이다.

 

 

 

 

 

 

댓글