스프링 기본 - 섹션1 객체 지향 설계와 스프링
CS/김영한 스프링 강의

스프링 기본 - 섹션1 객체 지향 설계와 스프링

먼 옛날 EJB라는 현재의 스프링과 같은 기능을 했지만 너무 복잡하고 성능도 안나오는 지옥시절이 있었다.

이게 너무 불편해서 순수 자바로 돌아가서 다시 스프링 만들었다.

 

 

알맹이는 스프링 프레임워크. 여기 안에 모든 핵심 기술들 다 들어가 있는 거고 부트는 도와주는 역할(패키지 매니저, 서버 열어주기 등).

 

스프링이 왜 좋나면 객체지향의 강점을 최대로 이끌어 내는거고, 객체지향이 좋은 이유는 다형성(Polymorphism) 때문임.

흔히 예시로 드는 자동차인데 한 0.2초정도 아하 하고 이해한듯 하다가 다시 의문을 가지는 예시다.

객체지향이 왜 좋은지 모르겠다면, 반대로 안쓰고 함수만을 써서 한다고 생각해보자. 위 자동차 예시는 이제 핸들 위치, 페달 위치 그런게 interface로 함수 이름 등이 정해져 있는것이므로 운전자는 내부 구조를 몰라도 interface에 정의된 함수 이름만 그대로 쓰면 된다. 결과적으론 내부 구조가 바뀌어도 운전자는 뭐 딱히 하는게 없다.

하지만 객체 없이 함수로만 쓴다면? 물론 똑같은 이름의 함수로 정의하면 되지만, 인터페이스가 아니기 때문에 자칫하면 함수 이름이 멋대로 달라질 수도 있고 그럼 운전자도 새로 배워야 한다. 규칙을 정해서 함수이름을 이렇게 정의하라고 할 수도 있지만 자유로운 규칙은 불안하며 제약할 수 있는게 낫다. 객체지향에선 interface가 그 제약을 해주는 것.

 

 

 

위 내용을 한마디로 요약하면 클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.

 

 

스프링이 이것들을 정말 잘 해준다. 만약 스스로 만든다고 하면 각 클래스마다 new 로 인스턴스를 매번 만드는 실수를 할 수 있다. 하지만 스프링에서 입문때 배운것만 해도 DI(의존관계 주입)을 보면, config에서 정의하고 bean에 등록하기만 해도 알아서 싱글톤으로 만들어주고, 생성자에 정의만 해도 알아서 의존관계 주입해준다. 그래서 실수 할 일이 없고, 따로 어디서 또 만들고 할 필요 없이 초보도 고수도 안정적으로 사용하게 해주는 것이다.

 

 

여기까지 이해했으면 이제 좋은 객체 지향 설계의 5가지 원칙인 SOLID를 이해할 수 있다.

 

SRP: 단일 책임 원칙(single responsibility principle)

OCP: 개방-폐쇄 원칙(Open/closed principle)

LSP: 리스코프 치환 원칙(Liskov substitution priciple)

ISP: 인터페이스 분리 원칙(Interface segregation principle)

DIP: 의존관계 역전 원칙(Dependency inversion principle)

 

단일 책임 원칙은 하나의 클래스는 하나의 책임만 가져야 한다는 것. 유저 서비스를 바꾸는데 막 DB까지 건드려야 된다면 여러개의 책임을 지고 있으니 잘못된 거다. 뭐 작은거 하나 수정하는데 전혀 다른곳까지 고려해야 한다면 지옥이 시작된다.

 

개방-폐쇄 원칙은 누군가가 자신을 상속해서 확장시켜 사용하는 것에는 열려있어야 하지만, 자기 자신이 변경되는 것은 안된다. 즉, 앞에서 얘기한 다형성에 관련되어 있음.

근데 입문때 DB설정자를 다른걸로 바꾼다고 안에있는 내용을 막 바꿨다. 즉, 객체지향설계의 최대 장점인 다형성을 잘 살려서 했더니 오히려 자기 자신이 변경되어서 개방-폐쇄 원칙이 깨짐. 이런건 별도로 연결해주는 설정자가 필요하고, 스프링이 이걸 해준다. 그럼 코드상에선 해결됨

 

리스코프 치환 원칙은 상속할 때 기능이 상식에서 벗어도록 바꾸지 말것. 예를 들어 전진하는 코드인데 갑자기 후진으로 완전히 바꾼다던지. 하던 일을 계속 하게끔.

 

인터페이스 분리 원칙은 최대한 잘게 쪼개기. 그래야 대체 가능성이 높아진다.

 

의존관계 역전 원칙은, 자기 자신을 의존하는(DI) 클래스가 자기 자신의 메소드를 보지 않고 자기가 상속하는 인터페이스를 보고 함수를 사용해야 한다. 자신의 구현체를 보면서(자신의 클래스를 보고) 의존하게 되면 변경이 어려워진다. 내가 함수를 마음대로 못 바꿈.

근데 이것도 다형성을 지키면서 했을 때 구현 클래스를 직접 선택하기 때문에 위배됨.

 

결론은 다형성을 잘 지켜도 OCP, DIP를 지킬 수 없다. 이것들은 누군가가 해줘야 하고, 스프링이 해준다.

스프링으로 OCP, DIP를 가능하게 지원. DI 지원해줬었던게 그 예시임. 유저 서비스 클래스 안을 건드린게 아니라 설정 파일을 건드렸단 걸 기억해보자. 실무에선 추상화에만 의존하면 그것도 너무 번거로운 문제가 생기니 이건 경험의 영역임.