본문 바로가기

Spring

토비의 스프링 #1 오브젝트와 의존관계

1. 초난감 DAO (안좋은 코드란 무엇인가?)

  • 요구사항에 맞는 코드를 작성했다면 원하는 기능을 수행할 것이다. 그렇다면 이러한 코드가 좋은 코드라고 할 수 있을 것인가? No!
  • 당장에는 문제가 발생할 수도 있고 그렇지 않을 수도 있다. 하지만 미래에 코드의 개선이 필요할 때가 온다면? 어떤 코드가 개선이 쉽게 될 수 있을것인가?

2. 분리

  • 관심사의 분리 : 관심이 같은 것끼리는 하나의 객체 안으로 또는 친한 객체로 모이게 하고, 관심이 다른 것은 가능한 한 따로 떨어져서 서로 영향을 주지 않도록 분리하는 것. 모든 것을 뭉뜽그려서 한데 모으는 편이 처음엔 쉽고 편하다. 그런데 언젠가는 그 뭉쳐 있는 여러 종류의 관심사를 적절하게 구분하고 따로 분리하는 작업을 해줘야만 할 때가 온다. 관심사가 같은 것끼리 모으고 다른 것은 분리 해줌으로써 같은 관심에 효과적으로 집중할 수 있게 만들어주는 것이다.
  • 메소드 추출(extract method) : 공통의 기능을 담당하는 메소드로 중복된 코드를 뽑아내는 것을 리팩토링에서는 메소드 추출 기법이라고 부른다.
  • 리팩토링 : 기존의 코드를 외부의 동작방식에는 변화 없이 내부 구조를 변경해서 재구성하는 작업 또는 기술을 말한다.
  • 템플릿 메소드 패턴 : 슈퍼클래스에 기본적인 로직의 흐름을 만들고, 그 기능의 일부를 추상 메소드나 오버라이딩이 가능한 protected 메소드 등으로 만든 뒤 서브클래스에서 이런 메소드를 필요에 맞게 구현해서 사용하도록 하는 방법
  • 팩토리 메소드 패턴 : 서브클래스에서 구체적인 오브젝트 생성 방법을 결정하게 하는 것

3.확장

  • 인터페이스 : 어떤 일을 하겠다는 기능만 정의해놓은 것
    • 인터페이스로 틀을 만들고 해당 기능을 구현하는 클래스를 여러개를 만든다면 기능의 확장이 가능하다.
  • 책임 전가 : 클라이언트의 역할

객체지향 설계 원칙 (SOLID)

  • SRP(The Single Responsibility Principle): 단일 책임 원칙
  • OCP(The Open Closed Principle): 개방 폐쇄 원칙
    • 클래스나 모듈은 확장에는 열려 있어야 하고 변경에는 닫혀있어야 한다. 클래스는 기능을 확장하는데에 얼마든지 열려있어야 하지만 핵심 기능을 구현한 코드는 그런 변화에 영향을 받지 않고 유지할 수 있어야 한다는 원칙.
  • LSP(The Liskov Substitution Principle): 리스코프 치환 원칙
  • ISP(The Interface Segregation Principle): 인터페이스 분리 원칙
  • DIP(The Dependency Inversion Principle): 의존관계 역전 원칙

높은 응집도와 낮은 결합도

  • 응집도
    • 응집도가 높다는 건 하나의 모듈, 클래스가 하나의 책임 또는 관심사에만 집중되어 있다는 뜻이다.
    • 불필요하거나 직접 관련이 없는 외부의 관심과 책임이 얽혀 있지 않으며, 하나의 공통 관심사는 한 클래스에 모여있다.
    • 높은 응집도는 클래스 레벨뿐 아니라, 패키지, 컴포넌트, 모듈에 이르기까지 그 대상의 크기가 달라도 동일한 원리로 적용될 수 있다.
  • 결합도
    • 하나의 오브젝트가 변경이 일어날 때에 관계를 맺고 있는 다른 오브젝트에게 변화를 요구하는 정도이다.
    • 낮은 결합도란 결국, 하나의 변경이 발생할 때 마치 파문이 이는 것처럼 여타 모듈과 객체로 변경에 대한 요구가 전파되지 않는 상태를 말한다.
  • 전략패턴 : 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔서 사용할 수 있게 하는 디자인 패턴

4.제어의 역전(IOC)

  • 팩토리 : 객체의 생성 방법을 결정하고 그렇게 만들어진 오브젝트를 돌려주는 일을 하는 오브젝트
  • 일반적인 프로그램의 흐름 : 프로그램이 시작되는 지점에서 다음에 사용할 오브젝트를 결정하고, 결정한 오브젝트를 생성하고, 만들어진 오브젝트에 있는 메소드를 호출하고, 그 오브젝트 메소드 안에서 다음에 사용할 것을 결정하고 호출하는 식의 작업의 반복
  • 제어의 역전 : 오브젝트가 자신이 사용할 오브젝트를 스스로 선택하지 않는다. 다연히 생성하지도 않는다. 또 자신도 어떻게 만들어지고 어디서 사용되는지를 알 수 없다. 모든 제어 권한을 자신이 아닌 다른 대상에게 위임하기 때문이다. 프로그램 시작을 담당하는 main()과 같은 엔트리 포인트를 제외하면 모든 오브젝트는 이렇게 위임받은 제어 권한을 갖는 특별한 오브젝트에 의해 결정되고 만들어진다.

5. 스프링의 IOC

  • 빈 : 스프링이 IOC 방식으로 관리하는 오브젝트(관리되는 오브젝트), 스프링이 직접 그 생성과 제어를 담당하는 오브젝트
  • 빈 팩토리 : IoC를 담당하는 핵심 컨테이너, 빈을 등록하고, 생성하고, 조회하고 돌려주고, 그 외에 부가적인 빈을 관리하는 기능을 담당한다. 보통 빈 팩토리를 바로 사용하지 않고 이를 확장한 애플리케이션 컨텍스트를 이용한다.
  • 애플리케이션 컨텍스트(application context) :  빈 팩토리를 확장한 IoC 컨테이너다. 빈 팩토리라고 부를 때는 빈의 생성과 제어의 관점에서 이야기하는 것이고, 애플리케이션 컨텍스트라고 할 때는 스프링이 제공하는 애플리케이션 지원 기능을 모두 포함해서 이야기하는 것이라고 보면 된다.
  • 설정정보/ 설정 메타정보
  • 컨테이너 또는 IOC 컨테이너 : IoC 방식으로 빈을 관리한다는 의미에서 애플리케이션 컨텍스트나 빈 팩토리를 컨테이너 또는 IoC 컨테이너라고도 한다. 애플리케이션 컨텍스트 보다 좀더 추상적인 표현이다.
  • 어플리케이션 컨텍스트를 사용했을 때 얻을 수 있는 장점
    • 클라이언트는 구체적인 팩토리 클래스를 알 필요가 없다.
    • 애플리케이션 컨텍스트는 종합 IoC 서비스를 제공해준다.
    • 애플리케이션 컨텍스트는 빈을 검색하는 다양한 방법을 제공한다.

6.싱글톤 레지스트리와 오브젝트 스코프

  • 애플리케이션 컨텍스트는 우리가 만들었던 오브젝트 팩토리와 비슷한 방식으로 동작하는 IoC 컨테이너다. 그러면서 동시에 이 애플리케이션 컨텍스트는 싱글톤을 저장하고 관리하는 싱글톤 레지스트리이기도 하다. 스프링은 기본적으로 별다른 설정을 하지 않으면 내부에서 생성하는 빈 오브젝트를 모두 싱글톤으로 만든다.(디자인 패턴에서 나오는 싱글톤 패턴과 개념은 비슷하지만 구현 방법은 확연히 다름)
  • 왜 스프링은 싱글톤으로 빈을 만드는가? 매번 클라이언트에서 요청이 올 때마다 각 로직을 담당하는 오브젝트를 새로 만든다면 부하가 심해진다.
  • 싱글톤 레지스트리 : 자바의 기본적인 싱글톤 패턴의 구현 방식은 여러 가지 단점이 있기 때문에, 스프링은 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공한다.
  • 오브젝트 스코프 : 스프링이 관리하는 오브젝트, 즉 빈이 생성되고 존재하고 적용되는 범위, 스프링 빈의 기본 스코프는 싱글톤이다. 싱글톤 스코프는 컨테이너 내에 한 개의 오브젝트만 만들어져서 강제로 제거하지 않는 한 스프링 컨테이너가 존재하는 동안 계속 유지된다. (대부분의 빈은 싱글톤 스코프를 갖는다.)

7.의존관계 주입(DI)

  • 의존관계 : A가 B에 의존한다 -> B가 변하면 그것이 A에 영향을 미친다는 뜻(의존관계에는 방향성이 있다.)
  • 의존오브젝트 : 오브젝트가 만들어지고 나서 런타임 시에 의존관계를 맺는 대상, 즉 실제 사용대상인 오브젝트
  • 의존관계 주입 : 구체적인 의존 오브젝트와 그것을 사용할 주체, 보통 클라이언트라고 부르는 오브젝트를 런타임 시에 연결해주는 작업을 말한다.
  • 의존관계 주입 조건
    • 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. 그러기 위해서는 인터페이스에만 의존하고 있어야 한다.
    • 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제3의 존재가 결정한다.
    • 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공해줌으로써 만들어진다.

8.XML을 이용한 설정

<bean id="dataSource"

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi=""

xsi:schemaLocation="">

class="""

<property name="" vlaue=""/>

</bean>

<bean id="" clas="">

<property name="" ref=""/>

</bean>