1. 인터페이스 Predicate<T>

자바 8인 액션에서 람다표현식과 관련된 부분을 읽다가

함수형 인터페이스@FunctionalInterface 에는 메서드가 하나만 있어야 한다.

라고 제약이 있다는 이야기가 나왔다. 그런데 그 다음으로 andornegate을 포함하고 있다는 이야기가 나온다.

이게 어떻게 가능한거지??

이는 JDK8 에 제공되는 Predicate 인터페이스를 살펴보면 어느정도 이해가 된다.

/**
 * Represents a predicate (boolean-valued function) of one argument.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #test(Object)}.
 *
 * @param <T> the type of the input to the predicate
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Predicate<T> {
 
    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
 
    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * AND of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is {@code false}, then the {@code other}
     * predicate is not evaluated.
     *
     * <p>Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * {@code other} predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ANDed with this
     *              predicate
     * @return a composed predicate that represents the short-circuiting logical
     * AND of this predicate and the {@code other} predicate
     * @throws NullPointerException if other is null
     */
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
 
    /**
     * Returns a predicate that represents the logical negation of this
     * predicate.
     *
     * @return a predicate that represents the logical negation of this
     * predicate
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
 
    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * OR of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is {@code true}, then the {@code other}
     * predicate is not evaluated.
     *
     * <p>Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * {@code other} predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ORed with this
     *              predicate
     * @return a composed predicate that represents the short-circuiting logical
     * OR of this predicate and the {@code other} predicate
     * @throws NullPointerException if other is null
     */
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
 
    /**
     * Returns a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}.
     *
     * @param <T> the type of arguments to the predicate
     * @param targetRef the object reference with which to compare for equality,
     *               which may be {@code null}
     * @return a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

소스코드 상에서 andor과 negate 메서드에는 default 가 선언되어 있는 것을 확인할 수 있다. default 가 선언된 인터페이스의 메서드를디폴트메서드default method라고 부른다.

  • 디폴트 메서드란 무엇인가? 자바8에서 호환성을 유지하면서 API를 바꿀 수 있도록 추가한 새로운 기능이다. 이제 인터페이스는 자신을 구현하는 클래스에서 메서드를 구현하지 않을 수 있는 새로운 메서드 시그니처를 제공한다. 그럼 디폴트 메서드는 누가 구현할까? 인터페이스를 구현하는 클래스에서 구현하지 않은 메서드는 인터페이스 자체에서 기본으로 제공한다(그래서 디폴트 메서드라고 부른다).

인터페이스에 선언된 메서드는 클래스에서 구현하려할 때에는 반드시오버라이드Override 되어야 하는 대상이다. 그러나 default 선언된 메서드는 구현하지 않아도 된다.

public interface IncludeDefaultMethodInterface {
 
    int add(int aint b);
 
    default int max(int aint b) {
        return a > b ? a : b;
    }
}
 
//default int max 메서드는 오버라이드 하지 않았다. 
public class IncludeDefaultMethodInterfaceImpl implements IncludeDefaultMethodInterface {
 
    @Override
    public int add(int aint b) {
        return a + b;
    }
 
}
 
public class IncludeDefaultMethodInterfaceImplTest {
 
    @Test
    public void testAdd() throws Exception {
        // given 
        IncludeDefaultMethodInterfaceImpl interfaceImpl = new IncludeDefaultMethodInterfaceImpl();
        int a = 10;
        int b = 10;
 
        // when 
        int result = interfaceImpl.add(a, b);
 
        // then 
        assertThat(result, is(20));
    }
 
    @Test
    public void testMax() throws Exception {
        // given 
        IncludeDefaultMethodInterfaceImpl interfaceImpl = new IncludeDefaultMethodInterfaceImpl();
        int a = 10;
        int b = 15;
 
        // when: 구현하지 않았지만 로직이 동작한다. 
        int max = interfaceImpl.max(a, b);
 
        // then 
        assertThat(max, is(15));
    }
}

이와 같은 식으로 Predicate 인터페이스에는 andor과 negate 메서드가 디폴트 메서드로 구현되어 있기 때문에 개발자가 별도로 그 메서드들을 구현하지 않아도 함수인터페이스를 사용하면서 사용할 수 있는 것이다.

라고 정리하면 이해할 수 있을까??

2. 정리

그럼 함수형 인터페이스에 선언된 디폴트 메서드정적 메서드는 함수형 인터페이스의 메서드로 취급하지 않는것인가??

라고 물어보면 어떻게 대답할 수 있을까? 일단은 그렇다라고 봐야겠군. 람다표현식으로 전달받은 동작 파라미터를 구현할 때는 함수형 인터페이스에 선언된 메서드(디폴트 메서드나 정적메스드가 아닌 유일한 메서드)를 이용한다고 보면 되겠다.


스프링부트 1.3.0이 출시되었다.

1.3에서 추가된 부분들의 주요사항들을 살펴보면:

  • Developer Tools

    새롭게 추가된 spring-boot-devtools 모듈은 개발시 경험을 향상시키는데 초점을 두고있다. 모듈이 제공하는 기능은:

    • 민감한 속성 기본(예를 들어 템플릿 캐시를 비활성화)

    • 애플리케이션 자동 재시작

    • LiveReload 지원(살아있는 상태에서 다시 읽기…​?) 애플리케이션을 종료하지 않고도 변경사항을 다시 읽어오는 것이 가능해짐

    • 원격 개발 지원(HTTP 터널을 통한 원격 갱신과 원격 디버그 지원)

    • 재시작 동안 HTTP session 영속화

      여유가 된다면 DevTools 에 관한 짧은 소개영상을 보자.

  • Caching Auto-configuration

    EhCache, Hazelcast, Infinispan, JCache (JSR 107) implementations, Redis 과 Guava을 위한 자동설정을 제공한다. 추가적으로 인-메모리 캐시 기반의 간단한 Map도 지원한다.

  • Fully executable JARs and service support

    메이븐Maven과 그레들Gradle 플러그인을 이용해서 리눅스/유닉스에서 다음과 같은 형태로 실행할 수 있는 완벽한 실행가능한 아카이브를 생성할 수 있다.

    $ ./myapp.jar

    거기서 더 나아가, init.d 혹은 systemd 서비스로 동작한다. init.d 서비스로 설치할 때는 심볼릭만 생성하면 된다.

    $ sudo link -s /var/myapp/myapp.jar /etc/init.d/myapp
  • Color banners

    banner.txt 파일에 ANSI 칼라코드를 포함시킬 수 있다. 이런 미친 짓(?)도 가능하다.

    Meow
    Figure 1. color banner
  • Support for @WebServlet, @WebFilter and @WebListener annotations 내장 서블릿 컨테이너를 사용할 때,@ServletComponentScan을 사용하여 활성화시킨 경우 @WebServlet, @WebFilter  @WebListener 애노테이션을 사용한 클래스가 자동 등록된다.

  • Additional auto-configurations

    다음 항목들에 대한 자동설정을 제공한다. Cassandra OAuth2 Spring Session jOOQ SendGrid Artemis

  • Actuator Metrics

    측정metric 은 반출과 집계를 지원기능이 확장되었다. 추가적으로 자바8에 정의된 GaugeService CounterService 구현체(가능하다면 사용가능한)와 성능의 향상을 제공한다.

  • Update Endpoints and Health Indicators

    /logfile, /flyway  /liquibase 액츄에이터 엔드포인트를 포함하였고 엘라스틱서치, 이메일과 JMS health indicator를 지원한다.

  • Other changes

    다른 변경사항이나 향상된 기능들에 대해서는 릴리즈 노트를 살펴보라. 다음버전에서 삭제예정의 클래스와 메서드들도 찾아볼 수 있다.



쉽게 이해하면 좋을 스프링 프레임워크


스프링 프레임워크Spring Framework.

자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크
  • 애플리케이션 프레임워크

    애플리케이션 프레임워크는 특정 계층이나, 기술, 업무 분야에 국한되지 않고 애플리케이션의 전 영역을 포괄하는 범용적인 프레임워크를 말한다. 애플리케이션 프레임워크는 애플리케이션 개발의 전 과정을 빠르고 편리하며 효율적으로 진행하는데 일차적인 목표를 두는 프레임워크다.

  • 경량급

    불필요하게 무겁지 않다.

  • 자바 엔터프라이즈 개발을 편하게

    엔터프라이즈 개발의 근본적인 문제점에 도전해서 해결책을 제시한다는 것이 기존 기술의 접근방법과 스프링의 접근 방법의 차이다.

  • 오픈소스

    스프링은 오픈소스 프로젝트(https://github.com/spring-projects/spring-framework) 방식으로 개발중이다.


간단하다면 간단하지만 복잡하다면 한없이 복잡한 이 녀석을 어떻게 설명하는 것이 좋을지 고민이다.


1. 소개

1.1. 프레임워크란?

프레임워크Framework

사전적 의미: a hypothetical description of a complex entity or process 복잡한 엔티티 혹은 프로세스

우리가 말하는 프레임워크는 엔터프라이즈 개발의 복잡함을 해소하기 위해 사용하는 애플리케이션에 집중한다. 개발자에게 프레임워크란 맨손으로 개발하지 않을 수 있도록 제공되는 그 무엇이 될 것이다. 다수의 개발자가 함께 개발하는 환경이 되면서 소프트웨어는 점점 거대해졌다. 이 거대해진 소프트웨어를 구현하는 코드를 작성하는 방식은 같은 교육과정을 거친 개발자들이라고 해도 저마다 풀어가는 방식이 다를 수 있다. 그런 다양한 방식 속에서 일정한 형태를 가질 수 있도록 유도하는 것이 프레임워크가 가지고 있는 힘(혹은 강제력)이라고 할 수 있다.

프레임워크를 기반으로 한 개발은 일정한 개발형식을 띄게 된다.

이 형식은 아키텍트architect에 의해서 혹은 선임 개발자에 의해서 틀이 잡혀졌을수도 있고 관례Convention적으로 정의되었을 수도 있다. 애플리케이션 프레임워크는 일관된 개발을 지원하고, 프레임워크에 정의된 경계에 따라 설정을 강제하고 재사용가능하고 확장가능하고 단순한 형태를 유지하면서 유지관리성의 이익을 얻을 수 있다. 물론, 그래도 복잡하다.

1.2. 스프링 프레임워크

스프링 프레임워크는 2003년 로드존슨Road Johnson 이라는 유명한 개발자가 2003 년에 Expert One-on-One J2EE Design and Development라는 책을 출간하면서 자바 엔터프라이즈 개발에 관한 자신의 풍부한 경험을 바탕으로 J2EE 설계와 개발의 모든 영역에 대한 개발전략을 다룬 책이다.


항상 프레임워크 기반으로 접근하라.

이 책에 포함된 3만 라인 가량의 샘플 애플리케이션 예제에 포함된 프레임워크가 스프링 프레임워크의 기원이다. 이 책에서 주장하는 자바 엔터프라이즈 개발의 이상적인 프로그래밍 모델을 추구하는데 필요한 기반이 돼주는 코드, 즉 프레임워크가 지금 스프링의 원시 버전이라고 보면 된다.

스프링의 핵심이 POJO 프로그래밍이란는 사실은, 스프링의 핵심을 가장 잘 나타내고 알려진 스프링 삼각형을 통해서도 알 수 있다. 이 그림은 스프링소스의 CTO인 아드리안 콜리어가 스피링의 핵심개념을 설명하기 위해서 만들었다.

Spring POJO
Figure 1. Spring POJO

스프링 애플리케이션은 POJO를 이용해서 만든 애플리케이션 코드와, POJO가 어떻게 관계를 맺고 동작하는지를 정의해놓은 설계정보로 구분된다. DI(Dependency Injection)의 기본 아이디어는 유연하게 확장가능한 오브젝트를 만들어두고 그 관계는 외부에서 동적으로 설정해준다는 것이다. 이런 DI의 개념을 애플리케이션 전반에 걸쳐 적용하는 것이 스프링의 프로그래밍 모델이다. 스프링의 주요기술인 IoC/DI, AOP와 PSA(Portable Service Abstraction)는 애플리케이션을 POJO로 개발할 수 있게 해주는 가능기술enabling technology이라고 불린다.

  • POJO의 조건

    1. 특정규약에 종속되지 않는다.

      POJO는 자바 언어와 꼭 필요한 API 외에는 종속되지 않아야 한다. EJB와 같이 특정 규약을 따라 비즈니스 컴포넌트를 만들어야 하는 경우는 POJO가 아니다. 특정 클래스를 상속해서 만들어야 하는 규약이 있는 경우도 마찬가지다.

    2. 특정 환경에 종속되지 않는다.

      특정 환경에 종속적이어야만 동작하는 오브젝트도 POJO라고 할 수 없다. POJO는 환경에 독립적이어야 한다.

  • POJO의 장점

    1. 특정기술과 환경에 종속되지 않은 오브젝트는 그만큼 깔끔한 코드가 될 수 있다.

    2. POJO로 개발된 코드는 자동화된 테스트에 매우 유리하다.

    3. 객체지향적인 설계를 자유롭게 적용할 수 있다.

1.3. 스프링 프레임워크 기술

1.3.1. 제어역전(IoC)/의존관계주입(DI)

  • DI 활용방법

    1. 핵심기능의 변경

      DI의 가장 대표적인 적용방법은 의존 대상의 구현을 바꾸는 것이다. 디자인 패턴의 전략 패턴이 대표적인 예다. A → B 구조에서 A의 기능 일부를 B에게 위임한다고 했을 때 B의 구현 방식을 필요에 따라 B1, B2, B3로 변경하는 것이다.

    2. 핵심기능의 동적인 변경

      의존 오브젝트의 핵심기능 자체를 바꾸는 것이다. 하지만 일반적인 DI를 이용한 변경방법과는 달리, 동적으로 매번 다르게 변경할 수 있다. DI도 기본적으로는 런타임시에 동적으로 의존 오브젝트를 연결해주는 것이긴 하지만, 일단 DI되고 나면 그 후로는 밖Nㅣ지 않는다. 즉, 동적인 방식으로 연결되지만 한번 DI되면 바뀌지 않는 정적인 관계를 맺어주는 것이다.

    3. 부가기능의 추가

      핵심기능은 그대로 둔 채로 부가기능을 추가하는 것이다. 데코레이터 패턴을 생각해보면 된다. 인터페이스를 두고 사용하게 하고, 실제 사용할 오브젝트는 외부에서 주입하는 DI를 적용해두면 데코레이터 패턴을 쉽게 적용할 수 있다.

    4. 인터페이스의 변경

      클라이언트가 사용하는 인터페이스와 실제 오브젝트 사이에 인터페이스가 일치하지 않는 경우에도 DI가 유용하다.

    5. 프록시

      프록시 패턴의 전형적인 응용 방법도 있다. 필요한 시점에서 실제 사용할 오브젝트를 초기화하고 리소르를 준비하게 해주는 지연된 로딩lazy loading을 적용하려면 프록시가 필요하다.

    6. 템플릿과 콜백

      템플릿/콜백 패턴은 DI의 특별한 적용방법이다. 반복적으로 등장하지만 항상 고정적인 작업 흐름과 그 사이에서 자주 바뀌는 부분을 분리해서 템플릿과 콜백으로 만들고 이를 DI 원리를 이용해서 자주 바뀌는 부분을 분리해서 템플릿과 콜백으로 만들고 이를 DI 원리를 응용해 적용하면서 지저분하게 매번 만들어야 하는 코드를 간결하게 만들 수 있다.

    7. 싱글톤과 오브젝트 스코프

      미가 필요한 중요한 이유 중 한 가지는 01 할 오브젝트의 생명주기를 제어할 수 있다는 것이다 0 1 를 프레임워크로 이용한다는 건 01 대상 오브젝트를 컨테이너가 관리한다는 의미다. 오브젝트의 생성부터 관계설정. 이용, 소멸 에 이 르기까지 의 모든 과정을 DI 컨테이너가 주관히-기 때문에 그 오브젝 트의 스코프를 자유롭게 제어할 수 있다.

    8. 테스트

      그래서 의존 오브젝트를 대선해서 스럽 또는 목 오브젝트 같은 테스트 대역을 활용해야 한다. 이때도 DI는 중요한 역할을 한다. 미 를 위해 만든 수정자 메소드를 사용하면 테스트 코드 안에서 수동으로 목 오브젝트를 주입할 수 있다. 또는 테스트용으로 설정을 별도로 만드는 방법도 있다 DI 없이는 이런 테 스트 기법을 적용하기란 불가능하다. 갈수록 테스트의 중요성이 커져가고 있으니 DI 의 활용 방법에서 테스트 가차지하는 비중도 커질 것이다.

1.3.2. 애스팩트 지향 프로그래밍(AOP, Aspect-Oriented Programming)

기능을 핵심 비지니스 로직과 공통 모듈로 구분하고, 핵심 로직에 영향을 미치지 않고 사이사이에 공통 모듈을 효과적으로 잘 끼워넣도록 하는 개발 방법이다.

보안 인증, 로깅 같은 요소등)을 만든 후에 코드 밖에서 이 모듈을 비지니스 로직에 삽입하는 것이 바로 AOP 적인 개발이 코드 밖에서 설정된다는 것이 핵심이다.

AOP가 사용되는 경우
  • 1) 간단한 메소드 성능 검사

    개발 도중 특히 DB에 다량의 데이터를 넣고 빼는 등의 배치 작업에 대하여 시간을 측정해보고 쿼리를 개선하는 작업은 매우 의미가 있다. 이 경우 매번 해당 메소드 처음과 끝에 System.currentTimeMills();를 사용하거나, 스프링이 제공하는 StopWatch코드를 사용하기는 매우 번거롭다. 이런 경우 해당 작업을 하는 코드를 밖에서 설정하고 해당 부분을 사용하는 편이 편리하다.

  • 2) 트랜잭션 처리

    트랜잭션의 경우 비지니스 로직의 전후에 설정된다. 하지만 매번 사용하는 트랜잭션 (try~catch부분)의 코드는 번거롭고, 소스를 더욱 복잡하게 보여준다.

  • 3) 예외 반환

    스프링에는 DataAccessException이라는 매우 잘 정의되어 있는 예외 계층 구조가 있다. 예전 하이버네이트 예외들은 몇 개 없었고 그나마도 Uncatched Exception이 아니였다. 이렇게 구조가 별로 안 좋은 예외들이 발생했을 때, 그걸 잡아서 잘 정의되어 있는 예외 계층 구조로 변환해서 다시 던지는 애스팩트는 제 3의 프레임워크를 사용할 때, 본인의 프레임워크나 애플리케이션에서 별도의 예외 계층 구조로 변환하고 싶을 때 유용하다.

  • 4) 아키텍처 검증

    • 하이버네티스와 JDBC를 같이 사용할 경우, DB 동기화 문제 해결

    • 멀티쓰레드 Safety 관련하여 작업해야 하는 경우, 메소드들에 일괄적으로 락을 설정하는 애스팩트

    • 데드락 등으로 인한 PessimisticLockingFailureException등의 예외를 만났을 때 재시도하는 애스팩트

    • 로깅, 인증, 권한 등

AOP의 구성요소
  • 조인포인트(joinPoint) - 횡단 관심 모듈의 기능이 삽입되어 동작할 수 있는 실행 가능한 특정위치

    ex) 메쏘드가 호출되는 부분 또는 리턴되는 시점, 필드를 액세스하는 부분, 인스턴스가 만들어지는 지점, 예외가 던져지는 시점, 예외 핸들러가 동작하는 위치, 클래스가 초기화되는 곳 등이 대표적인 조인포인트가 될 수 있다. 각각의 조인포인트들은 그 안에 횡단 관심의 기능이 AOP에 의해 자동으로 추가되어져서 동작할 수 있는 후보지가 되는 것이다.

  • 포인트컷(pointCut) - 어떤 클래스의 어느 조인포인트를 사용할 것인지를 결정하는 선택 기능

    AOP가 항상 모든 모듈의 모든 조인포인트를 사용할 것이 아니기 때문에 필요에 따라 사용해야 할 모듈의 특정 조인포인트를 지정할 필요가 있다. 일종의 조인포인트 선정 룰과 같은 개념이다. AOP에서는 포인트컷을 수행할 수 있는 다양한 접근 방법을 제공한다. AspectJ에서는 와일드카드를 이용한 메쏘드 시그니처를 사용한다.

  • 어드바이스(advise) 또는 인터셉터(intercepter)

    • 어드바이스 - 각 조인포인트에 삽입되어져 동작할 수 있는 코드

      주로 메소드 단위로 구성된 어드바이스는 포인트컷에 의해 결정된 모듈의 조인포인트에서 호출되어 사용된다. 일반적으로 독립적인 클래스 등으로 구현된 횡단 관심 모듈을 조인포인트의 정보를 참조해서 이용하는 방식으로 작성된다.

    • 인터셉터 - 인터셉터 체인 방식의 AOP 툴에서 사용하는 용어로 주로 한 개의 invoke 메소드를 가지는 어드바이스

    • 어드바이스(advise)의 종류

      • Before advice : 메서드 에 적용되는

      • After returning advice : 메서드가 정상적으로 실행된 후에 실행 (예외를 던지는 상황은 정상적인 상황에서 제외)

      • After throwing advice : 예외를 발생시킬 때 적용되는 Advice를 정의 (catch와 비슷)

      • Around advice : 메서드 호출 이전, 이후, 예외 발생 등 에서 적용 가능한 Advice를 정의

  • 위빙(weaving) 또는 크로스컷팅(crossCutting)

    위빙 - 포인트컷에 의해서 결정된 조인포인트에 지정된 어드바이스를 삽입하는 과정 (다른 말로 크로스컷팅 위빙은 AOP가 기존의 핵심 관심 모듈의 코드에 전혀 영향을 주지 않으면서 필요한 횡단 관심 기능을 추가할 수 있게 해주는 핵심적인 처리과정이다. 위빙을 처리하는 방법은 후처리기를 통한 코드생성 기술을 통한 방법부터 특별한 컴파일러 사용하는 것, 이미 생성된 클래스의 정적인 바이트코드의 변환 또는 실행 중 클래스로더를 통한 실시간 바이트코드 변환 그리고 다이내믹 프록시를 통한 방법까지 매우 다양하다.

  • 인트로덕션(Introduction) 또는 인터타입 선언

    인트로덕션 - 정적인 방식의 AOP 기술 동적인 AOP 방식을 사용하면 코드의 조인포인트에 어드바이스를 적용해서 핵심관심 코드의 동작 방식을 변경할 수 있다. 인트로덕션은 이에 반해서 기존의 클래스와 인터페이스에 필요한 메소드나 필드를 추가해서 사용할 수 있게 해주는 방법 OOP에서 말하는 오브젝트의 상속이나 확장과는 다른 방식으로 어드바이스 또는 애스팩트를 이용해서 기존 클래스에 없는 인터페이스 등을 다이내믹하게 구현해 줄 수 있다.

  • 애스팩트(aspect) 또는 어드바이저 에스팩트 - 포인트컷(어디에서) + 어드바이스(무엇을 할 것인지) + (필요에 따라 인트로덕션도 포함) AspectJ와 같은 자바 언어를 확장한 AOP에서는 마치 자바의 클래스처럼 애스팩트를 코드로 작성할 수 있다. AOP 툴의 종류에 따라서 어드바이스와 포인트컷을 각각 일반 자바 클래스로 작성하고 이를 결합한 어드바이저 클래스를 만들어서 사용하는 방법도 있다.

  • AOP 적용기법

    1. 스프링과 같이 다이내밍 프록시를 사용하는 방법

    2. 자바 언어의 한계를 넘어서는 언어의 확장을 이용하는 방법

  • AOP 적용단계

    • 1단계: 미리 준비된 AOP 이용

    • 2단계: 전담팀을 통한 AOP 적용

    • 3단계: AOP의 자유로운 이용

1.3.3. PSA(Portable Service Abstraction)

환경과 세부 기술의 변화에 관계없이 일괄된 방식으로 기술에 접근할 수 있게 해준다. POJO로 개발된 코드는 특정 환경이나 구현 방식에 종속적이지 않아야 한다. 특정 환경과 기술에 종속적이지 않다는 게 특정 기술을 사용하지 않는다는 뜻은 아니다. 다만 POJO 코드가 그런 기술에 직접 노출되어 만들어지지 않는다는 말이다. 이를 위해 스프링이 제공하는 대표적인 기술이 바로 일관성 있는 서비스 추상화 기술이다.

1.4. 스프링 프레임워크 살펴보기

spring overview.png
Figure 2. Overview of Spring Framework

스프링 프레임워크(Overview modules)는 위와 같은 형태로 점점 세분화되고 모듈화되고 있다. 그만큼 살펴봐야할 것도 많고 익혀야할 개념도 많다. 스프링 프레임워크가 익숙해지게 되면 스프링 기반으로 하여 제공되는 다양한 모듈들을 추가하고 모듈의 기능을 활용하는 것이 익숙해지게 된다. 스프링 프레임워크 사용이 익숙해지면 필요한 모듈을 추가하고 그 기능을 활용하는 것이 쉬워진다. 스프링 프레임워크 기반의 개발경험을 다른 모듈에도 반영할 수 있기 때문이다. 하지만 이건.. 아직 먼 이야기.

1.4.1. 스프링 모듈 소개

Core Container

Core container spring-core, spring-beans, spring-context, spring-context-support, 그리고 spring-expression(Spring Expression Language) 모듈로 구성되어 있다.

  • spring-core, spring-beans 모듈은 프레임워크의 기초적인 부분들(제어역전과 의존성 주입 기능) 을 제공한다.BeanFactory는 팩토리 패턴의 수준 높은 구현체다. 프로그래밍적인 요구에 따라 싱글톤을 제거하고 실질적인 프로그램 로직에 따라 설정과 의존성 정의를 분리할 수 있다(뭔소리지?!).

  • Context (spring-context) 는 Core and Beans의해 제공되는 기초를 조직한다. JNDI 레지스트리와 유사한 형태의 프레임워크 형식으로 객체에 접근한다. 컨텍스트 모듈은 빈Beans 모듈로 부터 기능을 유전받고 국제화 지원을 추가하고, 이벤트 처리, 자원 적재, 그리고 서블릿 컨테이너 컨텍스트 등을 생성한다. 컨텍스트 모듈은 EJB, JMX, 그리고 기본적인 원격처리와 관련된 Java EE 기능을 지원한다. ApplicatoinContext 인터페이스는 컨텍스트 모듈에서 중요한 지점이다. spring-context-support는 스프링 애플리케이션 컨텍스트의 공통 서드파티 라이브러리들에 관한 통합을 지원한다(캐시, 메일링, 스케줄링, 템플릿 엔진).

  • spring-expression 모듈은 실행시 쿼리 및 객체 그래프 유지에 필요한 표현식 언어를 제공한다.JSP 2.1 스펙에서 정의된 공통 표현식 언어를 확장했다.

AOP and Instrumentation

spring-aop 모듈은 AOP 관점지향 프로그래밍 구현을 제공한다. 메서드 인터셉터 그리고 포인트컷 코드와 구현된 기능을 깔끔히 분리한다.

  • spring-aspect 모듈은 AspectJ 통합기능을 제공한다.

  • spring-instrument 모듈은 클래스 계측제어 지원와 애플리케이션 서버에 포함된 클래스로더 구현체 지원을 제공한다.spring-instrument-tomcat 모듈은 톰캣을 위한 스프링의 계측제어 에이전트를 포함한다.

Messaging

스프링 프레임워크 4에 포함된 spring-messaging모듈은 스프링 통합Spring Integration Message, MessageChannel,MessageHandler로부터 추상화를 제공하고, 메시기 기반 애플리케이션을 구축할 수 있도록 지원한다. 스프링 MVC 애노테이션을 기반한 프로그래밍 모델과 유사한 형태로 메시지를 메서드에 매핑할 수 있는 애노테이션을 포함하고 있다.

Data Access/Integration

Data Access/Integration 계층은 JDBC, ORM, OXM, JMS 그리고 Transaction 모듈로 구성되어 있다.

  • spring-jdbc 모듈은 JDBC-지루한 JDBC 코딩과 데이터베이스벤더에서 정의된 에러코드 처리와 관련된 줄일 수 있는 추상화 계층을 제공한다.

  • spring-tx 모듈은 특정 인터페이스를 구현하고 POJO를 위한 프로그램적이고 선언적인 트랜잭션을 관리한다.

  • spring-orm 모듈은 JPA, JDO그리고 Hibernate를 포함한 인기있는 객체-관계 매핑를 위한 통합계층을 제공한다.

  • spring-oxm 모듈은 JAXB, Castor, XMLBeans, JiBX 그리고 XStream 과 같은 Object/XML mapping을 지원하는 추상계층을 제공한다.

  • spring-jms 모듈(Java Messaging Service)은 메시징의 생산과 소비 기능을 포함한다. 스프링 프레임워크 4.1부터는spring-messaging에 통합되었다.

Web

웹 계층은 spring-web, spring-webmvc, spring-websocket 그리고 spring-webmvc-portlet 모듈로 구성되어 있다.

  • spring-web 모듈은 멀티파티 파일 업로드 기능과 서블릿 리스너를 사용한 IoC 컨테이너의 초기화와 웹지향 애플리케이션 컨텍스트 등 웹지향 통합 기능을 제공한다. HTTP client와 웹과 관련된 스프링의 원격지원 기능을 포함하고 있다.

  • spring-webmvc 모듈은 (Web-Servlet 모듈이라고 알려짐)은 스프링의 모델-뷰-컨트롤러(MVC)와 웹 애플리케이션을 위한 REST Web 서비스 구현체를 포함하고 있다. 스프링의 MVC 프레임워크는 도메인모델과 웹 폼의 깔끔한 분리를 제공하고 스프링 프레임워크의 다른 기능들을 모두 통합한다.

  • spring-webmvc-portlet 모듈은 spring-webmvc 모듈의 기능들의 복제와 포틀릿 환경에 사용하는 MVC 구현체를 제공한다.

Test

spring-test 모듈은 스프링 컴포넌트의 jUnit 혹은 TestNG와 관련된 유닛 테스트와 통합 테스트를 지원한다. 스프링 애플리케이션 컨텍스트의 적재와 컨텍스트에 대한 캐싱 처리를 제공하고, 코드에 관한 독립적인 목객체를 제공한다.

1.4.2. 스프링 사용 시나리오

overview full.png
Figure 3. Typical full-fledged Spring web application

스프링 프레임워크에서 제공하는 기능들을 모두 적용한 전형적인 스프링 웹 애플리케이션은 다음과 같은 기능(Usage Scenarios)들을 제공받을 수 있게 된다.

스프링 프레임워크 모듈은 org.springframework 라고 하는 그룹ID(GroupID)와 spring으로 시작하는 ArtifactID를 기반으로 구성된다. http://maven.apache.org/메이븐] 그레들과 같은 빌드툴을 기반으로한 의존성 관리를 처리하는데 용이하도록 하고 있다.


2. 스프링 프레임워크를 익혀야 하는 이유?

2.1. 많이 사용되니까

 우리는 스프링 프레임워크를 알고 사용해야할까요?

  • 현재 널리 사용되고 있는 애플리케이션 프레임워크다.

    스프링 프레임워크는 국내 자바계열 프로젝트에서 가장 널리 사용되고 있는 애플리케이션 프레임워크 다(전자정부프레임워크 포함). 과하다 싶을 만큼 사용되고 있는 스프링 이전에는 스트럿츠가 있었고 그 이전에는 EJB가 있었을 것이다(아마도?). 그리고 삼성SDS의 애니프레임anyframe이 있었고 LG CNS의 데브온DevOn이 있었다. 그 이외에도 셀수없을만큼 스프링 프레임워크를 깨작거려서 내놓은 애플리케이션 프레임워크가 있었다. 스프링 프레임워크가 오픈소스 였기에 소스가 공개되어 있고 오픈소스를 기반으로 하여 자기들만의 기능을 추가하거나 조금만 수정하는 것만으로도 자사의 프레임워크라고 이야기 하며 마케팅하던 때도 있었다. 스트럿츠와 스트럿츠2가 많이 사용되던 국내 엔터프라이즈 개발환경에 스프링이 빠르게 확산되어 갔다.

  • 국내의 많은 프로젝트에서 사용중이다.

    국내 공공기관쪽에서는 전자정부프레임워크 사용을 권장(or 강제?)하고 있고, 국내외 금융기관들은 아직까지는 자바를 기반으로 한 엔터프라이즈 개발환경을 선호하고 있다. 그 기반에는 대형 SI기업이었던 삼성SDS, LG CNS, SK C&C 등의 영향이 있다. 그들은 스프링 프레임워크를 기반으로 한 자사의 개발프레임워크를 기반으로 개발프로세스를 개발하고 프로젝트를 구축하는 가이드를 적용해왔다.

  • 자바기반에서는 이만한 녀석이 또 있을까?

    국내에서 자바 개발환경을 구축한 곳이면 스프링 프레임워크가 사용될 가능성이 90%는 넘는다. 오래된 시스템에서는 파스칼이나 EJB가 있긴 하겠지만 차세대 사업을 통해서 스프링프레임워크 기반으로 변경해나가고 있는 상황이다. 아직은 자바-스프링프레임워크-비즈니스로직 개발 조합을 깨뜨릴만한 상황은 벌어지지 않고 있다. 향후 10년간은 일자리 걱정도 딱히 하지 않아도 된다고 할까?

2.2. 왜 많이 쓰일까?

스프링이 널리 쓰이게 된 이유를 꼽아보자면,

  • 1.0이 나온 이래로 지속적으로 성능이 향상되고 필요한 기능들이 반영되어 업그레이드가 되고 있다.

  • 기본적인 웹기능구현을 비롯해서 메시징, 통합 등의 다양한 기능을 제공한다.

  • 배우기 쉬운 자바를 기반으로 하여 프로젝트를 진행하는데 필요한 인력을 수급하기에 무리가 없다.

    • 자바는 다른 언어에 비해서 배우고 사용하는데 부담이 적은 언어다. 물론 객체지향을 이해하고, 도메인의 개념을 이해하는데는 많은 시간이 필요하지만 어느정도 설계되어 있는 상황에서 기능을 구현하는데 큰 문제가 되지는 않는다.

  • 프레임워크에서 권장(제한)하는 처리방식에 의해서 많은 개발자가 협업하며 개발하고 유지보수하는데 무리가 없다.

  • 오픈소스이고

    • 깃헙에서 모든 소스코드를 열어보며 어떻게 동작하는지 살펴보고 결함이 있는 경우 이슈로 등록하고 수정을 요청할 수 있다.

  • 무료다(스프링 프레임워크를 적용하면서 컨설팅을 받고 문제가 발생했을 때 지원받을 수 있기는 하지만 대체적으로 자가해결을 한다)

국내에서는 전자정부프레임워크의 영향이 크다고 볼 수 있다. 대형SI에서 컨소시엄을 이뤄 공공기관에 적용되는 개발프레임워크를 만들어 비용을 줄이겠다는 목표를 가지고 진행하고 있는 프로젝트로서 자바를 기반으로 해서 이클립스-스프링프레임워크-각종 컴포넌트를 조합한 개발환경을 제공하고 필요에 따라서는 무료로 컨설팅과 이슈처리까지 지원해주고 있기 때문에 공공기관 SI 프로젝트를 진행하는 많은 기업에서 채용하고 있다.

이건 환경적인 영향이고,

자바를 기반으로 한 프레임워크 중에서 스프링만큼 잘 설계되고 확장가능한 프레임워크가 없다.


3. 애플리케이션 개발 기본 흐름

스프링프레임워크를 처음부터 파악하고 사용하는 일은 쉽지 않습니다. 어떤 식으로 개발이 진행되는지를 대략적으로 살펴보면 좋을 듯 합니다.

프로젝트가 진행될때 기본적인 골격은 아키텍트Architect에 의해서 잡혀진다고 보면 됩니다. 아키텍트는 개발자의 최종 테크트리…​라고 할 수 있다. 아키텍트에 대해 궁금하다면,

를 읽어보세요.

3.1. 애플리케이션 개발 흐름

  1. 실무자와 기획자에 의한 전체적인 서비스의 기획-분석

  2. 아키텍트- 애플리케이션 기능설계

    1. 애플리케이션에 적용될 프레임워크 및 관련 설정 검토

    2. 솔루션 도입시 이와 관련된 기능분석 및 협의

    3. 개발환경 구축

      1. VCS(Version Control System) 설치 및 버전관리 전략수립

      2. CI 구축(Jenkins 가 많이 이뤄짐)

  3. 스프링 프로젝트 빌드

    1. 메이븐Maven이나 그레들Gradle 빌드툴을 이용한 의존성 설정 및 빌드통합 처리

  4. web.xml 설정

    1. servlet 3.0+ 이상을 적용하는 경우에는 ServletInitializer를 통해서 web.xml 설정 대체가능

  5. 스프링 애플리케이션 컨텍스트ApplicationContext 설정

    1. application-context.xml(DAO, 서비스 영역)

      1. datasource 설정

      2. AOP 설정

    2. web-application-context.xml(웹 영역)

    3. security-context.xml(웹접근 인증 설정)

      1. URL과 사용자 권한을 기준으로 접근제어

  6. 애플리케이션 컨텍스트 정상설정 테스트

  7. MyBatis 를 사용하느냐, 하이버네이트등의 ORM 을 사용하느냐에 따라 DB 사용방식 달라짐

    1. MyBatis 인 경우에는 Database 에 스키마와 테이블들이 생성되어 있어야 함

      1. Mapper 클래스 및 SQL 을 설정해줘야 함

      2. iBatis 말고 MyBatis 사용을 권장: iBatis는 개발지원이 끝난지 꽤 되었음

      3. MyBatis와 관련된 부분은 MyBatis를 참고

    2. ORM인 경우에는 개발단계에서 ddl-auto 의 설정을 통해서 테이블 및 컬럼의 자동생성처리가 가능

      1. Spring Data JPA를 사용할 경우 기본적인 CRUD 처리를 JPARepository를 통해서 처리가 가능함

      2. 이와 관련된 자세한 내용은 자바 ORM 표준 JPA 프로그래밍 을 살펴보기

  8. 이후 애플리케이션의 패키지를 구성하고 기능별로 계층을 나눠 개발

    아키텍트나 프로젝트 리더에 의해서 정리되고 개발된다.

  9. 계층형 패키지 구성(domain, repository, service, web 영역 구분)

    io.honeymon.spring
      configuration
        - WebConfiguration.java
      domain
        - Member.java
        - Project.java
      repository
        - MemberRepository.java
        - ProjectRepository.java
      service
        - MemberService.java
        - DefaultMemberService.java
        - ProjectService.java
        - DefaultMProjectService.java
      web
        - MemberController.java
        - ProjectController.java
      common
        - FileUtils.java
        - DateUtils.java
  10. 기능별 패키지 구성(member, project 등 기능별로 구분짓고 관련 클래스를 모아둠)

    io.honeymon.spring
      configuration
        - WebConfiguration.java
      member
        - Member.java
        - MemberRepository.java
        - MemberService.java
        - DefaultMemberService.java
        - MemberController.java
      project
        - Project.java
        - ProjectRepository.java
        - ProjectService.java
        - DefaultProjectService.java
        - ProjectController.java

    와 같은 기능별 패키지로 나눠 개발하는 방식도 있습니다. 이노쿼츠팀에서도 계층형 패키지 구성에서 기능형 패키지 구성으로 변환했음.


위와 같은 형태로 개발을 진행합니다.

  • 이노쿼츠 현재 상황

    1. 애플리케이션 개발에 있어서 MyBatis 보다는 JPA 사용을 선호함. MyBatis 는 4년전 이후로 사용해본 경험없음

    2. ORM을 기반으로 개발하면 엔티티 객체를 기반으로 해서 DB와의 매핑처리도 쉽고 기능구현도 쉬움.


스프링부트를 기반으로 개발하게 될 경우, 스프링과 관련된 설정의 부담감이 줄고 개발에 필요한 라이브러리들을 `Starter-POM`s 를 통해서 쉽게 처리가 가능하기 때문에 스프링 프레임워크에 대한 이해가 어느정도 있는 개발자에게는 스프링부트 사용을 권함

3.2. 화면개발

  1. 기본설정이 완료된 후에는 개발하는 화면에 따라 기능 구현 시작

  2. JSP 페이지 등의 템플릿 파일 작성

  3. Controller ModelAndView 에 템플릿 페이지 등록

    1. ajax 를 활용할 경우 화면처리를 담당할 컨트롤러와 데이터를 JSON으로 처리해줄 컨트롤러를 분리하면 좋음

    2. Spring 4.0 이후 @RestController 애노테이션이 생겨서 요청한 컨텐트타입으로 반환해주는 컨트롤러를 만들 수 있음

  4. 화면에 필요한 데이터를 담을 데이터들을 ModelAndView 혹은 템플릿엔진을 사용하는 경우에는 Model에 담아주면ViewResolver에 의해서 처리됨

  5. 화면에 필요한 데이터에 따라서 Controller에서 Model에 담아주는 데이터가 달라지고 이는 Service의 구현이 필요해짐

    1. 화면데이터에 따라 데이터, 서비스 가 달라짐


3.3. 스프링 애플리케이션 분석

3.3.1. 고전적인 XML 설정을 기반으로 한 경우

  1. web.xml 찾아서 애플리케이션 필터 설정들을 확인

  2. application-context.xml 혹은 *-context.xml 파일 분석

    1. application-context.xml: 파일은 보통 src/main/resource/META-INF에 위치

    2. web-application-context.xml: 파일은 보통 WEB-INF 에 위치

    3. 프로젝트를 설정한 사람에 따라 파일명이나 위치는 다를 수 있으므로 파일찾기를 통해서 찾아보기 바람

  3. DB 설정 확인

  4. 애플리케이션 패키지 구성 확인

  5. 애플리케이션을 구동하면서 찍히는 로그를 통해서 동작순서 확인

  6. 관련한 설정 확인

3.3.2. JavaConfig 인 경우

  1. @Configuration 애노테이션을 사용한 클래스 탐색

    1. @Configuration 애노테이션을 사용한 클래스느는 보통 하나의 패키지 아래에 집중된다.

  2. 나머지 항목들은 고전적인 XML 설정을 기반으로 한 경우 와 동일

3.3.3. STS를 이용한 경우


STS: Spring Tool Suite http://spring.io/tools/sts
  1. spring explorer view 를 활용해서 각 설정빈을 확인 가능함

  2. Spring tools - Live Bean graph를 통해서 애플리케이션에 선언된 빈들의 연결을 확인할 수 있다.


4. 스프링 프로젝트 시작하기

4.1. 자바 엔터프라이즈 플랫폼과 스프링 애플리케이션

4.1.1. 클라이언트와 백엔드 시스템

엔터프라이즈 애플리케이션은 자신이 클라이언트가 돼서 또 다른 엔터프라이즈 시스템에 서비스를 요청할 수 있다. 또는 데이터베이스나 레거시 시스템 같은 엔터프라이즈 정보 시스템이라고 불리는 백엔드 시스템의 기능을 이용하기도 한다.

4.1.2. 애플리케이션 서버

스프링으로 만든 애플리케이션을 자바 서버환경에 배포하려면 JavaEE 서버가 필요하다.

  • 경량급 WAS/서블릿 컨테이너

    스프링은 기본적으로 톰캣tomcat이나 제티Jetty와 같은 가벼운 서블릿 컨테이너만 있어도 충분하다. 그 이외의 필요한 기능들은 모듈과 라이브러리등을 통해서 지원하능하다.

  • WAS

    상용 또는 오픈소스 WAS를 사용하는 경우도 있음. 제우스, 웹스프어 등등등…​

4.1.3. 스프링 애플리케이션의 배포단위

  • 독립형 모듈

    스프링은 보통 war로 패키징된 독립 웹 모듈로 배포된다. 톰캣 같은 서블릿 컨테이너를 쓴다면 독립 웹 모듈이 유일한 방법이다.

  • 엔터프라이즈 애플리케이션

    확장자가 ear인 엔터프라이즈 애플리케이션으로 패키징해서 배포할 수도 있다.

5. …​ ㅠㅅ-) 나도 어렵다.

스프링을 제대로 사용하는 건 생각보다 쉽지 않다. 이런 식으로 만들면 된다는 표준 샘플이 있는 것도 아니다. 스프링의 개발 표준 따위가 존재하지도 않지만, 스프링 적용 베스트 프렉티스를 모아서 그대로 따른다고 해도 스프링을 잘 사용하고 있다고 확신할 수는 없다.

5.1. 프레임워크 기반 개발

소프트웨어를 개발하는데 프레임워크를 사용하는 이유는, 프레임워크가 제공하는 편의기능을 활용하고 여러 개발자가 함께 개발할 때 프레임워크의 제약에 따라 일정한 형태의 코딩을 하도록 하는 효과가 있다.

  • @Repository, @Service, @Component, @Controller와 같이 계층적인 구분을 지을 수 있는 애노테이션을 사용

  • @Transactional, @Cacheable, @CacheEvict 등의 AOP 적인 선언을 통해서 프로그래밍 가능

5.2. 주의할 점

스프링프레임워크는 좋은 프레임워크임에는 분명하다. 그러나 나는 지나치게 프레임워크에 치우친 개발을 하는 것은 피해야한다고 생각한다. 개발자가 해결해야하는 문제는 다양한 형태로 도출될 수 있고 그 문제를 푸는 방법도 여러가지가 있다. 어떤 틀(프레임워크)에 갖혀서는 그 문제를 풀 수 없을 경우들이 발생한다.

개발자는 연마를 통해서 다양한 기술을 익히고 문제를 풀 수 있도록 준비하는 것이 좋다.

6. 참고



[SpringBoot] 로깅 처리

1. SpringBoot Logging

스프링부트는 Commons Logging을 사용한다. Java Util Logging, Log4J, Log4J2 and Logback에 대한 기본설정을 제공한다.

2. 로그 출력형태

스프링부트에서 출력하는 기본로그 형태
2014-03-05 10:57:51.112  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52
2014-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2014-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1358 ms
2014-03-05 10:57:51.698  INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2014-03-05 10:57:51.702  INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]

출력되는 내용은 다음과 같다. * 날짜와 시간: 밀리세컨드단위로 되어 정렬가능 * 로그레벨: ERROR,WARN, INFO, DEBUG or TRACE * 프로세스ID * ---: 를 통해서 실제 로그 메시지와 구분 * 스레드 네임 * 로거 네임: 로그가 찍히는 위치 * 로그 메시지


로그백Logback에서는 FATAL 레벨이 없다(ERROR로 매핑됨)

3. logback.xml 설정

스프링부트에서는 클래스패스classpath 상에서 루트에 logback.xml이 존재하면 해당설정파일을 로깅설정에 적용한다. 그래서 스프링부트에서는 logback-spring.xml으로 설정하는 것을 권장한다. 이렇게 해두고 설정파일에서 logging.config: classpath:logback-spring.xml과 같은 형태로 설정하면 로그설정을 추가등록한다.

스프링부트에서 생성하는 로그 설정은 대략 다음과 같다.

스프링 환경시스템 속성설명
logging.exception-conversion-wordLOG_EXCEPTION_CONVERSION_WORD로깅 예외발생시 사용할 관례적인 단어
logging.fileLOG_FILE정의되어 있다면 기본로그 설정에 사용됨
logging.pathLOG_PATH정의되어 있다면 기본로그 설정에 사용됨
logging.pattern.consoleCONSOLE_LOG_PATTERN콘솔에 출력되는 로그 패턴(stdout). (JDK 로거는 지원하지 않음)
logging.pattern.fileFILE_LOG_PATTERN파일에 사용될 로그 패턴(LOG_FILE 활성화된 경우). (JDK 로거는 지원하지 않음)
logging.pattern.levelLOG_LEVEL_PATTERN출력 로그레벨 형태 사용(기본%5p). (logging.pattern.level형태는 로그백에서만 지원)
PIDPID현재 프로세스 ID(OS 환경 변수로 정의되지 않은 경우에는 발견)

4. 로그백Logback 확장

스프링부트에서는 logback-spring.xml을 설정하길 권장한다. logback.xml로 설정하면 스프링부트가 설정하기 전에 로그백 관련한 설정을 하기 때문에 제어할 수가 없게 된다.

5. 스프링부트의 로그 설정을 유지하면서 로그백을 통해서 일일 로그파일 남기기

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
 
<appender name="dailyRollingFileAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<prudent>true</prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>applicatoin.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
 
<encoder>
<pattern>%d{yyyy:MM:dd HH:mm:ss.SSS} %-5level --- [%thread] %logger{35} : %msg %n</pattern>
</encoder>
</appender>
 
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.thymeleaf" level="INFO"/>
<logger name="org.hibernate.SQL" level="INFO"/>
<logger name="org.quartz.core" level="INFO"/>
<logger name="org.h2.server.web" level="INFO"/>
 
<root level="INFO">
<appender-ref ref="dailyRollingFileAppender" />
</root>
</configuration>

위의 형태로 logback-spring.xml을 만들어서 ${project}/src/main/resources 에 위치시키고 application.properties 혹은 application.yml에 다음과 같이 설정한다.

  1. 애플리케이션 내 로그레벨 설정

spring.profiles: logging-info
logging:
  file: logs/application.log
  level:
    org.thymeleaf: INFO
    org.springframework.web: INFO
    org.hibernate.SQL: INFO
    org.quartz.core: INFO
    org.h2.server.web: INFO
 
---
spring.profiles: logging-debug
logging:
  file: logs/application.log
  level:
    org.thymeleaf: DEBUG
    org.springframework.web: DEBUG
    org.hibernate.SQL: DEBUG
    org.quartz.core: DEBUG
    org.h2.server.web: DEBUG
 
---
spring.profiles: logging-daily
logging:
  config: classpath:logback-spring.xml

6. 로그파일 실행

$ java -jar application.jar --spring.profiles.active=logging-debug,logging-daily

위의 형태로 실행하면, 실행한 위치에는 logback-spring.xml 설정에 의해 생성된 로그는application.2015-11-03.log 파일이 생성되고, application.yml에 설정한 logging.* 관련한 로그는 logs/application.log이 생성된다.



Spring application development and analysis process


최근 스프링개발환경은 많은 변화가 있었다. 고전적인 XML 설정방식외에도 JavaConfig 방식이 가능해졌고, 기존에 설정의 복잡함을 줄이기 위한 관례적인 설정을 자동으로 제공하는 자동설정Auto-configuration을 제공하는 스프링부트(http://projects.spring.io/spring-boot/) 프로젝트를 기반으로 한 애플리케이션 개발환경이 제공되고 있다.


1. 스프링애플리케이션 개발순서

  1. 스프링애플리케이션 기능설계

  2. 스프링 프로젝트 빌드

  3. web.xml 설정

    1. servlet 3.0+ 이상을 적용하는 경우에는 ServletInitializer를 통해서 web.xml 설정 대체가능

  4. 스프링 애플리케이션 컨텍스트ApplicationContext 설정

    1. application-context.xml(DAO, 서비스 영역)

      1. datasource 설정

      2. AOP 설정

    2. web-application-context.xml(웹 영영)

    3. security-context.xml(웹접근 인증 설정)

      1. URL과 사용자 권한을 기준으로 접근제어

  5. 애플리케이션 컨텍스트 정상설정 테스트

  6. MyBatis 를 사용하느냐, 하이버네이트등의 ORM 을 사용하느냐에 따라 DB 사용방식 달라짐

    1. MyBatis 인 경우에는 Database 에 스키마와 테이블들이 생성되어 있어야 함

      1. Mapper 클래스 및 SQL 을 설정해줘야 함

      2. iBatis 말고 MyBatis 사용을 권장: iBatis는 개발지원이 끝난지 꽤 되었음

      3. MyBatis와 관련된 부분은 MyBatis를 참고

    2. ORM인 경우에는 개발단계에서 ddl-auto 의 설정을 통해서 테이블 및 컬럼의 자동생성처리가 가능

      1. Spring Data JPA를 사용할 경우 기본적인 CRUD 처리를 JPARepository를 통해서 처리가 가능함

      2. 이와 관련된 자세한 내용은 자바 ORM 표준 JPA 프로그래밍 을 살펴보기

  7. 이후 애플리케이션의 패키지를 구성하고 기능별로 계층을 나눠 개발

io.honeymon.spring
  configuration
    - WebConfiguration.java
  domain
    - Member.java
    - Project.java
  repository
    - MemberRepository.java
    - ProjectRepository.java
  service
    - MemberService.java
    - DefaultMemberService.java
    - ProjectService.java
    - DefaultMProjectService.java
  web
    - MemberController.java
    - ProjectController.java
  common
    - FileUtils.java
    - DateUtils.java

위와 같은 형태로 기능별로 계층을 나눠 개발하기도 하고

io.honeymon.spring
  configuration
    - WebConfiguration.java
  member
    - Member.java
    - MemberRepository.java
    - MemberService.java
    - DefaultMemberService.java
    - MemberController.java
  project
    - Project.java
    - ProjectRepository.java
    - ProjectService.java
    - DefaultProjectService.java
    - ProjectController.java

와 같은 기능별 패키지로 나눠 개발하는 방식도 있습니다. 저도 최근에 이 방식으로 변환을 시도하고 있다.

위와 같은 형태로 개발을 진행합니다.

  1. 애플리케이션 개발에 있어서 MyBatis 보다는 JPA 사용을 선호함. MyBatis 는 4년전 이후로 사용해본 경험없음

  2. ORM을 기반으로 개발하면 엔티티 객체를 기반으로 해서 DB와의 매핑처리도 쉽고 기능구현도 쉬움.


스프링부트를 기반으로 개발하게 될 경우, 스프링과 관련된 설정의 부담감이 줄고 개발에 필요한 라이브러리들을 `Starter-POM`s 를 통해서 쉽게 처리가 가능하기 때문에 스프링 프레임워크에 대한 이해가 어느정도 있는 개발자에게는 스프링부트 사용을 권함

1.1. 화면개발

  1. 기본설정이 완료된 후에는 개발하는 화면에 따라 기능 구현 시작

  2. JSP 페이지 등의 템플릿 파일 작성

  3. Controller ModelAndView 에 템플릿 페이지 등록

    1. ajax 를 활용할 경우 화면처리를 담당할 컨트롤러와 데이터를 JSON으로 처리해줄 컨트롤러를 분리하면 좋음

    2. Spring 4.0 이후 @RestController 애노테이션이 생겨서 요청한 컨텐트타입으로 반환해주는 컨트롤러를 만들 수 있음

  4. 화면에 필요한 데이터를 담을 데이터들을 ModelAndView 혹은 템플릿엔진을 사용하는 경우에는 Model에 담아주면 ViewResolver에 의해서 처리됨

  5. 화면에 필요한 데이터에 따라서 Controller에서 Model에 담아주는 데이터가 달라지고 이는Service의 구현이 필요해짐

    1. 화면데이터에 따라 데이터, 서비스 가 달라짐

2. 스프링 애플리케이션 분석

2.1. 고전적인 XML 설정을 기반으로 한 경우

  1. web.xml 찾아서 애플리케이션 필터 설정들을 확인

  2. application-context.xml 혹은 *-context.xml 파일 분석

    1. application-context.xml: 파일은 보통 src/main/resource/META-INF에 위치

    2. web-application-context.xml: 파일은 보통 WEB-INF 에 위치

    3. 프로젝트를 설정한 사람에 따라 파일명이나 위치는 다를 수 있으므로 파일찾기를 통해서 찾아보기 바람

  3. DB 설정 확인

  4. 애플리케이션 패키지 구성 확인

  5. 애플리케이션을 구동하면서 찍히는 로그를 통해서 동작순서 확인

  6. 관련한 설정 확인

2.2. JavaConfig 인 경우

  1. @Configuration 애노테이션을 사용한 클래스 탐색

  2. 나머지 항목들은 고전적인 XML 설정을 기반으로 한 경우 와 동일

2.3. STS를 이용한 경우


STS: Spring Tool Suite http://spring.io/tools/sts
  1. spring explorer view 를 활용해서 각 설정빈을 확인 가능함

3. 참고자료


+ Recent posts