My SQL Auto_increment 최대값

My SQL Auto_increment 최대값

MY SQL : 

- 시퀀스가 없다.
- Auto_increment를 이용하여 DB에서 자동 생성하는 값을 이용한다.

Auto_increment 의 Max값 :

1. unsigned INT = 4294967295
2. unsigned BIGINT = 18446744073709551615

어떤 값을 사용해야할까? 

- 일반적인 대부분의 케이스에서는 INT만 사용하면 됨.
- INT만 이용해도 하루에 1,176,703개의 row를 10년동안 쌓아야 최대값에 도달.

최대값에 도달하면 ? 

- 에러가 발생할 것이다.
- 그러나 대부분 발생하지 않는다.

MongoDB 3.0 Release 바뀐점

MongoDB 3.0 Release 바뀐점
Mongo DB : JSON-document base storage 

MongoDB 3.0 발표 

새로운점 

- 기존과는 다른 새로운 기능이 추가 되었음.
1. pluggable storage engin API 제공 :
    가장 두드러진 특징
    third parti들에게 새로운 스토리지를 생성할 수 있도록 허용하는 인터페이스 제공
    특정 어플리케이션에 의해서 튜닝이 가능
    MongoDB 가 자신의 스토리지 엔진을 제공하는 것을 허용

2. 더욱 정교한 locking기능 제공, 더욱 우수한 동시성 제공, 속도도 빨라짐

3. 더 쉬워진 쿼리 옵티마이징 처리 에서부터 풍부한 로깅까지 DBA와 오퍼레이터에게 편의기능 제공

4. 고차원 MongoDB Management Service 지원 :
    Cloud Manager 제공
    향상된 서버의 관리 시스템
    하나의 콘솔에서 다수의 다양한 MongoDB cluster들을 관리 가능

엔진의 향상 

이전 버젼의 MongoDB는 단일 스토리지 엔진을 제공했었다, 이를 MMAP라고 부른다, 메모리 맵 파일을 도입해서 사용하고 있었다. MMAP는 디스크 I/O의 모든 작업, seeks, block caching, OS상에서 이러한 작업이 수행되었다.
MongoDB 3.0은 MMAP의 향상된 버젼(MMAPv1)과 WiredTiger 스토리지 엔진을 제공하게 변경이 되었다.

MMAPv1은 MMAP에 대한 backword compatible 지원을 위해 유지, 이전 MongoDB로 개발된 버젼은 MMAPv1으로 업그레이드 할 수 있다. MMAPv1은 locking 에 대해서 미세한 처리를 수행할 수 있도록 개선 되었다. MMAP는 데이터베이스 레벨로 Lock을 잡았었다. 이로 인해 MMAP는 datalevel로 락을 걸었기 때문에 한번에 하나의 컬렉션만을 쓰기 할 수 있었다. MMAPv1은 컬렉션 레벨로 lock을 걸수 있다. 클라이언트는 복수개의 컬렉션을 동시에 쓰기 할수 있게 되었다. 이로 인해 쓰기 처리 속도는 확실하게 빨라졌다. 그러나 읽기도 빨라졌다. 읽기는 write에 의해서 블록이 될 수 있기 때문이다.

MMAPv1은 할당 메커니즘에 대한 향상도 가져왔다. MongoDB는 document-base 저장소이다. 각 도큐먼트는 반드시 연속적으로 저장되어져야 한다. 도큐먼트가 업데이트 되어 새로운 필드가 추가되거나 존재하는 컨텐츠의 길이가 더 길어지는 경우 전체 도큐먼트는 추가적인 공간을 얻기 위해서 다시 쓰기가 수행되어야 한다. 말할 필요도 없이 도큐먼트 재쓰기 작업은 매우 비싼 작업이다. 도큐먼트가 이동되면 이동과 더불어 인덱스 작업도 수행되어야 한다.

3.0버젼 이전에는 padding factor을 이용했었다. 이는 할당 타임에 추가적인 공간을 잡아주어 재쓰기 작업을 최소화 하는 목적으로 사용되었다. 이러한 padding factor는 이전에 할당된 이력이나 문서의 확대 속도에 따라서 추론되는 방법으로 운영된다.

3.0버젼에서는 2제곱으로 지정된 할당을 사용한다. 각 도큐먼트는 2제곱에서 가장 가까운 크기의 레코드로 저장된다. 그래서 padding은 항상 수행될 수 있도록 하고 있다. 현재 할당된 레코드를 넘어서는 도큐먼트가 있다면 새로운 레코드는 그 다음 거듭제곱으로 할당되어진다. 이것은 document의 재작성을 줄여주며, 하지만 사용되지 ㅇ낳는 도큐먼트 공간에 대한 추가적인 비용이 필요하다. 게다가 레코드 크기는 2의 거듭 제곱이기 때문에 레코드의 프라그멘테이션이 줄어들게 된다. 빈 공간은 쉽게 재 사용 될 수 있다.

노트 : 만약 도큐먼트 크기가 변경되지 않는다면 "power of two" 전략을 각 컬렉션에 대해서 끌 수 있다.

WiredTiger의 내부 

MMAPv1은 MongoDB 3.0의 기본 저장 엔진이다. 새로운 WiredTiget storage engine은 획기적인 이점을 제공한다. WiredTiger는 동일한 이름을 가진 회사에서 만든 엔진이다. 2014년 12월 MongoDB에 인수 되었다.  버클리 DB database의 아키텍트를 차용하였다.

WiredTiger 성능의 많은 부분은 주의깊게 설계된 내부로 부터 나온다 예를 들어 WiredTiger는 "hazard pointers"를 이용한다. 이는 공유된 객체에 멀티 쓰레도르 접근을 컨트롤 하기 위해서 lock-free메커니즘을 이용한다. 추가적으로 빠르게 업데이트 하기 위한 log-structed 머지와 Bloom filter 접근을 위한 arguments tree를 이용하며 키를 이용한 서치에서 인덱스 miss가 될 수 있는 현상을 줄였다.

MMAPv1은 collection level에 락을 거는 것과는 다르게 (이것만으로도 매우 큰 향상을 가져 왔음), WiredTiger는 도큐먼트 레벨의 락을 건다. 그러므로 MMAPv1의 동시성은 일반적으로 MMAP보다 뛰어나다 그러나 WiredTiger의 동시성도 여전히 더 우수하다.

WiredTiger는 데이터 압축 작업을 잘 수행한다. 3가지 옵션이 있으며 no compression, Snappy(default), Zlib가 있다. Snappy와 Zlib 압축은 서드파티 라이브러리로 제공된다.

WiredTiger가 적용하는 데이터 압축은 collection level에 대해 적용된다. 그래서 도큐먼트 컬렉션중 압축할 대상을 지정하여 압축할 수 있다. WiredTiger는 인덱스와 분리해서 압축할 것이다(인덱스 압축을 enable한경우) 이때 prefix-compression으로 알려진 처리를 수행한다. 이것은 데이터 중복 제거의 일종이다. prefix compression의 이점은 데이터는 압축해제를 할 필요가 없다는 것이다. 결과적으로 인덱스 데이터는 RAM에 딱 맞게 배치되며 성능을 향상 시킨다.

혼합 과 매칭 

앞에서 설명한것과 같이 pluggable storage engins API는 MMAPv1과 WiredTiger을 포함하는 것을 허용한다. 개발자는 그들의 스토리지 엔진을 생성할 수 있고, 타겟 어플리케이션에 대해서 특정 스토리지 기능을 추가할 수 있다. 게다가 서로다른 스토리지 엔진은 동일한 MongoDB 개발에서 사용될 수 있다. 비록 동일한 리플리카 셋을 이용하더라도, 복제는 스토리지 엔진에 투명하게 수행된다.

리플리카 셋에서 주요 도큐멘트들은 하나의 스토리지 엔진에서 다른 스토리지 인젠으로 복제되어 저장될 수 있다. 인 메모리 스토리지 엔진에서 수행중인 리플리카셋의 멤버들은 주요 클러스트에 있고 (MongoDB 엔지니어의 실험적 버젼으로 현재 평가중이다.) 두번째 리플리카셋의 클러스터 멤버들은 WiredTiger와 같은 곳에 저장될 것이다. 리플리카 셋의 데이터에 접근은 매우 빠를 것이다. 왜냐하면 요청은 in-memory 스토리지 엔진에서 수행할 것이기 때문이다. 두번째 스토리지에서는 크래시로 부터 이들을 보호하는 역할을 하게 된다.

배치에서 이러한 혼합형 스토리지 엔진은 하나의 스토리지에서 다른 스토리지로 이관을 제공한다. MMAPv1 데이터베이스는 MMAP 데이터베이스에 적합하다. WiredTiger 데이터베이스의 경우는 그렇지 않을 것이다. 혼합된 스토리지 엔진에 의해서 MMAP데이터를 WiredTiger로 rolling upgrade의 형식으로 이전할 수 있다. 이로 인해서 클라이언트에게 downtime 없이 이관처리를 가능하게 해준다.

MongoDB관리 

3.0의 기술적인 파트가 아닌 부분에대해서 MongoDB Management Service(MMS)는 많은 향상을 가져왔다. 이제는 MongoDB Cloud Manager이라고 불린다. 이 툴은 단일 모니터링 콘솔에서 전체 모니터링처리와 관리 서비스로 확장 되었다.

CloudManager는 관리자에게 현재 수행되는 클러스터 통계를 확인할 수 있도록 하며 (MMS도 수행되었음), MongoDB 클러스터 디플로이와 성능 업그레이드, 스케줄 백업 등을 지원하고 있다. 시스템은 고수준 자동화 처리를 통해서 단일 클라우드 매니저 콘솔 컨트롤에서 불규칙한 크기의 MongoDB클러스트 관리로 확대 되었다. 클라우드 매니저는 자동적으로 다양한 자동화 에이전트를 통해서 수행할 수 있다. 그리고 에이전트는 클라우드 매니저 커맨드에 대한 응답을 처리한다.

Cloud Manager의 enterprise 벼젼은 (Ops Manager로 불린다.) 설치 기능을 제공하며, 이는 on-site monitoring과 management dashboard를 가능하게 지원한다. Ops Manager는 로컬 어플리케이션과 같이 수행한다. (Cloud Manager와는 다르게). Cloud Manager는 30일 무료 버젼을 제공함. 이는 오직 모니터링 기능만 제공해준다. Ops Manager는 MongoDB의 Enterprise Edition에서만 가능하다.

기타 개선 

MongoDB는 커맨드 라인의 호스트와 함께 젝오한다. 이것은 mongoimport를 포함하여 외부 파일 데이터를 임포트 하는 기능을 가지고 있다. mongoexport는 MongoDB에서 JSON, CSV파일로 익스포트 할수 있어 데이터 베이스 백업을 수행할 수 있다.

이 툴은 MongoDB 3.0을 위해 다시 만들어 졌다. 이전 생애에서는 C++ 의 기술을 기반으로 만들어 졌다.
MongoDB 엔지니어에 의해서 관리가 쉽게 그리고 실행 크기를 줄이는 방향으로 만들어 져 있다. 추가적으로 MongoDB 엔지니어들은 멀티 쓰레드 아키텍쳐로 툴의 성능을 향상 시켰다.

MongoDB의 이전 에디션에는 리플리카 셋에서 오직 12개의 클러스터 노드만을 만들수 있었다. 이제  MongoDB 3.0에서는 50 노드 리플리카 셋을 구성할 수 있다.
이러한 설정을 통해서 읽기 요청은 클라이언트에서 가장 가까운 노드 (ping 타임 기준) 에서 서비스를 수행한다. MongoDB는 반응성과 탄력성을 제공한다. MongoDB 3.0에서는 리플리카셋을 더 많이 제공한다. 이것은 요청 서비스가 더욱 클라이언트에 가깝다는 것이다. 나아가 클라이언트가 리플리카 셋에 주는 임팩트도 최소화 할 수 있다.

MongoDB 3.0은 쿼리 시스템의 개선도 가져왔다. MongoDB의 explain() 메소드는 만족스러운 쿼리를 위해서 플랜을 노출한다. 과거에는 쿼리를 먼저 수행하고 explain()을 수행해야 좋은 쿼리 플랜이 나왔다. 그러나 MongoDB 3.0에서는 쿼리 수행 전에 explain()을 요청하여 플랜을 볼수 있다. 이로 인해서 DBA는 쿼리를 보내기 전에 튜닝을 수행할 수 있다. (이것은 long-run 쿼리에서는 매우 우수한 기능을 제공한다.) 반환되는 쿼리 플랜은 좋은 쿼리 플랜을 제공할 뿐만 아니라. 쿼리 옵티마이저가 생각하는 다른 프랜역시 제공한다.

MongoDB 3.0에서는 다른 향상된 기능들을 찾을 수 있을 것이다. geospatial 인덱스를 광범위한 위치에 대한 처리부분에서 향상 시켰다. (현재는 지구 표면의 50퍼센트가 넘는 영역도 쿼리 할 수 있다.) 또한 개발자가 수행중인 시스템의 성능을 향상 시킬 수 있도록 튜닝에 도움을 주는 로깅 시스템의 미세한 처리도 제공한다. DBA는 audit로그를 설정하여 데이터베이스의 어떠한 오퍼레이션도 캡쳐 할 수 있다. 과거에는 오직 관리적인 액션만 로깅으로 잡을 수 있었다.


출처 : http://www.javaworld.com/article/2972304/data-storage/review-mongodb-3-0-rises-for-the-enterprise.html?nsdr=true


























Domain Driven Design 소개

Domain Driven Design 소개
from : Patterns, Principles and Practices of Domain-Driven Design / Scott Millett with Nick Tune

도메인 주도 모델은 무엇인가 ?

Domain-Driven Design (DDD) :
- Eric Evans 의 세미나에서 Tackling Complexity in the Heart of Software(Addision-Wesley Professional, 2003)에서 소개한 소프트웨어 개발 철학 

- 복잡한 Problem Domain (문제영역)에 대한 소프트웨어를 생산하고 유지보수 하는 것에 대한 효과적인 관리를 가능하도록 해주는 접근 방법

복잡한 문제 영역의 소프트웨어 생성에 대한 도전 

-BBOM (Big Ball of Mud) :
    무턱대고 설계, 제멋대로, 엉성하고, 대충 만든 스파게티 코드 정글과 같은 구조를 말한다.
    Eric Evans가 설명한 "코드는 무언가 유용하다, 그러나 설명할 수 없는 코드"

- BBOM과 같은 코드가 나오는 이유는 도메인 복잡도와 기술적 복잡도의 혼합으로 인해서 나타난다.


공통 언어 없이 생성된 코드 

- 공유된 언어와 문제 영역에 대한 지식에 대한 집중력 부족으로 생성된 코드는 동작은 하지만 비즈니스 의도는 드러나지 않는다.
- 이렇게 만든 코드는 분석 모델과 코드 모델 사이에 변환에 대한 비용과 오류를 발생 시키기 때문에, 읽기 어렵고, 유지보수 하기 어렵다.
- 분석모델을 도입하지 비즈니스 이해를 위해 초과 근무를 하게 되고, 결국 BBoM 패턴과 닮은 아키텍처를 낳게 된다.
- 번역 비용이 들게 되면 코드 내에서 문제 영역의 풍부한 용어를 활용할 수 없게 되며 이는 비즈니스 전문가와 협업시 새로운 도메인 개념에 대한 발견 기회를 감소 시킨다.

분석모델이란 무엇인가?

- 논리적 디자인과 소프트웨어 구조에 대한 묘사를 위해 사용된다.
- 모델 언어 UML과 같은 언어로 스케치 될 수 있다.
- 소프트웨어에 대한 표현으로 기술 기반이 없는 사람들이 소프트웨어가 어떻게 구성되어야 할지에 대한 개념화 하기 좋은 모델이다. 

BBoM 패턴은 개발을 어렵게 한다. 

- 스파게티 와 같은 패턴을 유지하는 것은 기능 개선을 느리게 할 수 있다. 새로운 버젼의 프러덕이 릴리즈 되면 기반 코드의 이해할 수 없는 내용들로 인해 버그가 양산된다. 그리고 개발자는 이것을 처리해야한다.
- 이러한 엉망인 코드에서 작업에 대해서 개발자들의 불평이 늘어나게 된다.
- 비록 프로젝트에 추가적인 리소스가 투입되더라도 비즈니스를 만족시킬만한 레벨의 속도를 향상시키지 못한다.
- 결국 이러한 상황에 대한 분노는 애플리케이션을 다시 만들자는 요청이 허용된다.
- 신중함과 주의 없다면 깨끗한 프로젝트라고 할지라도 BBoM과 같은 형태로 실패할 수 있다.
- 결과적으로 BBoM은 개발자에게 나쁜 뉴스가 된다. 이것은 엉망인 버그 생성 코드기반이고, 이것을 어쨌든 처리해야한다. 그리고 비즈니스에도 나쁜 뉴스가 된다. 빠르게 전달되어야할 비즈니스 가치를 감소 시키게 된다.

문제 영역에 대한 주의력 부족 

비즈니스 도메인에 대한 이해의 부족은 결국 소프트웨어를 실패하게 만든다.
타이핑은 제품을 전달하는데 있어 보틀넥이 아니다. 코딩은 개발중에 쉬운 부분이다.
비 기능적인 요구사항들의 외부를 생성하는 것, 유용한 소프트웨어의 도메인을 유지하기 위해서 비즈니스 유스케이스를 달성할 수 있도록 하는 것은 어려운 파트이다.
비즈니스 도메인의 이해에 투자할수록 더 나아질 것이다. 그리고 비지니스 내제하는 문제를 해결할때 좋은 장비를 장착하게 된다.

문제영역이란? 

문제영역은 소프트웨어 개발을 수행하기 위한 주제 영역을 말한다.
크고 복잡한 비즈니스 시스템 소프트웨어를 개발할때 도메인 상위의 영역에 집중해야 하는 것은 스트레스 이다.
문제영역 전문가는 개발팀과 이러한 도메인에 집중해서 일을 한다. 이러한 작업은 가치있는 소프트웨어를 가능하게 하는 유용한 방법이다.
예를 들어, 건강 산업에서 환자의 치료 이력을 관리하는 소프트웨어를 작성할때, 의사가 되는 법은 중요한 파트가 아니다. 중요한 포인트는 건강 산업의 용어에 대한 이해이고, 환자의 관점과 치료의 관점에 대한 차이를 이해하는 것이며, 의사가 어떻게 이런 정보를 수집하고 치료에 이용할 것인지 이해하는 것이다. 

어떻게 Domain Driven Design  패턴이 복잡성을 관리하는가?

DDD는 문제 영역의 이해에 대한 도전과 관리가능한 솔루션의 생성 둘다 다룬다. 이것은 문제를 풀기 위한 유용한 도구가 된다. 이것은 몇가지의 유용한 전략 패턴과 디자인 패턴에 의해 달성된다.

DDD의 전략패턴 

DDD의 전략패턴은 문제영역을 정제하고, 어플리케이션의 아키텍쳐를 다듬는 역할을 한다.

1. 문제영역에서 무엇이 문제인지 드러내는 정제작업

개발팀과 도메인 전문가는 분석패턴과 지식 뽀개기 작업을 통해서 거대한 문제 영역을 정제하는 작업을 수행한다. 이를 통해 더 관리하기 쉬운 서브 도메인으로 나누게 된다.
이러한 정제 작업은 핵심 서브도메인을 드러나게 한다. DDD는 핵심 서브 도메인에 집중하라고 강조한다. 이것은 어플리케이션의 성공을 위한 핵심 키이며, 가장 가치있는 영역이다.

이것은 어디에 노력을 쏟을지 명확히 하는 것으로 시스템에서 덜 중요한 부분은 오픈 소스로 해결하도록 한다 이를 통해 핵심 도메인 영역이 BBOM이 되지 않도록 무엇이 중요한지에 대해서 더 많은 시간을 쏟도록 해준다.

핵심 도메인을 찾는 작업은 소프트웨어를 개발하는 이유를 이해하게 해며 비즈니스에서 성공적으로 소프트웨어를 생성하는 것을 도와준다. 이것은 개발팀이 시스템의 가장 중요한 부분에 더 많은 투자를 하게 해주며, 비즈니스를 발전 시키도록 해준다. 또한 핵심 영역에 코드 퀄리티를 위한 투자는 비즈니스 변경을 도와준다. 핵심 영역이 시너지를 발휘하지 못하게 되면 비즈니스 도메인은 더 많은 시간을 들여야 하고, 부패되어 가며, 진흙속의 큰 공처럼 변해가게 된다, 결과적으로 관리하기 어려운 소프트웨어로 변질된다.

2. 도메인 문제를 해결하기 위한 모델 생성 

솔루션 공간에서 소프트웨어 모델은 각 도메인 문제들을 해결하기 위한 각 서브도메인을 생성하고, 비즈니스 윤곽에 대해서 정렬하는 역할을 한다. 이 모델은 실제 삶의 모델은 아니다. 그러나 비즈니스 도메인의 룰과 로직을 획득하는 동안 비즈니스 유즈케이스의 요구사항을 만족하기 위해서 더욱 추상화 되어진다.

개발팀은 많은 에너지를 모델과 도메인 로직에 대해서 애플리케이션의 순수 기술적인 관점에서 쏟게 된다. 기술적으로 복잡한 모델을 피하기위한 것으로 인프라 스트럭쳐 코드로 부터 고립되어 작업이 된다.

모든 모델들이 같은 모양으로 생성되지 않는다. 대부분 적합한 디자인 패턴이 있고 전체 시스템에 적용되는 것보다 각 서브도메인의 복잡도에 대한 니즈에 기반하여 사용된다. 서브도메인의 모델들은 프러덕트의 성공을 위한 코어는 아니다. 이것은 풍부한 Object-oriented design을 기반으로 하지는 않는다. 그리고 이것들은 더 절차적이거나 데이터 기반의 아키텍쳐일 수 있다.

3. 모델링 협업을 가능하게 하기 위한 공유 언어의 사용 

모델은 도메인 전문가와 개발팀의 협업을 통해서 수행된다.
커뮤니케이션은 계속해서 발전되는 공유 언어인 ubiquitous language(UL)을 이용하여 달성된다. 소프트웨어 모델은 분석모델과 연결되며 이때 구조와 클래스 설계를 위한 UL용어와 동일한 용어를 사용한다. 통찰력, 개념, 용어들은 UL에서 복제된 코딩 레벨에서 발견된다. 그리고 분석 모델로 이어진다. 유사하게 비즈니스는 분석모델 레벨에서 숨겨진 개념이 드러나게 된다. 이러한 통찰력은 다시 코드 모델에 피드백 되어진다. 이것이 핵심이다. 이 핵심이 도메인 전문가와 개발팀에게협업 속에서 계속적인 발전된 모델을 만들게 한다.

4. 모호성과 부패로부터 모델을 분리시키기 

모델들은 컨텍스트 경계 내에 놓여진다. 이것은 모델의 적용 가능성을 정의하고, 통합되어 진다. 큰 모델은 작은 모델로 분할될 수 있다. 그리고 분리된 컨텍스트 영역내에 정의 되어질 수 있다. 모호한 용어들이 존재하는 곳이나 복수팀들은 복잡성을 줄이는 목적으로 작업이 수행된다.

경계 지어진 컨텍스트는 모델 주변 경계의 보호하에 사용된다. 이것은 소프트웨어가 BBoM으로 변질되는 것을 막는다. 이것은 전체 솔루션 내에서 잘 정의된 비즈니스 컨텍스트 내에서 발전이 거듭될 수 있도록 허용하고, 시스템의 다른 파트에 영향을 주지 않을 때 달성된다. 모델은 비즈니스 개념과 기술적인 내용이 기존 복잡도에 우연히 엮이지 않도록 인프라 스트럭쳐 코드로 부터 떼어내어 져야한다. 영역지어진 컨텍스트는 isolating을 통해서 부패된 모델과 통합되는 것을 맊는다.

5. 컨텍스트들 간에 관계 이해하기.

DDD는 팀들과 비즈니스들이 어떻게 모델을 분리하고, 컨텍스트들이 서로 작업하여 도메인 문제를 해결할지에 대해서 명확히 해야할 필요가 있다는 것을 이해한다. 컨텍스트 맵들은 더 큰 그림을 이해할 수 있도록 도움을 준다. 이것은 어떠한 모델들이 존재하고, 어떻게 책임을 지고 있으며, 그것들의 어플리케이션 바운더라가 어디 있는지 팀들이 이해할 수 있도록 해준다. 이 맵은 서로다른 모델들이 어떻게 상호작용 하고, 비즈니스 처리를 위해 교환될 데이터들이 무엇인지 드러나게 한다.

BIG BALL OF MUD가 항상 안티패턴은 아니다. 

거대한 어플리케이션의 모든 부분이 완벽하게 디자인 되는 것은 아니다. 또한 그렇게 되어야만 하는 것도 아니다. BBOM이 전체 엔터프라이즈 소프트웨어에 추천할 만한 것은 아니지만 여전히 유용하기는 하다. 낮은 복잡도 영역 혹은 완벽한 코드 퀄리티를 필요로 하는 것이 아닌 경우에는 돌아가는 코드로만 충분하다. 가끔 가능한 빨리 소프트웨어를 동작하게 하는게 필요할 수 있다. 코드 쿠러리티는 항상 비즈니스 다음으로 향상될 수 있다. 이것은 계속적이고 장기적인 좋은 투자를 통해서 가능하다. BBoM의 이점을 얻기 위한 키는 핵심 서브 도메인을 깨트리는 것을 피하는 영역 내에서 수행해야 한다. 

DDD의 전술적 패턴 

DDD의 전술적 패턴은 역시 알려진 모델 빌딩블록이다 이것은 패턴의 집합체이며, 복잡한 경계 영역의 컨텍스트에 대해서 효과적인 모델을 생성하는 것을 돕는다. 코딩패턴의 많은 부분은 전술 패턴의 집합 내에 이루어진다. 이것은 Eavans의 텍스트 이전에 Martin Fowler in Patterns of Enterprise Application Architecture와 Eric Gamma 등의 Design Pattern : Elements of Reusable Object-Oriented Software 같은 것들에 의해서 넓게 채택되던 것이다. 이러한 패턴은 모든 모델에 적용될 수는 없다. 이는 아키텍처에 따라 적용되는 스타일에 따라 적합하게 채택 되어야 한다.

문제 영역과 해결 영역 

문제 영역은 몬제의 복잡도를 관리하는 측면이며, 해결 영역은 솔루션에 대한 복잡도를 관리하는 것을 말한다. 이 문제 영역은 문제 영역을 정제하여 더 관리하기 쉬운 서브 도메인을 분리하여 관리하게 된다. DDD의 문제 영역에 대한 영향력은 중요한 것이 무엇인지, 그리고 노력을 집중해야할 곳이 어디인지 드러나게 하는데 있다.
솔루션 측면에서의 DDD는 애플리케이션을 다듬게 하여 더 쉽게 관리할 수 있도록 하는데 있다.


DOMAIN-DRIVEN DESIGN의 실천과 원칙 

핵심 도메인에 집중하기 

DDD는 핵심 도메인에 노력을 집중하게 요구한다. 이 핵심 서브 도메인은 프러덕트 영역에서 프로젝트의 성공과 실패 를 결정 짓는다. 핵심 도메인은 경쟁력을 제공하며, 비즈니스의 실제 가치를 생성한다. 무엇이 코어 도메인인지 이해하는 것이 팀의 생존 전략이다.

협업을 통한 배움

DDD는 갭라팀과 비즈니스 전문가가 문제를 해결하기 위한 가장 유용한 모델을 찾기 위해 협업을 중요하게 강조한다. 이러한 협업과 비즈니스 전문가로 부터의 약속 없이 지식의 공유는 이루어 지지 않게 된다. 그리고 개발 팀은 문제 영역에서 큰 영감을 얻을 수 없게 된다. 협업과 지식 뽀개기를 수행하게 되면 해당 도메인에 대해서 많은 배움을 얻을 기회를 얻게 될 것이다.

탐색과 경험을 통한 모델의 생성 

DDD는 분석과 코드 모델을 하나처럼 다룬다. 이것은 기술적 모드 모델은 공유된 UL을 통해서 분석 모델에 연결 된다. 분석 모델의 돌파구는 코드 모델의 변화를 가져온다. 코드 모델의 리팩토링은 비즈니스의 멘탈코델과 분석 모델에 반영된다. 팀이 모델을 탐험하고, 디자인에 대한 경험을 받게 된 경우에만 이러한 돌파구가 생성이 된다. 프로토 타이핑에 시간을 보내고 오랜 기간 경험을 수행하면서 더 낳은 디자인으로 다듬어 지게 된다. 또한 바보같은 디자인을 무엇인지 드러나게 된다. Eric Evans는 좋은 디자인에는 반드시 적어도 3가지의 나쁜 것이 있다, 이것은 처음 유옹한 모델에서 팀이 정체 되어 있는 것을 막게 될 것이다 라고 제안했다.

커뮤니케이션 

문제영역을 대표하는 모델에 대해 효과적으로 설명하는 능력은 DDD의 기반이 된다. DDD의 가장 중요한 단 하나의 측면은 UL의 생성이다. 이것은 의심의 여지가 없다. 공유된 언어가 없이 비즈니스와 개발팀의 협업은 효과적으로 문제를 해결하기 어렵게 한다. 분석과 심적 모델들은 지식 뽀개기 세션에서 생산된다. 팀들은 공유된 언어를 기술적 구현을 하고 상호간에 연결을 위해서 필요하게 된다.  문제 영역 내에서 커뮤니케이션 아이디어와 솔루션에 대한 효과적인 방법이 없이는 설계에 대한 돌파구가 발생되지 않는다. 협력과 UL의 생성은 DDD를 더 강력하게 만들어 준다. 이것은 문제 영역을 더욱 이해하기 쉽도록 해주며 더 효과적으로 커뮤니케이션 하게 해준다. 핵심 가치는 기술적 프레임워크들과 방법들이 더 중요해질수록 DDD는 더욱더 큰 위치를 차지한다. 결과적으로 소프트웨어 제품을 성공적으로 만들어 준다.

모델의 적용가능성의 이해 

각 모델은 서브도메인의 컨텍스트와 UL의 사용에 대한 이해에 기반해서 만들어진다. 그러나 많은 큰 모델은 UL에 대한 모호성이 있을수 있다. 이것은 서로다른 조직이 서로다른 이해를 바탕으로 공통의 언어나 개념에 대해서 해석하기 때문이다. DDD는 각 모델은 각자가 가진 UL이 있다고 말한다. 이것은 특정 컨텍스트 에서만 유용하다. 각 컨텍스트는 언어적인 영역에 의해서 정의되어진다. 모델들을 보장하는 것은 언어가 가지는 모호성을 피하여 제한된 컨텍스트 내에서 유일함이다. 그러므로 모델에서 겹치는 용어에 대해서는 2개의 모델로 분리를 해야한다. 각기 가지는 컨텍스트 내에서 명확히 정의 되어야 한다.

모델의 지속적인 발전 

복잡한 시스템에서 작업하는 어떤 개발자들은 좋은 코드를 작성하고 짧게 유지보수를 하는 사람이 있다. 그러나 소스코드와 문제 영역 사이에 시너지가 없이 계속적인 개발은 코드 기반의 작업으로 귀결된다. 이것은 변경이 어렵고 결과적으로 BBoM이 된다. DDD는 현재 문제에서 도메인이 얼마나 유용한지 계속적으로 살피도록 팀에게 강조한다. 이러한 도전은 팀이 발전하게 하고 복잡한 도메인 모델을 단순화 하게 하여 도메인 내에서 통찰력을 획득하도록 해준다. DDD는 여전히 은탄환은 아니다. 그리고 생성된 소프트웨어에 대해서 지식 뽀개기를 지속적으로 요구한다. 단순히 한 두달이 아니라 몇년동안 지속되도록 요구한다. 새로운 비즈니스 케이스는 이전의 유용한 모델을 깨트린다. 혹은 새롭게 변경하거나 기존에 있는 개념을 더욱 명확하게 하도록 도와준다.


가장 잘 알려진 DOMAIN-DRIVEN DESIGN의 오해 

아마 DDD가 개발 철학으로 생각할 수 있다. 이것은 도메인 중심의 생각 하도록 촉진한다. 이것은 프로세스를 배우는 것이고, 목적이 아니다. 이것이 DDD의 매우 강력한 점이다. 어떤 팀은 몇가지 유즈케이스 셋의 필요에 의해서 소프트웨어 프로덕트를 작성할 수 있다. 그러나 팀은 문제 영역에 시간을 들이고 노력을 들여야 한다. 그리고 새로운 비즈니스 유스케이스에 대해서 프로덕트를 지속적으로 발전 시켜야 한다. DDD는 제약적인 방법론이 아니다. 이것은 반복적인 소프트웨어 프로젝트 방법론으로 유용한 모델을 만들고 발전 시키기 위한 방법이다.


1. 전술 패턴은 DDD의 키이다 

DDD는 객체지향 설계애 대한 책은 아니다. 또한 코드 중심의 철학이나 패턴 언어는 더더욱 아니다. DDD를 웹에서 찾아보면 구현패턴이나, 모델링 패턴에만 집중된 블로그들을 보게 되어 오해하게 된다. 이것은 개발자들에게는 DDD의 기술적인 부분에 대한 코드가 비즈니스 사용자와 팀이 도메인에 기반한 대화보다도 더 쉽게 보여진다. 이러한 이유로 DDD가 가끔 패턴 언어, 밸류 객체, 리포지토리 이상은 아니라고 오해하게 된다. 사실 DDD구현시 리치 도메인 메돌 생성 없이 혹은 리포지토리 없이 구현 가능하다. DDD는 소프트웨어 디자인 패턴에 대한 부분은 작은 부분이며 협업을 통한 문제 해결이 더 강조 된다.
Evans는 개발팀과 비즈니스 전문가에 의해서 UL을 통해 생성된 모델이 소프트웨어 개발 패턴을 사용하는 것에 대한 기술적인 부분을 표현했다. 그러나 분석적인 실천이나, 협업, 실제 도구의 코딩 구현에 대해서는 부족했다. DDD는 코드 중심이 아니다. 이것의 목적은 우아한 코드를 작성하는 것이 아니다. 소프트웨어는 단지 DDD의 산출물이다.

2. DDD는 프레임워크이다. 

DDD는 특정 프레임워크나 데이터베이스를 요구하지 않는다. 모델은 코드에 구현되어지며 POJO 원칙을 따른다. 이것은 다른 인프라 스트럭쳐 코드가 전혀 없이 도메인에 집중된 모델로 산만하지 않다. 객체지향 방법론은 개발을 위한 유용한 모델이다. 그러나 필수는 아니다.
DDD에는 반드시 따라야하는 한가지 설계 스타일이라는 것이 없다. Evans의 텍스트에는 레이어화 된 스타일의 아키텍처로 표현되었다. 그러나 이것은 옵션일 뿐이다. 아키텍쳐적인 스타일은 다양할 수 있다.

3. DDD는 은탄환이다. 

DDD는 많은 노력을 요한다. 이것은 반복적인 개발 방법론을 요구하고, 비즈니스에 집중하고 스마트한 개발자를 필요로 한다. 모든 소프트웨어 프로제그는 DDD의 분석적인 실천으로 이득을 얻을수 있으며 이는 문제 영역을 전략적인 패턴에 따라 코드 모델에서 분리하여 도메인 로직을 표현하는 것으로 잘 정제할 수 있다.그러나 DDD에서는 리치 도메인 모델의 기술적인 패턴 전부는 아니다. 중요하지 않은 도메인은 세련된 레벨의 도메인을 보장하지는 않는다. 그것들은 미미하거나 도메인 로직이 없다. 예를 들어 단순한 블로그를 만드는데 DDD의 모든 패턴을 사용하는 것은 시간과 비용의 낭비이다.

핵심 포인트 

1. DDD(Domain-Driven Design)은 개발철학이다. 이것은 복잡한 문제 영역의 소프트웨어를 작성하고 생성, 유지하기 위한 관리적인 형태로 디자인된다.
2. DDD는 패턴, 원칙, 실천의 집합체이다. 이것은 복잡도를 관리하기 위해 적용될 수 있다.
3. DDD는 2개의 패턴 타입이 있다. 전략 패턴은 솔루션을 다루며 전술적 패턴은 리치도메인을 구현하기 위해서 사용된다. 전략 패턴들은 어떠한 어플리케이션에서든지 유용하다. 그러나 전술적 패턴은 오직 충분한 도메인 로직 내에서만 유용하다.
4. 큰 문제 영역의 정제는 스브 도메인들로 나눠지고 여기에서 핵심 도메인이 드러나게 된다. 시스템의 전체 부분이 디자인되어지는 것은 아니다. 팀은 핵심 도메인 영역에 더 많은 노력과 집중을 투자해야한다.
5. 추상 모델은 도메인 문제를 관리하기 위해 각 서브 도메인을 위해 생성된다.
6. ubiquitous language (UL)은 부석 모델을 코드 모델에 바인드 하기 위해 사용된다. 이것은 개발팀과 도메인 전문가들이 모델을 디자인할때 상호 협업을 위해 사용된다. 배움과 문제 영역에 대한 커메뉴케이션을 위해서 언어가 생성되어지며 이는 DDD의 과정중에 하나이다. 코드는 산출물이다.
7. 모델의 통합을 유지하기 위해서 바운더리 컨텍스트내에 정의 되어진다. 모델은 인프러 스트럭쳐 코드에서 고립되어 지며 이는 비즈니스 복잡도로 부터 기술적인 복잡도를 분리하기 위한 개념이다.
8. 모델에 대한 용어상에 모호성이 있는 곳이나 복수의 팀이 모델에 대한 작업을 수행하는 곳에서는 작은 bounded context로 나누어 정의 될 수 있다.
9. DDD는 개발자를 위한 특정 아키텍처 스타일을 지정하지 않는다. 이것은 오직 기술적 복잡도로 부터 분리시켜 도메인 로직에 집중할 수 있도록 해준다.
10. DDD 가치는 핵심 도메인에 집중하고, 협업하며, 도메인 전문가와 탐험 하는 것, 그리고 더욱 유용한 모델을 생산해 내기 위해서 경험하고 다양한 컨텍스트의 이해를 복잡한 문제 영역에서 수행하는 것이다.
11. DDD는 패턴 언어가 아니며, 전달에 집중된 협업 철학이다. 중심적인 롤에 커뮤니케이션 하는 것이다.
12. DDD는 소프트웨어 개발을 위한 언어와 도메인 중심의 접근이다.










Gradle Java Quickstart.

Gradle Java Quickstart.

from : https://docs.gradle.org/current/userguide/tutorial_java_projects.html

1. The Java Plugin 

자바 Gradle는 일반 목적의 빌드 툴이다. 빌드스크립트에 많은 노력을 들이지 않더라도 빌드를 수행할 수 있다. 빌드 스크립트를 추가하지 않는경우 빌드를 수행하지 않는다. 
대부분의 자바 프로젝트는 유사하게 자바소스 파일을 컴파일 해야한다. 테스트를 돌리든지, JAR파일내의 클래스를 생성하든지, 그런대로 나은점은 각 프로젝트마다 이런 모든 코드를 할 필요는 없다는 것이다. 운 좋게도 Gradle는 이런 작업을 하지 않아도 된다. Gradle는 plugins를 이용하여 이러한 문제들을 해결한다. 플러그인은 몇가지 방법으로 프로젝트 설정을 확장한다. 보통 몇가지 사전 설정 작업을 수행함으로 해서 다른 유용한 동작과 함께 수행된다. Gradle는 쉽게 당신의 코드에 추가하거나, 다른 프로젝트와 공유할 수 있도록 플러그인을 제공하고 있다. 이러한 플러그인중 하나는 Java Plugin이다. 이 플러그인은 당신의 프로젝트에 몇가지 태스크를 추가한다. 이것은 컴파일하고 유닛테스트를 수행하고 Jar 파일을 생성하는 작업이다. 
Java Plugin은 관습적인 기반을 갖는다. 이것의 의미는 플러그인은 기본값을 지정하여 프로젝트의 많은 부분에 설정된다. 예를 들면 Java Source Files의 위치를 지정하는 것을 들 수 있다. 이러한 관습을 따른다면 빌드 스크립트를 작성할때 많은 노력을 들지 않아도 된다. Gradle는 관습을 따르지 않기를 원한다면, 프로젝트를 커스터마이즈 하게 해준다. 사실 자바 프로젝트에 빌드를 위해서 모든 플러그인을 사용할 필요가 없다. 이것은 자바 프로젝트의 지원은 플러그인으로 구현되어 있다. 
Gradle은 Java Plugin, 의존성관리, 복합 프로젝트 빌드 등에 대한 많은 부분을 깊이있게 다루고 있다.
이 챕터에서는 일반적인 빌드 관련 사항에 대해서 살펴볼 것이다. 


2. A basic Java project

간단한 예제를 보자. Java Plugin을 이용하기 위해서 다음 내용을 빌드 파일에 넣자. 

Example 7.1. Using the Java plugin
build.gradle
apply plugin: 'java'
Note : 이 예지의 코드들은 samples/java/quickstart 파일에서 찾을 수 있다. 
이 코드는 모든 자바 프로젝트에 정의해야한다. 이것은 Java Plugin을 프로젝트에 적용하고 프로젝트에 몇가지 태스크를 추가할 것이다. 

어떤 태스크들이 가능한가?

gradle tasks를 사용하여 프로젝트의 태스크 리스트를 살펴 볼 수 있다. 이것은 프로젝트에 추가된 Java plugin에 대한 태스크 리스트를 보여준다. 
Gradle는 생성되는 모든 자바 코드는 src/main/java 아래 생성되 있다고 기대한다. 또한 테스트 코드는 src/test/java에 들어 있다고 생각한다. 추가적으로 파일들은 src/main/resources에 들어가며 이는 JAR파일내의 리소스가 들어간다. 테스트를 위해서 필요한 리소스는 src/test/resources 아래 들어가게 된다. 모든 출력 파일들은 build 디렉토리 하위에 들어가며, JAR파일들은 build/libs디렉토리에 최종적으로 만들어진다. 

2.1. Building the project

Java plugin은 몇가지 태스크를 프로젝트에 추가하게 된다.
가장 공통적으로 사용되는 태스크는 build태스크이다. 이것은 프로젝트를 full build를 수행한다. gradle build를 실행하면 Gradle는 컴파일과 테스트를 수행한다. 그리고 메인 클래스와 리소스를 추가한 JAR파일을 생성한다. 

Example 7.2. Building a Java project
Output of gradle build
> gradle build
:compileJava
:processResources
:classes
:jar
:assemble
:compileTestJava
:processTestResources
:testClasses
:test
:check
:build

BUILD SUCCESSFUL

Total time: 1 secs
몇가지 유용한 태스크는 다음과 같다. 
clean
build 디렉토리를 삭제하고 모든 빌드 파일을 제거한다. 
assemble
컴파일과 jars를 수행한다. 그러나 유닛 테스트는 수행하지 않는다. 다른 플러그인은 이 태스크에 추가적인 artifacts를 추가한다. 예를 들어 War플러그인을 사용하면 이 작업은 WAR파일을 빌드하게 된다. 
check
컴파일과 테스트를 수행한다. 다른 플러그인은 이 작업을 위해 다 많은 체크를 추가한다. 예를 들어 만약 checkstyle플러그인을 수행하면 이 것은 소스코드에 대해서 체크 스타일을 수행한다. 

2.2. External dependencies

일반적으로 자바 프로젝트는 외부 JAR파일들에 의존성을 가지게 된다. 프로젝트에서 이러한 JAR파일들을 참고하기 위해서는 Gradle에 그것을 어디에서 찾을 수 있을지 알려 주어야 한다. Gradle에서는 JAR파일들과 같은 aritifacts 들은 repository에 위치하게 된다. repository는 프로젝트의 의존성을 패칭하기 위해서 사용되어야 한다. 혹은 프로젝트의 아티팩트들을 퍼블리싱 하기 위해서 필요하다. 이 예제에서 우리는 공용 Maven 프로젝트를 사용할 것이다. 

Example 7.3. Adding Maven repository
build.gradle
repositories {
    mavenCentral()
}
몇가지 의존성을 추가해보자. 여기에 우리는 컴파일 시점에 commons collections과 junit을 추가할 것이다. 

Example 7.4. Adding dependencies
build.gradle
dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

2.3. Customizing the project

Java plugin은 프로젝트에 프로퍼티들의 몇개를 추가한다. 이 프로퍼티들은 기본값을 가진다. 이 값들을 가지고 시작을 위해서는 충분하다. 이값들이 적합하지 않을경우 변경하는 것은 매우 쉽다. 우리는 자바 프로젝트의 버젼 넘버를 지정할 것이다. 다음으로 우리는 JAR manifest를 추가할 수 있다.  

Example 7.5. Customization of MANIFEST.MF
build.gradle
sourceCompatibility = 1.5
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart',
                   'Implementation-Version': version
    }
}

어떤 프로퍼티들이 가능한가?

gradle properties 를 이용하여 프로젝트의 리스트를 확인할 수 있다. Java plugin에 의해서 추가된 프로퍼티들을 보게 해준다. 
Java plugin이 추가한 태스크는 regular 태스크이다. 빌드파일에 설정된 것과 완젼히 동일하다. 이 의미는 이전 챕터에서 본 이러한 태스크들을 커스터마이즈 하는 메커니즘을 사용할 수 있다는 것이다. 예를 들면 태스크의 프로퍼티를 설정할수 있고 태스크에 대한 행위를 추가하고, 태스크의 의존성들을 벼경하거나 태스크들을 교체할 수 있다. 우리의 예제에서는 test태스크를 설정할 것이다. 이것은 Test의 타입이며 테스트들이 수행되어질때 시스템 프로퍼티가 추가된다.  

Example 7.6. Adding a test system property
build.gradle
test {
    systemProperties 'property': 'value'
}

7.2.4. Publishing the JAR file

보통 JAR 파일들은 어딘가 퍼블리시되어야 한다. 이것을 위해서 Gradle에는 JAR파일에 퍼블리시 될 위치를 알려 주어야 한다. Gradle에서는 JAR파일들과 같은 아티팩트들은 프로퍼티들에 퍼블리시 되어진다. 우리의 샘플에서 우리는 로칼 디렉토리에 퍼블리시 될 것이다. 또한 원격 위치에 퍼블리시 되거나 복합적인 위치에 퍼블리시 되어야 한다. 

Example 7.7. Publishing the JAR file
build.gradle
uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}
JAR파일을 퍼블리시 하기 위해서 gradle uploadArchives를 수행하자. 

7.2.5. Creating an Eclipse project

Eclipse-specific 디스크립트 파일들이며 .project와 같은 파일을 생성하는 것이다. 빌드 파일에 다른 플러그인을 추가할 필요가 있다. 

Example 7.8. Eclipse plugin
build.gradle
apply plugin: 'eclipse'
이제 gradle eclipse 커맨들르 실행하여 Eclipse프로젝트 파일을 생성하자. 

7.2.6. Summary

우리의 샘플을 위해서 완벽한 빌드 파일은 다음과 같다. 

Example 7.9. Java example - complete build file
build.gradle
apply plugin: 'java'
apply plugin: 'eclipse'

sourceCompatibility = 1.5
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart',
                   'Implementation-Version': version
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

test {
    systemProperties 'property': 'value'
}

uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}


3. Multi-project Java build

복수 프로젝트 빌드를 살펴보자. 아래 프로젝트 레이아웃을 보자. 

Example 7.10. Multi-project build - hierarchical layout
Build layout
multiproject/
  api/
  services/webservice/
  shared/
  services/shared/
Note : 이 예제의 코드는 samples/java/multiproject에서 찾을수 있다. 
여기에는 4개의 프로젝트를 가지고 있다. api프러덕트는 JAR파일로 XML웹서비스의 Java client 를 담고 있다. webservice는 XML을 반환한다. shared 는 api와 sebservice양쪽에서 사용되는 코드를 담고 있다. services/shared는 shared프로젝트에 의존되는 코드를 담고 있다. 

3.1. Defining a multi-project build

multi-project빌드를 정의하기 위해서는 settings파일을 생성해야한다. 이 settings파일은 소스 트리의 루트 디렉토리에 존재하며, 빌드에 포함될 프로젝트를 지정한다. 이것은 settings.gradle 라 불리며, 이 예제에서는 단순한 계층구조의 레이아웃을 이용하고 있다. 

Example 7.11. Multi-project build - settings.gradle file
settings.gradle
include "shared", "api", "services:webservice", "services:shared"

3.2. Common configuration

대부분의 멀티 프로젝트 빌드를 위해서 몇가지 설정이 있다. 이것은 모든 프로젝트에 공통으로 적용된다. 우리의 예제에서는 루트 프로젝트에 공통 설정을 할것이다. 이것은 configuration injection이라고 불린다. 루트 프로젝트는 컨테이너와 같다. 그리고 subprojects메소드는 이 컨테이너의 엘리먼트들을 순회하며 특정 설정을 인젝트 한다. 이 방법은 모든 아카이브들을 위해 manifest 컨텐츠를 정의하기 쉽게 하고, 몇가지 공통 의존성들을 설정하기 쉽게 해준다. 

Example 7.12. Multi-project build - common configuration
build.gradle
subprojects {
    apply plugin: 'java'
    apply plugin: 'eclipse-wtp'

    repositories {
       mavenCentral()
    }

    dependencies {
        testCompile 'junit:junit:4.12'
    }

    version = '1.0'

    jar {
        manifest.attributes provider: 'gradle'
    }
}
우리 샘플에서는 자바 플러그인을 각 하위 프로젝트에 적용하였다. 이것은 태스크들과 설정 프로퍼티들을 의미하며 이전 섹션에서 보았던 각 서브 프로젝트 내에 설정한 내용들이다. 이제 컴파일과 테스트 그리고 JAR 파일 생성을 gradle build를 통해서 수행할 수 있다. 
또한 이 플러그인들은 subprojects 섹션에서 적용되어지며 루트 레벨에서는 적용이 되지 않는다. 그리고 루트 빌드는 루트 프로젝트 내에서 자바 소스 파일들을 찾을 것으로 기대하지 않는다. 오직 서브 프로젝트에서 찾기를 바란다. 

3.3. Dependencies between projects

동일 빌드내에 프로젝트들 사이에 의존성을 추가할 수 있다. 예를 들면 하나의 프로젝트에 대한 JAR파일이 다른 프로젝트의 컴파일에 사용되어진다. api빌드 파일은 shared프로젝트의 의존성이 추가될 것이다. 때문에 이 의존성에 대해서 Gradle는 프로젝트 shared 프로젝트는 api프로젝트 이전에 빌드를 보장한다.

Example 7.13. Multi-project build - dependencies between projects
api/build.gradle
dependencies {
    compile project(':shared')
}

3.4. Creating a distribution

우리는 배포를 추가할 수 있다. 이것은 클라이언트에 적재 되어진다. 

Example 7.14. Multi-project build - distribution file
api/build.gradle
task dist(type: Zip) {
    dependsOn spiJar
    from 'src/dist'
    into('libs') {
        from spiJar.archivePath
        from configurations.runtime
    }
}

artifacts {
   archives dist
}