요약. 

  • 먼저 책임이 다른 코드를 분리해서 두 개의 클래스로 만들었다.(관심사의분리-SoC, 리팩토링)
  • 그중에서 바뀔 수 있는 쪽의 클래스는 인터페이스를 구현하도록 하고, 다른 클래스에서 인터페이스를 통해서만 접근하도록 만들었다. 이렇게 해서 인터페이스를 정의한 쪽의 구현 방법이 달라져 클래스가 바뀌더라도, 그 기능을 사용하는 클래스의 코드는 같이 수정할 필요가 없도록 만들었다.(전략 패턴)
  • 이를 통해 자신의 책임 자체가 변경되는 경우 외에는 불필요한 변화가 발생하지 않도록 막아주고, 자신이 사용하는 외부 오브젝트 기능은 자유롭게 확장하거나 변경할 수 있게 만들었다.(개방 폐쇄 원칙)
  • 결국 한쪽의 기능변화가 다른 쪽의 변경을 요구하지 않아도 되게 했고(낮은결합도), 자신의 책임과 관심사에만 순수하게 집중하는(높은 응집도) 깔끔한 코드를 만들 수 있었다.
  • 오브젝트가 생성되고 여타 오브젝트와 관계를 맺는 작업의 제어권을 별도의 오브젝트 팩토리를 만들어 넘겼다. 또는 오브젝트 팩토리의 기능을 일반화한 IoC 컨테이너로 넘겨서 오브젝트가 자신이 사용할 대상의 생성이나 선택에 관한 책임으로부터 자유롭게 마들어줬다(제어의역전-IoC)
  • 전통적인 싱글톤 패턴 구현 방식의 단점을 살펴보고, 서버에서 사용되는 서비스 오브젝트로서의 장점을 살릴 수 있는 싱글톤을 사용하면서도 싱글톤 패턴의 단점을 극복할 수 있도록 설계된 컨테이너를 활용하는 방법에 대해 알아봤다(싱글톤 레지스트리)
  • 설계 시점과 코드에는 클래스와 인터페이스 사이의 느슨한 의존관계만 만들어놓고, 런타임 시에 실제 사용할구체적인 의존 오브젝트를 제3자(DI컨테이너)의 도움으로 주입받아서 다이내믹한 의존관계를 갖게 해주는  IoC의 특별한 케이스를 알아봤다.(의존관계 주입-DI)
  • 의존오브젝트를 주입할 때 생성자를 이용하는 방법과 수정자 메소드를 이용하는 방법을 알아봤다(생성자 주입과 수정자 주입)
  • 마지막으로, XML을 이용해 DI 설정정보를 만드는 방법과 의존 오브젝트가 아닌 일반 값을 외부에서 설정하게 런타임 시에 주입하는 방법을 알아봤다.(XML 설정)

Step.1 의존관계 분리 방법 ~ p.97

  • 상속을 사용한 템플릿 메소드 패턴(Template method pattern)
    • 슈퍼클래스에 기본적인 로직의 흐름을 만들고, 그 기능의 일부를 추상 메소드나 오버라이딩이 가능한 protected 메소드 등으로 만든 뒤 서브클래스에서 이런 메소드를 필요에 맞게 구현해서 사용하도록 하는 방법
    • 상속을 통해 슈퍼클래스의 기능을 확장할 때 사용하는 가장 대표적인 방법이다. 변하지 않는 기능은 슈퍼클래스어 만들어두고 자주 변경되며 확장할 기능은 서브클래스에서 만들도록 한다.
    • 슈퍼클래스에서 디폴트 기능을 정의해두거나 비워뒀다가 서브클래스에서 선택적으로 오버라이드할 수 있도록 만들어둔 메소드를 훅(hook) 메소드라고 한다. 서브클래스에서는 추상 메소드를 구현하거나, 훅 메소드를 오버라이드하는 방법을 이용해 기능의 일부를 확장한다.
  • 팩토리 메소드 패턴(Factory method pattern) 
    • 서브클래스에서 "구체적인 오브젝트 생성 방법을 결정하게 하는 것"
    • 템플릿 메소드 패턴과 구조가 흡사, 슈퍼클래스 코드에서는 서브클래스에서 구현할 메소드를 호출해서 필요한 타입의 오브젝트를 가져와 사용한다.
    • 주로 인터페이스 타입으로 오브젝트를 리턴, 슈퍼클래스에서는 오브젝트 구조를 알지 못한다.
  • 템플릿 메소드 패턴과 팩토리 메소드 패턴의 차이 
    • 템플릿 메소드 패턴 :: 제어의 권한 슈퍼클래스, 추상 메소드로 구현
    • 팩토리 메소드 패턴 :: 제어의 권한 서브클래스, interface로 구현
  • 개방 폐쇄 원칙(OCP, Open-Closed Principle) - 클래스나 모듈은 확장에는 열려있어야하고 변경에는 닫혀있어야 한다. ( SOLID 5대 원칙 중 하나)
  • 전략 패턴(Strategy Pattern)
    • 자신의 기능 맥락(context)에서, 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔서 사용할 수 있게 하는 디자인 패턴이다. 
      독립적인 책임으로 분리가 가능한 기능을 뜻한다.
  • 오브젝트 팩토리 - 객체의 생성 방법을 결정하고 그렇게 만들어진 오브젝트를 돌려주는 역할

※ 팩토리 메소드 패턴으로 제어의 역전 관계를 설명하고 오브젝트 팩토리에 제어의 역할 전달하여 IoC 관계를 설명
  전략 패턴 및 개방 폐쇄 원칙의 설명으로 IoC에서 유지되어야 할 중요 사항들을 설명

Step.2 스프링의 IoC(Inversion of Control) ~ p.102

스프링의 핵심을 담당하는 건 어플리케이션 컨텍스트(Application Context)
 - 어플리케이션에서 IoC(제어의 역전)를 적용해서 관리할 모든 오브젝트에 대한 생성과 관계설정을 담당. 어플리케이션 컨텍스트에는 오브젝트를 생성하고 관계를 맺어주는 코드가 없고, 그런 생성정보와 연관관계 정보를 별도의 설정정보를 통해서 얻는다. 이를 통해 낮은 결합도 유지

  • 어플리케이션 컨텍스트는 빈팩토리(Bean Factory)를 상속
    어플리케이션 컨텍스트는 별도의 정보를 참고해서 빈(오브젝트)의 생성, 관계설정 등의 제어작업을 총괄한다. (오브젝트 팩토리 역할) 
  • Application Context 설정 방법 ::
          ApplicationContext context = new AnnotaionConfigApplicationContext(DaoFactory.class);
          UserDao dao = context.getBean("userDao", UserDao.Class);
    • getBean 메소드는 오브젝트를 요청하는 메소드, ApplicationContext에 등록된 빈의 이름으로 오브젝트 호출
  • Application Context 동작 방식 ::
    • @Configuration 설정 정보 등록
    • @Bean이 붙은 메소드의 이름을 가져와 빈 목록 생성
    • 클라이언트가 getBean 메소드 호출 시 빈 목록에서 요청한 빈 검색 후 해당 오브젝트 생성, 전달
  • Application Context 장점 ::
    • 클라이언트는 구체적인 팩토리 클래스를 알 필요가 없다.
       - 어플리케이션 컨텍스트를 이용하여 일관된 방식으로 원하는 오브젝트를 가져올 수 있다.
    • 종합 IoC 서비스를 제공해준다.
      - 오브젝트가 생성되는 방식, 시점과 전략을 다르게 가져갈수도 있고, 부가적으로 자동생성, 후처리, 설정방식 다변화,인터셉팅 등 다양한 기능 제공
    • 빈을 검색하는 다양한 방법을 제공
      - getBean 이외에도 타입만으로 빈을 검색하거나 특별한 어노테이션 설정이 되어 있는 빈을 찾을 수도 있다.

 

Step.3 싱글톤 레지스트리와 오브젝트 스코프 ~ p.111

  • 싱글톤 패턴(Singleton Pattern)
    • 어떤 클래스를 어플리케이션 내에서 제한된 인스턴스 개수, 이름처럼 주로 하나만 존재하도록 강제하는 패턴, 이렇게 하나만 만들어지는 클래스의 오브젝트는 어플리케이션 내에서 전역적으로 접근이 가능하다. 단일 오브젝트만 존재해야하고, 이를 어플리케이션의 여러곳에서 공유하는 경우에 주로 사용한다.
    • 구현 방법 ::
      • 클래스 밖에서는 오브젝트를 생성하지 못하도록 생성자를 private로 만든다. 
      • 생성된 싱글톤 오브젝트를 저장할 수 있는 자신과 같은 타입의 스태틱 필드를 정의한다.
      • 스태틱 팩토리 메소드인 getInstance()를 만들고 이 메소드가 최초로 호출되는 시점에서 한번만 오브젝트가 만들어지게 한다. 생성된 오브젝트는 스태틱 필드에 저장된다.
      • 한번 오브젝트(싱글톤)가 만들어지고 난 후에는 getInstance() 메소드를 통해 이미 만들어져있는 스태틱 필드의 오브젝트를 리턴한다.
    • 싱글톤 패턴의 문제점 ::
      • private 생성자를 갖고 있기 때문에 상속할 수 없다. 상속과 이를 이용한 다형성을 적용할 수 없다.
      • 싱글톤은 테스트가 힘들다.
        만들어지는 방식이 제한적이므로 테스트에 사용되는 목 오브젝트 등으로 대체하기 힘들다.
      • 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다.
        서버 구성에 따라 싱글톤 클래스임에도 서버에 따라 동일한 오브젝트를 각각 생성될수도 있다.
      • 싱글톤의 사용은 전역상태를 만들 수 있기 때문에 바람직하지 못하다.
        싱글톤은 사용하는 클라이언트가 정해져 있지 않다. 여러 클라이언트가 하나의 싱글톤을 공유하기때문에 전역상태로 사용이 되어 데이터가 뒤섞일 수 있다.
  • 싱글톤 레지스트리(Singleton registry)
    • 싱글톤 패턴을 사용함으로써 발생되는 문제점들을 보완하기 위해 스프링 프레임워크에서 직접 싱글톤을 생성, 관리 해주는 기능
    • 제어권을 컨테이너에 넘기고(IoC) 컨테이너가 싱글톤 오브젝트를 생성, 관리 하므로 일반적인 자바 소스(public) 임에도 싱글톤으로 사용할 수 있다. 이로인해 싱글톤 패턴과 달리 스프링이 지지하는 객체지향적인 설계 방식과 원칙, 디자인 패턴 등을 적용하는 데 아무런 제약이 없다.
    • 주의점 :: 
      • 싱글톤 오브젝트는 멀티스레드 환경에서 동시에 접근이 가능하므로 상태정보를 내부에 갖고 있지 않은 무상태(stateless) 방식으로 만들어져야 한다.
      • 스프링의 싱글톤 빈으로 사용되는 클래스를 만들때는 개별적으로 바뀌는 정보는 로컬 변수로 정의하거나, 파라미터로 주고 받으면서 사용하게 해야한다.
      • 이외 읽기 전용 정보이거나 자신이 사용하는 다른 싱글톤 빈을 저장하려는 용도라면 인스턴스 변수를 사용해도 된다.
    • 스프링 빈의 스코프(scope)
      • 스프링 빈의 스코프는 default 싱글톤이다. 컨테이너 내에 한개의 오브젝트만 만들어져서, 강제로 제거하지 않는 한 스프링 컨테이너가 존재하는 동안 계속 유지된다.
      • 경우에 따라서는 변경이 가능하다. 
        • 프로토타입 스코프(prototype scope) - 빈을 요청할 때마다 매번 새로운 오브젝트를 만들어준다.
        • 요청 스코프(request scope) - 새로운 HTTP 요청이 생길때마다 오브젝트를 새로 생성한다.
        • 세션 스코프(session scope) - 웹의 세션과 유사하다.

Step.4 의존관계 주입(Dependency Injection) ~ p.128

기존 서블릿 등에서 사용된 IoC의 개념을 기초로 Spring Framework의 오브젝트를 구현했지만 기존의 IoC라는 단어의 설명으로는 Spring의 컨테이너 동작 원리의 상세 설명이 부족한 부분이 있다. 그래서 새로운 단어인 의존관계 주입(Dependency Injection - DI)를 사용한다. 

  • 의존관계란?
    - 두개의 클래스 또는 모듈이 의존관계에 있다고 말할때 항상 방향성이 존재한다. 
    - DI의 장점 :: 관심사의 분리(SoC)를 통해 얻어지는 높은 응집도에서 비롯된다. 개방 폐쇄 원칙(OCP)를 기초로 개발된 소스라면 특정 기능의 오브젝트를 언제든지, 어디든지 연결했다 제외해도 앞 뒤의 오브젝트에 영향이 가지 않는다는 것이다.
  • 설계 시점에 구성되는 의존관계, A에서 B에 정의된 메소드를 호출하는 경우, 사용에 대한 의존관계라 칭한다.
    런타임 시에 오브젝트 사이에서 만들어지는 의존관계, 실제 개발자의 경우에는 인지하고 있겠지만 소스상으로는 연결이 되어 있지 않은 소스가 구동될때 실제 연결이 되는 의존관계를 런타임 의존관계 또는 오브젝트 의존관계라 한다.
  • 의존관계 주입(Dependency Injection - DI)
    - 의존관계 주입(DI)은 구체적인 의존 오브젝트와 그것을 사용할 주체, 클라이언트 오브젝트를 런타임 시에 연결해주는 작업을 지칭한다.
    • 의존관계 주입의 원칙
      • 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다.
      • 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제 3의 존재가 결정한다.
      • 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공(주입)해줌으로써 만들어진다.
    • 자바에서 주입이란?
      - 메소드를 실행하면서 파라미터로 오브젝트의 레퍼런스를 전달해주는 방법
      - 주입 방법은 의존관계를 주입하는 시점과 방법이 달라졌을 뿐 결과는 동일하다.
      • 생성자를 통한 주입
      • 수정자 메소드를 이용한 주입
        - 하나의 파리미터를 기초로 생성(setter)
        - 외부로부터 제공받은 오브젝트 레퍼런스를 저장해뒀다가 내부의 메소드에서 사용하게 하는 DI방식에서 활용하기에 적당하다.
      • 일반 메소드를 이용한 주입
        - custom형식으로 여러개의 파리미터를 전달받아 처리 가능, 너무 다양한 종류의 파라미터를 한번에 추가시 높은 응집도가 깨져 불편한 소스로 변질될 가능성이 있음
        - 임의의 초기화 메소드를 이용하는 DI는 적절한 개수의 파라미터를 가진 여러 개의 초기화 메소드를 만들 수도 있기 때문에 한 번에 모든 필요한 파라미터를 다 받아야하는 생성자보다 낫다.
  • 의존관계 검색(Dependency Lookup - DL)
    - 코드에서는 구체적인 클래스에 의존하지 않고, 런타임 시에 의존관계를 결정한다는 점에서 의존관계 주입과 비슷하지만, 의존관계를 맺는 방법이 외부로부터의 주입이 아니라 능동적으로 검색을 이용한다.
    • 런타임 시 의존관계를 맺을 오브젝트를 결정하는 것과 오브젝트의 생성작업은 외부 컨테이너에게 IoC로 맡기지만, 이를 가져올 떄는 메소드나 생성자를 통한 주입 대신 스스로 컨테이너에게 요청하는 방법을 사용한다.
      - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(XXX.class);
        this.connectionMaker = context.getBean("BeanName", XXX.class);
    • 대부분 의존관계 주입 방식을 사용, 특정 경우 검색 방식이 필요
      • 어플리케이션의 기동 시점에서 적어도 한 번은 의존관계 검색 방식을 사용해 오브젝트를 가져와야한다.
      • 서버에서 사용자의 요청을 받을때 서블릿에서 스프링 컨테이너에 담긴 오브젝트를 사용하려면 한 번은 의존관계 검색을 통해 오브젝트를 가져와야한다. 이경우 스프링에서 기본으로 제공되기에 직접 구현은 필요가 없다.
    • 의존관계 주입과 검색의 중요 차이점
      • 의존관계 검색 방식에서는 검색하는 오브젝트는 자신이 스프링의 빈일 필요는 없다.  

Step.5 XML을 이용한 설정 ~ p.142

스프링은 자바 클래스를 이용하는 것 외에도, 다양한 방법을 통해 DI 의존관계 설정정보를 만들 수 있다. 가장 대표적인 것이 바로 XML이다.

  • XML의 장점
    - 단순한 텍스 파일이기 때문에 다루기가 쉽다.
    - 한눈에 이해하기 쉬운 구조로 작성된다. 별도의 빌드 작업이 없다는 것도 장점이다.
    - 스키마나 DTD를 이용해 정해진 포맷을  따라 작성됐는지 손쉽게 확인이 가능하다.
  •  하나의 @Bean 메소드를 통해 얻을 수 있는 빈 DI 정보는 다음 세 가지 이다.
    - 빈의 이름 :: @Bean 메소드 이름이 빈의 이름이다. 이 이름은 getBean()에서 사용된다.
    - 빈의 클래스 :: 빈 오브젝트를 어떤 클래스를 이용해서 만들지 정의한다.
    - 빈의 의존 오브젝트 :: 빈의 생성자나 수정자 메소드를 통해 의존 오브젝트를 넣어준다.
    의존 오브젝트도 하나의 빈이므로 이름이 있을 것이고, 그 이름에 해당하는 메소드를 호출해서 의존 오브젝트를 가져온다. 
  • 수정자 메소드를 사용해 의존관계를 주입해주는 경우
    - 수정자 메소드는 프로퍼티가 된다. 프로퍼티 이름은 메소드 이름에서 set을 제외한 나머지 부분을 사용한다.
    - <property> 태그는 name과 ref라는 두 개의 애트리뷰트를 갖는다.
    • name :: 프로퍼티의 이름이다. 이 프로퍼티 이름으로 수정자 메소드를 알 수 있다.
    • ref :: 수정자 메소드를 통해 주입해줄 오브젝트의 빈 이름이다.
    • ex) <property name="connectionMaker" ref="connectionMaker" />
  • DTD와 스키마
    XML문서는 미리 정해진 구조를 따라서 장성됐는지 검사할 수 있다. XML 문서 구조를 정의하는 방법은 DTD와 스키마(schema)가 있다.
    • DTD :: 사용할 beans 앞에 작성 <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
    • schema :: 스프링은 beans / bean 외에도 별도의 태그를 사용할 수 있는 방법을 제공한다. 이 사용법은 스키마 파일에 정의되어 있고 따라서 이런 태그를 사용하려면 DTD 대신 네임스페이스가 지원되는 스키마를 사용해야한다. <beans> 태그를 기본 네임스페이스로 하는 스키마 선언은 다음과 같다.
      <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/benas/spring-beans-3.0.xsd">
  • GenericXmlApplicationContext를 이용 XML 파일로 applicationContext 생성
    • ApplicationContext context = new GenericXmlApplicationContext( "applicationContext.xml");
    • 이외에도 ClassPathXmlApplicationContext를 이용, XML 설정정보를 가져오게 할 수 있다.
      - 이는 XML파일을 클래스패스에서 가져올 때 사용할 수 있는 기능으로 추가 된 것이다.
      - new ClassPathXmlApplicationContext("daoContext.xml",UserDao.class);
    • 파라미터로 전달받은 UserDao의 위치로부터 상대적으로 지정할 수 있는 기능이다.
  • Spring Bean이 아닌 class를 bean에 참조해야 하는 경우
    • 외부의 라이브러리를 사용하는 경우 Spring bean으로 String 값만이 아닌 등록되지 않은 클래스등을 파라미터로 Bean에 전달해야 되는 경우가 발생한다.  property의 ref 대신 value를 사용한다. 
    • 스프링은 value에 지정한 텍스트 값을 적절한 자바 타입으로 변환해준다. Integer, Double, String 과 같은 기본타입은 물론 Class,URL, File,Charset 같은 오브젝트로 변환도 가능하다. 또한 값이 여러개라면  List, Map같은 배열 타입으로도 값의 주입이 가능하다.

[우분투 My-SQL 설치]

 apt-get으로 설치

  1. mysql 설치 - sudo apt-get install mysql-server
  2. mysql 로그인 - mysql -u root [-h ip] [-P port] -p 
  3. db 선택 - use mysql
  4. 권한 부여
    - GRANT ALL PRIVILEGES ON *.* to 'root'@'%' IDENTIFIED BY 'password';
  5. 갱신 - flush privileges
  6. my.cnf 설정파일 변경
    • sudo nano /etc/mysql/my.cnf
    • mysqld 내 port 변경, bind-address 주석처리
      bind-address는 해당 ip로만 db서버에 접근이 가능하도록 제한하는 기능
    • DB 서버 한글 설정( [mysqld] 하단에 추가 ) - character-set-server=utf8

[우분투 SSH 설치]

 apt-get으로 설치

  1. SSH 설치 확인
    • dpkg -l | grep ssh
    • 검색 결과중 openssh-server가 없다면 apt-get을 통해 설치
  2. SSH 설치 - sudo apt-get install openssh-server
  3. 서버 확인(기본포트 22) netstat -ntl
  4. 포트 변경(선택)
    1. sudo vi /etc/ssh/sshd_config

[우분투 방화벽 설정]

UFW 설정

 - ufw는 관리자 계정만 사용가능 sudo -s로 권한 획득 필요

  • 설정 확인
    • ufw status [numbered/verbose]
    • numbered - index 번호 출력
    • verbose - ufw 설정확인
  • 방화벽 사용/미사용
    • ufw [enable/disable]
  • 포트 허가/제한 설정
    • ufw [allow/deny] [port넘버] ex)ufw allow 3306/tcp
  • 포트 설정 삭제
    • ufw delete [number] -> ufw status numbered로 number 확인하여 삭제가능

 

 

[우분투 Jenkins 설치]

 apt-get으로 설치

 

 

 

 

+ Recent posts