Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8주차](박준영, 김수환, 오형석) #11

Open
sunwootest opened this issue Aug 14, 2023 · 3 comments
Open

[8주차](박준영, 김수환, 오형석) #11

sunwootest opened this issue Aug 14, 2023 · 3 comments
Assignees
Labels

Comments

@sunwootest
Copy link
Collaborator

  • 8주차
    • 7.5 ~ 7.7장
    • 8장
    • 9장
@farmJun
Copy link

farmJun commented Aug 21, 2023

토비의 스프링 7장 스프링 핵심 기술의 응용

1️⃣ DI를 이용해 다양한 구현 방법 적용하기

운영 중인 시스템에서 사용하는 정보를 실시간으로 변경하는 작업을 만들 때, 가장 먼저 고려해야 할 사항은 동시성 문제다.

1. ConcurrentHashMap

지금까지는 JDK의 HashMap을 사용해왔다. 하지만 HashMap의 경우 멀티 스레드 환경에서 동시에 수정을 시도하거나, 수정과 읽기를 동시에 요청하는 경우 예상치 못한 결과가 발생할 수 있다.
그래서 동기화된 해시 데이터 조작에 최적화되도록 만들어진 CuncurrentHashMap을 사용하는 것이 일반적으로 권장된다.

  1. 데이터 조작 시 전체 데이터에 락을 걸지 않는다.
  2. 읽기 작업에는 락을 아예 사용하지 않는다.

이러한 이유로 어느 정도 안전하면서 성능이 보장되는 동기화된 HashMap으로 이용하기에 적당하다. 하지만 동시성에 대한 부분을 테스트하기엔 간단하지 않다.

2. 내장형 데이터베이스

CuncurrentHashMap이 멀티 스레드 환경에서 최소한의 동시성을 보장해주고 성능도 나쁜 편은 아니지만,
저장되는 데이터의 양이 많아지고 잦은 조회와 변경이 일어나는 환경에서는 한계가 있다.
인덱스를 이용한 최적화된 검색을 지원하고 동시에 많은 요청을 처리하면서 안정적인 변경 작업이 가능한 기술은 데이터베이스다.

그렇다고 해서 고작 DAO가 사용할 SQL을 저장하고 관리할 목적으로 별도의 DB를 구성하면 주객전도가 발생하는 상황이다.
이럴 땐, DB의 장점과 특징은 그대로 갖고 있으면서, 애플리케이션 외부에 별도로 설치하고 셋업하는 번거로움이 없는 내장형 DB를 사용하는 것이 적당하다.

내장형 DB : 애플리케이션에 내장돼서 애플리케이션과 함께 시작되고 종료되는 DB

내장형 DB는 데이터가 메모리에 저장되기 때문에 IO로 인해 발생하는 부하가 적어서 성능이 뛰어나다.
동시에 Map과 같은 컬렉션이나 오브젝트를 이용해 메모리에 데이터를 저장해두는 방법에 비해 매우 효과적이고 안정적인 방법으로 등록, 수정, 검색이 가능하다.
또, 최적화된 락킹, 켝리수준, 트랜잭션을 적용할 수 있다.

자바에서는 Derby, HSQL, H2의 내장형 DB가 널리 사용된다. 왜냐하면 모두 JDBC 드라이버를 제공하고 표준 DB와 호환되는 기능을 제공하기 때문에 JDBC 프로그래밍 모델을 그대로 따라서 사용할 수 있다.
하지만 JDBC 방식의 접근이어도 기존의 DataSource와 DAO를 사용하는 모델을 그대로 사용하는 것은 좋지 않다.
애플리케이션과 생명주기를 같이하는 내장형 DB는 외부에서 DB를 생성하고 테이블을 만들고 초기화하는 작업을 하는 것이 아니라, 애플리케이션 내에서 DB를 가동시키고 초기화 SQL 스크립트 등을 실행시키는 등의 초기화 작업이 별도로 필요하기 때문이다.
초기화 후에는 내장형 DB용 JDBC 드라이버를 통해 일반 DB와 마찬가지로 접속하고 사용할 수 있다.

특별한 기능으로는 내장형 DB는 애플리케이션 안에서 직접 DB 종료 요청을 할 수 있어야 한다.
이를 위해 스프링은 DataSource 인터페이스를 상속해서 shutdown()이라는 내장형 DB용 메서드를 추가한
EmbeddedDatabase 인터페이스를 제공한다.

new EmbeddedDatabaseBuilder() 
        .setType(내장형 DB 종류) 
        .addScript(초기화에 사용할 DB 스크립트의 리소스 )
        ...
        .build(); 
  1. EmbeddedDatabaseBuilder() : 빌더오브젝트 생성
  2. setType() : HSQL, DERBY, H2 중 택
  3. addScript() : 테이블 생성과 데이터 초기화를 맡는 SQL 스크립트 위치 지정, 하나 이상 지정 가능
  4. build() : 주어진 조건에 맞는 내장형 DB를 준비하고 초기화 스크립트를 모두 실행한 뒤에 이에 접근 가능한 EmbeddedDatabase를 돌려줌

3. 트랜잭션 적용

내장형 DB를 통해 조회가 빈번하게 일어나는 중에도 데이터가 깨지는 일 없이 SQL을 수정하도록 보장했다. 하나의 SQL을 수정할 때는 문제가 없지만, 만약 여러 개의 SQL을 한 번에 수정해야 하는 경우에는 심각한 문제가 발생할 수 있다.

한 번에 여러 개의 SQL을 수정하는 이유로는, SQL들이 서로 관련이 있을 가능성이 크다. 비즈니스 로직이 변경되었다면, 그에 영향을 받는 모든 SQl이 변경돼야 하기 때문이다.
여러 개의 SQL을 수정하는 과정에서 예외가 발생하면 이미 수정한 SQL은 DB에 반영되고 예외가 발생한 SQL부터 그 이후는 변경되지 않은 채 작업이 끝난다.
따라서 여러 개의 SQL을 수정하는 작업은 반드시 트랜잭션 안에서 일어나야 한다.

HashMap과 같은 컬렉션은 트랜잭션 개념을 적용하기 매우 힘들다. 여러 개의 엘리먼트를 트랜잭션과 같은 원자성이 보장된 상태에서 변경하려면 매우 복잡한 과정이 필요하기 때문이다.
반면에 내장형 DB는 트랜잭션 적용이 상대적으로 쉽다. DB 자체가 기본적으로 트랜잭션 기반의 작업에 충실하게 설계됐기 때문이다.

기존 updateSql() 

public class EmbeddedDbSqlRegistry implements UpdatableSqlRegistry {
    SimpleJdbcTemplate jdbc;

    public void setDataSource(DataSource dataSource) {
        jdbc = new SimpleJdbcTemplate(dataSource); // 인터페이스 분리 원칙을 지키기 위해 DataSource를 주입
    }

    public void updateSql(Map<String, String> sqlmap) throws SqlUpdateFailureException {
        for (Map.Entry<String, String> entry : sqlmap.entrySet()) {
            updateSql(entry.getKey(), entry.getValue());
        }
    }
}
트랜잭션 테스트

public class EmbeddedDbSqlRegistryTest extends AbstractUpdatableSqlRegitstryTest {
    //    …
    @Test
    public void transactionlUpdate(){
        checkFind(“SQL1”,”SQL2”,”SQL3”);  
        // 초기상태 확인

        Map<String, String> sqlmap = new HashMap<String,String>();
        sqlmap.put(“KEY1”,”Modified1”);
        sqlmap.put(“KEY9999!@#$”,”Modified9999”); 
        // 존재하지 않는 키를 수정하도록 하면 예외가 발생할 것이다/
        // 트랜잭션 테스트를 위해 일부러 실패하도록 설정했다. 롤백을 체크하기 위한 테스트코드.

        try{
            sqlRegistry.updateSql(sqlmap);
            fail();   
        }
        catch(SqlUpdateFailureException e){}
        checkFind(“SQL1”,”SQL2”,”SQL3”);  // 초기상태와 동일한지 검증한다.
    }
}
public class EmbeddedDbSqlRegistry implements UpdateSqlRegistry {
    SimpleJdbcTemplate jdbc;
    TransactionTemplate transactionTemplate;
    // JdbcTemplate과 트랜잭션을 동기화해주는 트랜잭션 템플릿. 멀티 스레드 환경에서 공유 가능.

    public void setDataSource(DataSource dataSource) {
        jdbc = new SimpleJdbcTemplate(dataSource);
        transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
        // dataSource로 TransactionManager를 만들고 이를 이용해 TransactionTemplate을 생성한다.
    }

    // 익명 내부 클래스로 만들어지는 콜백 오브젝트 안에서 사용되기 때문에 final로 선언
    public void updateSql(final Map<String, String> sqlmap) throws SqlUpdateFailureException {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                //트랜잭션 템플릿이 만드는 트랜잭션 경계 안에서 동작할 코드를 콜백 형태로 만들고 
                // TransactionTemplate의 excute() 메서드에 전달
                for (Map.Entry<String, String> entry : sqlmap.entrySet()) {
                    updateSql(entry.getKey(), entry.getValue());
                }
            }
        });
    }
}

2️⃣ 스프링 3.1의 DI

스프링이 등장한 이후 많은 변화를 겪었다. 하지만 스프링이 근본적으로 지지하는, 객체지향 언어인 자바의 특징과 장점을 극대화하는 프로그래밍 스타일과 이를 지원하는 도구로서의 정체성은 변하지 않았다.
스프링은 1.0부터 3.1까지 거의 완벽에 가까운 구버전 호환성을 유지한다. 스프링이 제공하는 모든 기술의 기초가 되는 DI의 원리는 변하지 않았지만, DI가 적용된 코드를 작성하는 방법은 변했다.

1. 애노테이션의 메타정보 활용

자바는 소스코드가 컴파일된 후 클래스 파일에 저장됐다가, JVM에 의해 메모리로 로딩되어 실행된다. 그런데 때로는 자바 코드가 실행되는 것이 목적이 아니라 다른 자바 코드에 의해 데이터처럼 취급되기도 한다.
자바 코드의 일부를 리플렉션 API 등을 이용해 어떻게 만들었는지 살펴보고 그에 따라 동작하는 기능이 점점 많이 사용되고 있다.

리플렉션 API가 본래 목적보다 자바 코드의 메타 정보를 데이터로 활용하는 스타일의 프로그래밍 방식에 더 많이 활용되고 있다.
이런 프로그래밍 방식의 절정이 자바 5에서 등장한 애노테이션이다.
애노테이션의 특징은 다음과 같다.

  1. 자바 코드가 실행되는 데 직접 참여하지 못한다.
  2. 인터페이스처럼 타입을 부여하는 것도 아니고, 그 자체로 상속이나 오버라이딩이 가능하지 않다.
  3. 동작하는 코드를 넣을 수 없고, 코드에서 참조하거나 활용할 수 없다.
  4. 복잡한 리플렉션 API를 이용해 애노테이션의 메타정보를 조회하고, 애노테이션 내에 설정된 값을 가져와 참고한다.

애노테이션 자체가 클래스의 타입에 영향을 주지도 못하고, 일반 코드에서 활용되지 못한다. 그럼에도 애노테이션을 이용하는 표준 기술과 프레임워크가 빠르게 증가했다.
스프링 또한 애노테이션의 적극적인 활용에 앞장서왔다. 그 이유는 무엇일까?

@Special
public class MyClass{
    ...
}

@Special이라는 간단한 애노테이션을 클래스 선언 위에 추가했을 뿐인데 다양한 정보를 얻을 수 있다. 애노테이션이 부여된 클래스의 패키지, 클래스 이름, 접근 제한자, 상속한 클래스나 구현 인터페이스가 무엇인지 알 수 있다.

원한다면 클래스의 필드나 메서드 구성도 확인이 가능하다. 단순한 애노테이션 하나를 추가하는 것만으로, 다양한 정보를 얻어낼 수 있다.
반면에 동일한 정보를 XML로 표현하려면 모든 내용을 명시적으로 나타내야 한다.

리팩토링을 할 때도 차이점이 있다. 리팩토링 중 MyClass의 패키지를 변경하거나 클래스 이름을 바꿨다면 IDE를 활용하여 간단히 이름이나 위치를 바꾸는 리팩토링을 할 수 있다.
하지만 XML은 패키지나 클래스 정보 등이 단순 텍스트로 작성되어 있어서 리팩토링을 할 때 번거롭고 안전하지 못하다.

반면에, XML은 어느 환경에서나 손쉽게 편집이 가능하고, 내용을 변경하더라도 다시 빌드를 할 필요가 없지만, 애노테이션은 자바 코드에 존재하므로 변경할 때마다 매번 클래스를 새로 컴파일해야 한다.

2. 정책과 관례를 이용한 프로그래밍

애너테이션 같은 메타정보를 활용하는 프로그래밍 방식은 코드를 이용해 명시적으로 동작 내용을 기술하는 대신 코드 없이도 미리 약속한 규칙 또는 관례를 따라서 프로그램이 동작하도록 만드는 프로그래밍 스타일을 적극적으로 포용해왔다.
코드로 동작 내용을 구체적으로 구현하지 않고, 정책과 곤례를 따라 구현하면 쉽게 부가적인 것들을 부여할 수 있다. 반복되는 부분을 줄여주고 빠르게 구현할 수 있는 장점이 있다.

  1. XML을 자바코드로 대체
@ContextConfiguration(locations="/test-applicationContext.xml")

@ContextConfiguration(classes=TestApplicationContext.class)
  1. <bean> 전환
XML로 정의한 transactionManager 빈
<bean id="transactionManager"
    class ="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

자바 코드로 정의한 transactionManager@Bean
public PlaformTransactionManager transactionManager(){
    DataSourceTransactionManager tm = new DataSourceTransactionManager();
    tm.setDataSource(dataSource());
    return tm;
}
  1. 빈 스캐닝과 자동 와이어링

@AutoWired는 자동 와이어링 기법을 이용해 조건에 맞는 빈을 찾아 자동으로 수정자 메서드나 필드에 넣어준다.
컨터에너가 이름이나 타입을 기준으로 주입될 빈을 찾기에 빈의 프로퍼티 설정을 직접해주는 자바 코드나 XML의 양을 대폭 줄일 수 있다.

  1. @Component를 이용한 자동 빈 등록

@Component는 클래스에 부여되는 어노테이션이다. @Component가 붙은 클래스는 빈 스캐너를 통해 자동으로 빈으로 등록된다.
정확히는 @Component 또는 @Component를 메타 어노테이션으로 갖고 있는 애노테이션이 붙은 클래스가 자동 빈 등록대상이 된다.

@Component 메타 어노테이션을 가진 어노테이션 정의

@Component
public @interface SomeAnnotation{
    ...
}


@SomeAnnotation
public class SomeClass{
    ...
}
  1. 컨텍스트 분리와 @Import

지금껏 책을 읽으며 작성해온 코드들은 애플리케이션이 바르게 동작하는 데 필요한 DI 정보와 테스트를 수행하기 위해 만든 DI 정보가 하나의 파일 안에 혼재해 있다.
그러므로 성격이 다른 DI 정보를 분리해보자.

@ContextConfiguration(classes={TestAppContext.class, AppContext.class})
public class UserDaoTest{
    ...
}

@ContextConfiguration(classes=AppContext.class)
public class UserDao{
    ...
}

그다음으로 SQL 서비스와 관련된 빈들을 분리해보자.
분리하는 방법 자체는 간단하다. @Configuration 클래스를 하나 더 만들면 된다.

@Configuration
public class SqlServiceContext{
    ...
}

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages="~~")
@Import(SqlServiceContext)
public class AppContext{
    ...
}

이러한 방식으로 AppContext가 메인 설정 정보가 되고, SqlServiceContex는 보조 설정 정보로 사용할 수 있다.

  1. 프로파일

테스트 환경과 운영 환경에서 다른 빈 정의가 필요한 경우가 있다. 양쪽에 모두 필요하면서 내용만 다른 것들은 설정 정보를 변경하고 조합하는 것 만으로는 한계가 있다.
스프링 3.1은 환경에 따라서 빈 설정 정보가 달라져야 하는 경우에 파일을 여러 개로 쪼개고 조합하는 등의 번거로운 방법 대신 간단히 설정 정보를 구성할 수 있는 방법을 제공한다.

실행 환경에 따라 빈 구성이 달라지는 내용을 프로파일로 정의해서 만들어두고, 실행 시점에 어떤 프로파일의 빈 설정을 사용할지 지정하는 것이다.

운영 환경에서만 필요한 빈을 담은 빈 설정 클래스




@Configuration
@Profile("test")
public class TestAppContext{
    ...
}

@Configuration
@Profile("production")
public class ProductionAppContext {
    ...
}

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages="~~~")
@Import({SqlServiceContext.class, TestAppContext.class, ProductionAppContext.class})
public class AppContext {
    ...
}

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test") // 프로파일 사용
@ContextConfiguration(classes=AppContext.class)
public class UserServiceTest {
    ...
}

test 프로파일이 지정된 TestAppContext의 빈 설정은 포함되고, ProductionAppContext의 빈 설정은 production 프로파일로 선언되어 있어 무시된다.

@genius00hwan
Copy link

[9장] 스프링 프로젝트 시작하기

9장에서는 스프링을 이용해 애플리케이션을 만든다고 할 때 알아야하는 배경지식에 대해 다룬다.
또 프로젝트 시작할때 생각해볼 수 있는 아키텍처에 대해 다룬다.

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

스프링은 주로 자바 엔터프라이즈 환경에서 동작하는 애플리케이션을 개발하는데에 사용된다.

즉, 클라이언트의 요청을 받아 작업을 수행하고 그 결과를 반환하는 형식으로 서비스를 제공한다.

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

스프링이 사용되는 애플리케이션의 기본구조

  • 클라이언트 : 웹브라우저
  • 백엔드 시스템 : DB

클라이언트가 웹 브라우저여야 하는 것도 아니며 백엔드 시스템은 DB를 이용해야 하는 것만은 아니다.

자바 서버가 받아들일수 있는 방식으로 요청을 보내기만 한다면 어떤 종류의 클라이언트이든 상관없다.

스프링 엔터프라이즈 애플리케이션은 DB는 물론 메시징 서버, 메일 서버 등 자바가 지원하는 접속방식을 제공하기만 하는 시스템이면 백엔드 시스템으로 이용할 수 있다.

애플리케이션 서버

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

  • JavaEE의 대부분의 표준 기술을 지원하고 다양한 형태의 모듈로 배포 가능한 완전한 웹 애플리케이션 서버(WAS)

  • 웹 모듈의 배포만 가능한 경량급 WAS또는 서블릿/JSP 컨테이너

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

  • 스프링은 기본적으로 톰캣이나 제티 같은 가벼운 서블릿 컨테이너만 있어도 충분하다.

  • 서블릿 컨테이너로도 엔터프라이즈 애플리케이션에 필요한 핵심기능을 모두 이용할 수 있다.

  • 라이브러리의 도움을 받는다면 분산/글로벌 트랜잭션도 사용할 수 있다.

WAS

  • 미션 크리티컬한 시스템 에서 요구하는 고도의 안정성이나 고성능 시스템에서 안정적인 리소스 관리등 필요가 있다면 상용/오픈소스 WAS를 이용할 수 있다.

  • 상대적으로 관리 기능이나 모니터링이 기능이 뛰어나서 여러 대의 서버를 동시에 운영할 때 유리한 점이 많다.

미션 크리티컬한 시스템?

비즈니스 또는 조직의 생존에 필수적인 시스템
업무 수행을 위하여 가장 중요한(필수 불가결한) 요소

  • 국방·의료·금융·반도체·우주항공 등처럼 작은 실수만으로도 치명적인 결과를 초래하는 분야를 말한다.
  • IT 영역에서는 통신 시스템, 재난 통신망, 항공 관제시스템, 데이테이스 시스템 등을 미션 크리티컬 요소로 본다.

스프링소스 tcServer

  • 톰캣 기반으로 엔터프라이즈 스프링 애플리케이션에 최적화된 경량급 서버

  • 기존 톰캣에서는 아쉬웠던 고급 서버 관리 기능, 배포 기능, 진단 기능을 포함 톰캣 전문가의 기술지원까지 제공 받을 수 있다.

  • 스프링 개발회사가 개발한 것이라 애플리케이션 개발 및 운영에 필요한 중요한 기능을 제공받을 수 있다.

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

독립 웹 모듈

  • 톰캣 같은 서블릿 컨테이너를 쓴다면 독립 웹 모듈이 유일한 방법
  • WAS로 배포한다고 하더라도 독립 웹 모듈을 사용하는 경우가 대부분
  • 여러 개의 웹 모듈을 묶어서 하나의 웹 애플리케이션 모듈로 만들지 않는 한 독립 웹 모듈이 가장 단순하고 편리한 배포 단위이다.

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

  • 경우에 따라선 확장자가 ear인 엔터프라이즈 애플리케이션으로 패키징해서 배포할 수도 있다.
  • 하나 이상의 웹 모듈과 별도로 구분된 공유 가능한 스프링 컨텍스트를 엔터프라이즈 애플리 케이션으로 묶어주는 방법이다.

JAR, WAR, EAR 차이점

JAR, WAR, EAR 파일의 가장 큰 차이점은 서로 다른 환경을 대상으로한다는 점이다.

  • EAR 파일을 실행하려면 완전한 Java EE (Java Platform, Enterprise Edition) 또는 JBoss와 같은 Jakarta Enterprise Edition (EE) 호환 애플리케이션 서버가 필요하다.
  • WAR 파일은 Java EE Web Profile 호환 응용 프로그램 서버 만 실행하면되고 JAR 파일은 Java 설치 만 필요하다.

백그라운드 서비스 모듈

  • 이 두가지 방법 외에도 J2EE 1.4에서 등장한 rar 패키징 방법도 있다.
  • rar는 리소스 커넥터를 만들어 배포할 때 사용하는 방식
  • 스프링으로 만든 애플리케이션이 UI를 따로 가질 필요는 없고 서버 내에서 백그라운드 서비스처럼 동작할 필요가 있다면 rar 모듈로 만들어서 배포할 수 있다.

개발 도구와 환경

스프링3.0 을 적용하기 위해서는 jdk6.0, 적어도 5.0이상을 사용해야한다.
J2EE 1.4나 javaEE 5.0이상이 필요하다.

라이브러리 관리와 빌드 툴

  • 라이브러리 A와 B에 의존하고 있는 애플리케이션 코드가 있다고 하자
  • A와 B는 각각 라이브러리 C에 의존하고 있을 때 서로 다른 버전에 의존하고 있다면 충돌이 일어나 A, B 둘중 하나는 정상적으로 동작하지 못한다.

리패키징

  • 한쪽 버전의 클래스를 다른 패키지로 옮겨 서로 구별되는 클래스로 만들어주는 방법
  • 의존하는 라이브러리의 코드도 변경된 패키지 내의 클래스를 사용하도록 수정해야 한다.

라이브러리 선정

프로젝트 폴더 구조와 라이브러리 선정을 스스로 결정해야 하는 상황이라면 신경써야 할게 많다.

  • 애플리케이션의 요구 사항을 정리해야 한다.
  • 각 기능을 지원하는 기술 중 어떤 기술을 사용할지 결정해야 한다.

스프링 모듈

  • 스프링에는 약 20가지 모듈이 있다.
  • 일부는 거의 모든 애플리케이션에서 사용되는 필수 모듈이다.
  • 모듈 사이에도 의존 관계가 있다.

라이브러리

  • 스프링 모듈은 다른 모듈에 의존하기도 하지만 오픈소스 라이브러리 또는 표준 API, 상용 제품의 라이브러리를 의존하기도 한다.
  • 각 라이브러리를 활용하는 방법에 따라 다른 서드파티 라이브러리를 의존하기도 한다.
  • 해당 프레임워크나 라이브러리의 문서를 참조해 필요한 라이브러리가 어떤 것인지 직접 찾아봐야 한다.

Maven & POM

  • Maven : pom을 이용한 정형화된 빌드 시스템
  • pom.xml : 프로젝트 모델 정보, 프로젝트 관리 및 빌드에 필요한 환경설정, 저장소 위치, 의존성 관리 등의 정보를 저장하는 파일
  • 애플리케이션이 필요로 하는 라이브러리를 선언만 하면 원격으로 사용 가능 하게 한다.
  • POM 의존 정보에 하나의 라이브러리만 지정하면 지정된 라이브러리에 필요한 다른 라이브러리까지 함께 다운로드 해준다.

Gradle

  • Maven을 사용할 수 있는 변환 가능 컨벤션 프레임 워크
  • Apache Ivy에 기반한 강력한 의존성 관리
  • 원격 저장소나, pom, ivy 파일 없이 연결되는 의존성 관리 지원
  • 빌드를 설명하는 풍부한 도메인 모델

Build라는 동적인 요소를 XML로 정의하기에는 어려운 부분이 많다.

  • 설정 내용이 길어지고 가독성 떨어진다.
  • 상속구조를 이용한 멀티 모듈을 구현할 수 있다.
  • 특정 설정을 소수의 모듈에서 공유하기 위해서는 부모 프로젝트를 생성하여 상속하게 해야 한다.

애플리케이션 아키텍처

아키텍처는 내부 구성요소들이 어떤 책임을 갖고 어떤 방식으로 서로 관계를 맺고 동작하는지 규정하는 것이라고 할 수 있다.

계층형 아키텍처

성격이 다른 모듈이 강하게 결합되어 한데 모여 있으면 한 가지 이유로 변경이 일어날 때 그와 상관없는 요소도 함께 영향을 받게 된다.
인터페이스와 같은 유연한 경계를 만들어두고 분리하거나 모아주는 작업이 필요하다.

아키텍처와 관심의 분리

이런 원리는 아키텍처 레벨에서 좀 더 큰 단위에 대해서도 동일하게 적용할 수 있다.
애플리케이션을 구성하는 오브젝트들을 비슷한 성격과 책임을 가진 것들끼리 묶을 수 있다.

  • 데이터 액세스 로직을 담당하는 DAO들은 하나의 단위로 취급 할 수 이싸.
  • 비즈니스 로직을 구현해 놓은 비즈니스 서비스 오브젝트들도 같은 성격으로 묶을 수 있다.

이렇게 성격이 다른 것은 아키텍처 레벨에서 분리해주는 게 좋다.

  • 책임과 성격이 다른것을 크게 그룹으로 만들어 분리해두는 것을 아키텍처 차원에서는 계층형 아키텍처라고 한다.

보통 웹 기반의 엔터프라이즈 애플리케이션은 일반적으로 세 개의 계층을 갖는다고해서 3계층 애플리케이션이라고 한다.

3계층 아키텍처와 수직 계층

  • DB나 레거시 시스템과 연동하는 인터페이스 역할을 하는 데이터 액세스 계층
  • 비즈니스 로직을 담고 있는 서비스 계층
  • 웹기반의 UI를 만들고 관리하는 프레젠테이션 계층

데이터 액세스 계층

  • JdbcTemplate을 사용하는 데이터 액세스 계층의 특징은 JdbcTemplate이 추상화를 위한 계층으로 사용되어 하위레벨의 기반 계층에 존재하는 JDBC와 드라이버, 스프링의 트랜잭션 추상화 서비스의 동기화 기능을 간접적으로 이용하게 만든다는 것이다.
  • 추상화 계층구조를 따른다면 항상 JdbcTemplate을 통해 접근하도록 코드를 작성하는 것이 바람직하다.
  • JdbcTemplate 기능과 SqlService의 SQL을 가져오는 기능을 묶어서 더 단순한 방법으로 DAO코드를 작성하고 싶다면 또 하나의 추상계층을 추가할 수 있다.

서비스 계층

잘 만들어진 스프링 애플리케이션의 서비스 계층 클래스는 이상적인 POJO로 작성된다.
POJO로 만든다면 객체지향적인 설계 기법이 적용된 코드를 통해서 비즈니스 로직의 핵심을 잘 담아내고, 이를 쉽게 테스트하고 유연하게 확장할 수 있다.

  • 서비스 계층은 DAO 계층을 호출하고 이를 활용해서 만들어진다.
  • 때론 데이터 액세스를 위한 기능 외에 서버나 시스템 레벨에서 제공하는 기반 서비스를 활용할 필요도 있다.
  • 원칙적으로는 서비스 계층 코드가 기반 서비스 계층의 구현에 종속되면 안 된다.
  • 서비스 계층의 코드는 추상화된 기반 서비스 인터페이스를 통해서만 접근하도록 만들어 특정 구현과 기술에 종속성을 제거해야 한다.

POJO?

  • POJO는 "Plain Old Java Object"의 약자로, 간단하고 오래된 방식으로 작성된 자바 객체를 의미한다..
  • POJO는 특정 프레임워크나 라이브러리에 종속되지 않는 순수한 자바 객체를 뜻한다.

프레젠테이션 계층

프레젠테이션 계층은 가장 복잡한 계층이다. 프레젠테이션 계층은 매우 다양한 기술과 프레임워크의 조합을 가질 수 있다.

  • 엔터프라이즈 애플리케이션의 프레젠테이션 계층은 클라이언트의 종류와 상관없이 HTTP 프로토콜을 사용하는 서블릿이 바탕이 된다.

프레젠테이션 계층은 다른 계층과 달리 클라이언트까지 그 범위를 확장될 수도 있다.

  • 초기 클라이언트 모델은 단순히 HTML로 만들어진 결과를 사람이 볼 수 있도록 그려주고, 폼을 통해 입력받은 값을 전달하는 것이었다.
  • 최근에는 점점 많은 프레젠테이션 로직이 클라이언트로 이동하고 있다.

애플리케이션 정보 아키텍처

엔터프라이즈 시스템은 본질적으로 동시에 많은 작업이 빠르게 수행돼야 하는 시스템이다.

  • 애플리케이션의 주요 상태정보는 클라이언트나 백엔드 시스템에 분산돼서 보관된다.
  • 장기간 보관되는 상태정보는 주로 DB와 같은 백엔드 시스템에 저장된다.
  • 하나의 작업이 여러 번의 요청과 페이지에 걸쳐 일어나는 경우에 유지돼야 하는 임시 상태정보는 클라이언트에 일시적으로 보관되기도 하고 서버의 사용자별 세션 메모리에 저장되기도 한다.

DB/SQL 중심의 로직 구현 방식

데이터 중심구조의 특징은 하나의 업무 트랜잭션에 모든 계층의 코드가 종속되는 경향이 있다는 점이다.

예를 들어 사용자의 이름으로 사용자 정보를 검색해서 일치하는 사용자의 아이디, 비밀번호, 이름 등을 보여주는 작업이 있다고 하자.
이것이 하나의 업무 단위가 되면 모든 계층의 코드가 이 기준에 맞춰서 만들어 진다.
사용자 조회라는 단위 업무를 위해서만 존재하는 각 계층의 코드가 만들어진다는 뜻이다.

이런 식의 개발 방법과 아키텍처는 예전 엔터프라이즈 시스템에서 흔히 발견할 수 있다.

  • 이런 방식은 자바 코드를 단지 DB와 웹 화면을 연결해주는 단순한 인터페이스 도구로 전락시키는 것이다.
  • 자바의 오브젝트는 단지 HTTP 서비스 채널을 만들어고 JDBC를 이용해 DB기능을 사용하게 하는 스크립트 정도로 역할이 축소 된다.

오브젝트 중심 아키텍처

오브젝트 중심 아키텍처가 데이터 중심 아키텍처와 다른 특징은 도메인 모델을 반영하는 오브젝트 구조를 만들어두고 그것을 각 계층 사이에서 정보를 전송하는 데 사용한다는 것이다.

오브젝트 중심 아키텍처는 객체지향 분석과 모델링의 결과로 나오는 도메인 모델을 오브젝트 모델로 활용한다.

데이터와 오브젝트

카테고리와 상품이라는 두가지 엔티티가 나오는 상황을 예를 들어 보자.

조건에 맞는 모든 카테고리와 상품 정보를 가져와서 화면에 출력하는 기능을 만든다고 할때, 데이터 중심 아키텍처에서는 SQL과 DB관점에서 생각한다.

JOIN문을 활용해 2차원 구조의 정보를 만들어 두 정보를 조합 할 수 있다.

SELECT c.categoryid , c.description, p.productid, p.name, p.price 
FROM product p 
JOIN category c on p.categoryid= c.categoryid

맵에 필드 이름과 값을 담아 결과를 저장할 수 있다.

while(rs.next()){
  Map<String,Object> resMap = new HashMap<String, Object>();
  resMap.put(“categoryid”,rs.getString(1));
  resMap.put(“description“, rs.getString(2));
  …
  list.add(resMap);
}

서비스 계층에 전달되는 것은 List<Map<String, Object>> 타입이다.

데이터 중심 아키텍처 vs 오브젝트 중심 아키텍처

결과를 사용하는 서비스 계층이나 프레젠테이션 계층의 코드에서는 DAO메소드에서 두 개의 테이블을 JOIN 을 사용해 필드의 값을 가져와 필드 이름을 키로 갖는 맵에 값을 저장했음을 알아야 사용할 수 있다.

DAO에서 SQL을 변경하거나 필드 개수나 순서, 이름을 바꾼다면 서비스 계층과 프레젠테이션 계층의 코드도 같이 변경돼야 한다.

  • 데이터 중심의 아키텍처에서는 DAO가 만드는 SQL의 결과에 모든 계층의 코드가 의존하게 된다.

반면에 오브젝트 중심 아키텍처 에서는 애플리케이션에서 사용되는 정보가 도메인 모델의 구조를 반영해 만들어진 객체 안에 담긴다.

도메인 모델은 애플리케이션 전 계층에서 동일한 의미를 갖는다.

  • 도메인 모델이 반영된 도메인 오브젝트도 전계층에서 일관된 구조를 유지한 채로 사용될 수 있다.
  • SQL이나 웹페이지의 출력 포맷, 입력폼 등에 종속되지 않는 일관된 형식의 애플리케이션의 정보를 다룰 수 있게 된다.

도메인 오브젝트

public class Category{
  int categoryid;
  String description;
  Set<Product> products;  // 여러개의 Product를 참조하고있는 컬렉션을 가질수 있다.
  …
}


public class Product{
  int productid;
  Stringname;
  int price;
  Category category;  // 1개의 Category를 가리키는 레퍼런스를 직접 갖고 있다.
  …
}

자바의 레퍼런스 개념은 상호 참조가 가능 하게 한다.
애플리케이션 어디에서도 사용될 수 있는 일관된 형식의 도메인 정보를 담고 있다.

  • Product클래스에는 Product테이블처럼 categoryid라는 외래키가 없다.
  • Category 오브젝트를 가리키는 레퍼런스 변수를 갖고 있다.
  • 반대로 하나의 Category는 여러개의 Product와 관계를 가질 수 있으므로 Set이라는 컬렉션을 이용해 여러 개의 Product 오브젝트를 참조하게 만들 수 있다.

Category 오브젝트에서 Category에 속한 Product를 가져올 수도 있다.
Set<Product> products = myCategory.getProducts();

  • 데이터 중심 방식에서는 Category와 그에 대응되는 Product를 찾아 SQL을 이용해 조인한 다음 하나의 맵에 뭉뚱그려서 가져왔다.

  • 오브젝트 중심 방식에서는 테이블의 정보과 그 관계를 유지한 채로 정확한 개수의 Category 객체와 그에 대응되는 Product 객체로 만들어 사용할 수 있다.

도메인 오브젝트의 문제점

최적화된 SQL을 매번 만들어 사용하는 경우에 비해 성능 면에서 조금은 손해를 감수해야 할 수도 있다.
DAO는 비즈니스 로직의 사용 방식을 알지 못하므로, 도메인 오브젝트의 모든 필드 값을 다 채워서 전달하는 경우가 대부분이다.

  • 하나의 오브젝트에 담긴 필드의 개수가 많아지다 보면 그중에는 잘 사용되지 않는 필드도 있을 수 있다.
  • 어떤 비즈니스 로직에서 필요한 정보가 몇 개의 필드 뿐이라면 DAO에서 도메인 오브젝트의 모든 필드 정보를 채워서 전달하는 것은 낭비일 수도있다.

지연된 로딩(lazy loading) 기법

일단 최소한의 오브젝트 정보만 읽어두고 관계하고 있는 오브젝트가 필요한 경우에만 다이내믹하게 DB에서 다시 읽어올 수 있다.

  • 도메인 오브젝트를 사용하는 코드는 이런 사실을 전혀 의식하지 않고 처음부터 모든 오브젝트의 정보가 다 제공된다고 생각하고 작성하면 된다.
  • 필드가 너무 많을 경우에는 따로 도메인 오브젝트로 정의해두고 사용할 수 있다.
  • 그에 따라 DAO 메소드가 추가되어 계층간의 결합이 발생한다.
    (미약한 결합이라곤 하나 계층간의 결합은 지양해야 한다.)

RDB 매핑(ORM) 기술

  • "Object-Relational Mapping"의 약어로, 객체와 관계형 데이터베이스 간의 매핑을 자동화하는 기술
  • 이와 같은 데이터 액세스 기술은 기본적으로 지연된 로딩 기법 등을 제공해준다.
  • 번거로운 코드를 만들지 않고도 도메인 객체의 생성을 최적화할 수 있다.

도메인 오브젝트를 사용하는 오브젝트 중심 아키텍처에서는 가능하다면 ORM과 같은 오브젝트 중심 데이터 액세스 기술을 사용하는 것을 권장한다.

지연된 로딩

  • 데이터를 실제로 로딩하는 시점을 필요한 시점으로 지연 시키는 기법
  • 데이터를 조회할 때 데이터베이스에서 필요한 데이터만을 가져오는 것을 의미

빈약한 도메인 오브젝트

도메인 오브젝트에 정보만 담겨 있고, 정보를 활용하는 기능이 없다면 이는 온전한 오브젝트라고 보기 힘들다.

  • 이런 오브젝트를 빈약한(anemic) 오브젝트라 부른다.

  • 도메인 모델을 반영한 오브젝트에 정보를 담아 활용하는 편이 도메인 오브젝트를 사용하지 않는 것보다는 훨씬 낫다.

도메인 오브젝트에 넣을 수 있는 기능

  • 도메인의 비즈니스 로직

  • 빈약한 도메인 오브젝트 방식에서는 비즈니스 로직이 서비스 계층에 있다.

  • 도메인 오브젝트 방식은 거대한 서비스 계층구조와 비슷하다.

  • 비즈니스 로직이 복잡하지 않다면 가장 만들기 쉽고 3계층 구조의 특징을 잘 살려서 개발할 수 있는 유용한 아키텍처다.

풍성한 도메인 오브젝트 방식

빈약한 도메인 오브젝트의 단점을 극복하고 도메인 오브젝트의 객체지향적인 특징을 잘 사용할 수 있도록 개선

  • 어떤 비즈니스 로직은 특정 도메인 오브젝트나 그 관련 오브젝트가 가진 정보와 깊은 관계가 있다.

  • 이런 로직을 서비스 계층의 코드가 아니라 도메인 오브젝트에 넣어주고, 서비스 계층의 비즈니스 로직에서 재사용하게 만드는 것이다.

  • EX) 앞에서 만든 Category에 해당하는 Product의 가격을 모두 합하는 로직을 굳이 서비스 계층에 두지않고 Category 도메인 오브젝트에 로직을 담을 수 있다.

  • 이렇게 만들면 서비스 계층의 메소드에 따로 만드는 것보다 응집도가 높다.

도메인 오브젝트에 비즈니스 로직을 넣는다고 해서 비즈니스 로직을 담고 있던 서비스 계층 오브젝트가 필요 없어지는 건 아니다.

  • 도메인 오브젝트는 직접 데이터 액세스 계층이나 기반 계층 또는 다른 서비스 계층의 오브젝트에 접근할 수 없기 때문에 서비스 계층이 필요하기도 하다.

도메인 계층 방식

도메인 계층의 역할과 비중을 극대화하려다 보면 기존의 풍성한 도메인 오브젝트의 방식으로는 만족할 수 없다.

도메인 객체가 기존 3계층과 같은 레벨로 격상되어 하나의 계층을 이루게 하는 것이 도메인 계층 방식이다.

도메인 객체 독립된 계층을 다음과 같은 특징을 갖게 된다.

  • 도메인에 종속적인 비즈니스 로직의 처리는 서비스 계층이 아니라 도메인 계층의 오브젝트 안에서 진행된다.

  • 도메인 객체가 기존 데이터 접근 계층이나 기반 계층의 기능을 직접 사용할 수 있다.

스프링이 관리하지 않는 도메인 오브젝트에 DI를 적용하기 위해서는 AOP가 필요하다.

  • AOP의 적용 대상도 스프링의 빈 오브젝트 뿐이다.
  • 스프링 AOP대신 AspectJ AOP를 사용하면 클래스의 생성자가 호출되며 객체가 만들어지는 시점을 조인 포인트로 사용할 수 있다.
  • 스프링 빈이 아닌 객체에도 AOP 부가기능을 적용할 수 있다.

도메인 계층 방식은 이전의 어떤 방식보다 도메인 객체에 많은 비즈니스 로직을 담아낼 수 있다.
때로는 여러 도메인 오브젝트의 기능을 조합해서 복잡한 작업을 진행해야 하는 경우가 있다.

도메인 오브젝트가 계층을 이루기 전에는 모든 계층에 걸쳐 사용되는 일종의 정보전달 도구 같은 역할을 했다.

도메인 오브젝트가 도메인 계층을 벗어나서도 사용되게 할지 말지 결정해야 한다.

여전히 모든 계층에서 도메인 오브젝트를 사용한다.

  • 다양한 기능을 가진 도메인 객체를 프레젠테이션 계층이나 뷰 등에서 사용하게 해주면 이를 함부로 사용하는 위험이 따를 수 있다.

  • 철저한 가이드라인을 만들어두고 이를 적용해야한다.

도메인 오브젝트는 도메인 계층을 벗어나지 못하게 할 수도 있다.

  • 도메인 계층 밖으로 전달될 때는 별도로 준비된 정보 전달용 객체(DTO)dp 도메인 객체 내용을 복사해서 넘겨준다.

  • DTO는 기능을 갖지 않으므로 사용하기에 안전하다.

SOFEA (Service Oriented Front End Architecture)

프레젠테이션 계층의 코드가 서버에서 클라이언트로 다운로드 되어 클라이언트 장치 안에서 동작하며 서버에 존재하는 프레젠테이션 계층이나 서비스 계층과 통신하는 구조

상태 관리와 빈 스코프

아키텍처 설계에서 한 가지 더 신경 써야 할 사항은 상태 관리다.

애플리케이션은 하나의 HTTP 요청의 범위를 넘어서 유지해야 하는 상태정보가 있다.

  • 엔터프라이즈 애플리케이션은 특정 사용자가 독점해서 배타적으로 사용되지 않는다.

  • 하나의 애플리케이션이 동시에 수많은 사용자의 요청을 처리하게 하기 위해 매번 간단한 요청을 받아서 그 결과를 돌려주는 방식으로 동작한다.

  • 서버의 자원이 특정 사용자에게 일정하게 할당되지 않는다.

  • 서버 기반의 애플리케이션은 원래 지속적으로 유지되는 상태를 갖지 않는다(stateless)는 특징이 있다.

어떤 식으로든 애플리케이션의 상태와 장시간 진행되는 작업정보는 유지돼야 한다.

스프링은 기본적으로 상태가 유지되지 않는 빈과 객체를 사용하는 것을 권장한다.

  • 웹 클라이언트에 URL, 파라미터, 폼 히든 필드, 쿠키 등을 이용해 상태정보 또는 서버에 저장된 상태정보에 키 값 등을 전달할 수 있다.

  • 웹 클라이언트에 폼 정보를 출력하고 이를 수정하는 등의 작업을 위해서는 HTTP 세션을 적극 활용할 수 있다.

  • 싱글톤 이외의 스코프를 갖는 빈을 만들어 독립적으로 생성되고 유지되는 객체를 사용해 상태를 저장하고 DI를 통해 서비스 계층에서 사용할 수 있게 할 수 있다.

@kuk6933
Copy link

kuk6933 commented Aug 25, 2023

스프링이란 무엇인가?

스프링의 정의

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

애플리케이션 프레임워크

  • 대부분 프레임워크는 애플리케이션의 특정 계층에서 주로 동작하는 한 가지 기술 분야에 집중됨
  • 하지만 애플리케이션 프레임워크는 애플리케이션 전 영역을 포괄하는 범용적인 프레임워크

경량급

  • 불필요하게 무겁지 않다는 의미

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

  • 개발자가 스프링이 제공하는 기술이 아니라 애플리케이션의 로직에 더 많은 관심과 시간을 쏟게 해줌.

오픈소스

  • 스프링은 오픈소스 프로젝트 방식으로 개발 됨.
    • 장점: 투명한 방식으로 진행되기 때문에 빠르고 유연한 개발 가능, 라이선스 비용
    • 단점: 안정적인 개발이 불확실 → 전문 기업을 만듦

스프링의 목적

8.2.1 엔터프라이즈 개발의 복잡함

  • 너무 복잡함

복잡함의 근본적인 이유

  • 기술적인 제약조건과 요구사항이 늘어남
  • 엔터프라이즈 애플리케이션이 구현해야 할 핵심기능인 비즈니스 로직의 복잡함이 증가
    • 컴퓨터를 이용하는 업무가 많아짐

복잡함을 가중시키는 원인

  • 엔터프라이즈 애플리케이션 개발이 실패하는 주요 원인은 비즈니스 로직의 복잡함과 기술적인 복잡함.

8.2.2 복잡함을 해결하려는 도전

제거될 수 없는 근본적인 복잡함

  • 복잡함의 원인은 제거 대상이 아님
  • 복잡함을 효과적으로 상대할 수 있는 전략과 기법이 필요

실패한 해결책: EJB

  • EJB는 기술적인 복잡함을 애플리케이션의 핵심 로직에서 일부분 분리하는데 성공
  • 하지만 EJB라는 환경과 스펙에 종속되는 코드로 만들어져야 하는 더 큰 부담을 주게됨

비 침투적인 방식을 통한 효과적인 해결책: 스프링

  • 비 침투적인 기술을 통해 기술적인 복잡함과 비즈니스 로직을 다루는 코드를 깔끔하기 분리할 수 있었음

8.2.3 복잡함을 상대하는 스프링의 전략

기술적 복잡함을 상대하는 전략

  • 기술에 대한 접근 방식이 일관성이 없고 특정 환경에 종속적
    • 기술적인 복잡함은 일단 추상화를 통해 로우레벨의 기술 구현 부분과 기술을 사용하는 인터페이스를 분리하고, 환경과 세부기술에 독립적인 접근 인터페이스를 제공하는 것이 가장 좋은 해결책
  • 기술적인 처리를 담당하는 코드가 성격이 다른 코드에 섞여 등장
    • 트랜잭션, 보안적용 등이 예시
    • AOP를 사용하면 해결 가능

비즈니스 애플리케이션 로직의 복잡함을 상대하는 전략

  • 핵심 도구: 객체지향과 DI

8.3 POJO 프로그래밍

  • 스프링의 정수는 엔터프라이즈 서비스 기능을 POJO에 제공하는 것.
  • 엔터프라이즈 서비스는 보안, 트랜잭션과 같은 엔터프라이즈 시스템에서 요구되는 기술
  • 엔터프라이즈 서비스 기술과 POJO라는 애플리케이션 로직을 담은 코드를 분리했다는 뜻이기도 함

8.3.1 스프링의 핵심: POJO

스크린샷 2023-08-25 오후 5 03 06
  • 스프링의 주요 기술인 IoC/DI, AOP, PSA는 애플리케이션을 POJO로 개발할 수 있게 해주는 가능기술이라고 불림.

8.3.2 POJO란 무엇인가?

  • Plain Old Java Object
  • 자바의 단순한 오브젝트를 이용해 애플리케이션의 비즈니스 로직을 구현하는 것

8.3.3 POJO의 조건

  • POJO는 세 가지 조건을 충족해야함
    • 특정 규약에 종속되지 않아야함
      • 특정 규약을 따라 만들게 하는 경우는 대부분 상속을 통함. → 자바 단일 상속 제한때문에 문제 발생
    • 특정 환경에 종속되지 않아야함
      • EJB 3 빈의 오브젝트 정보는 JNDI를 통해 가져옴
    • 객체지향적인 자바 언어의 기본에 충실하게 만들어야함
      • 순수하게 JAVA API만 사용했다고 POJO가 아님

진정한 POJO란 객체지향적인 원리에 충실하면서 환경과 기술에 종속되지 않고 필요에 따라 재활용 될 수 있는 방식으로 설계된 오브젝트를 말함. 그런 POJO에 애플리케이션의 핵심 로직과 기능을 담아 설계하고 개발하는 POJO 프로그래밍이라고 함.

8.3.4 POJO의 장점

  • 특정 기술과 환경에 종속되지 않으니 깔끔한 코드가 될 수 있음
  • 자동화된 테스트에 유리
  • 객체지향적인 설계를 자유롭게 적용할 수 있음

8.3.5 POJO 프레임워크

  • 스프링은 POJO 프로그래밍이 가능한 기술적인 기반을 제공하는 프레임워크.
  • 좋은 코드와 좋은 프레임워크는 그것을 사용해서 만들어지는 코드가 나쁜 코드가 되기 어려움

8.4 스프링의 기술

  • POJO 개발을 가능하게 하는 기술이 IoC/DI, AOP, PSA

8.4.1 IoC/ DI

  • 핵심기능의 변경
  • 핵심기능의 동적인 변경
  • 부가기능의 추가
  • 인터페이스의 변경
  • 프록시
  • 템플릿과 콜백
  • 싱글톤과 오브젝트 스코프
  • 테스트

8.4.2 AOP

AOP 적용 기법

  • 다이나믹 프록시 이용
  • AspectJ 사용

8.3.4 포터블 서비스 추상화 (PSA)

  • 환경과 세부 기술의 변화에 관계없이 일관된 방식으로 기술에 접근할 수 있게 해주는 PSA

스프링이 어떻게해서 엔터프라이즈 개발이 주는 복잡함을 제거하고, POJO 프로그래밍이라는 효과적인 방법을 사용할 수 있게 하는지에 관심을 갖는 것이 스프링을 가장 빠르게 이해하고 적용할 수 있는 지름길

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants