Spring 3.0 m1이 지난 12월 중순에 발표되었다. Spring3.0 기준으로 책을 쓰고 있는 내 입장에서는 거의 실시간으로 3.0을 분석하고 연구하고 많은 테스트를 해가면서 책을 만들어가야한다. 그래서 앞으로 Spring3.0을 분석하면서 알게된 것들, 가졌던 생각들을 여기에 시리즈로 남겨보려고 한다. 일단 오늘은 그 첫번째로 새로운 프로젝트 구조와 빌드시스템의 변화에 대한 것이다. 스크롤의 압박이 살짝 있으니까 좀 여유있을 때 읽는 것이 좋겠다. (특히 영회! 대충 훑지 말고 꼼꼼히 읽을 것)

 

프레임워크 자체의 기능적인 변화는 2.5에서 도입된 애노테이션 설정을 좀 더 유연하고 폭넓게 사용할 수 있도록 조금 발전한 것 정도 외에 그리 주목할만한 것은 없다. 아마 3.0 전반에 걸쳐서도 2.5의 변화만큼 큰 폭의 변화는 없을 것이다. 그런면에서 메이저버전의 업그레이드 치고는 기대이하이다라고 생각할 사용자들도 있을지 모르겠다. 애노테이션에 EL정도 쓰고, 이미 큰 변화가 있었던 @MVC에 기능이 조금 추가된 것은 대단한 것이 아니라고 생각할 수도 있다. 하지만, 2.5의 새로운 스프링의 설정과 개발모델을 적극적으로 적용하려고 애썼던 개발자라면, 사실 3.0이 주는 그 미묘한 차이들이 "매우" 중요하다고 느낄 것이다. 어쩌면 2.5가 3.0이고 3.0이 3.1이 됐어야 했는지도 모르겠다. 2.5로 남았던 가장 큰 이유는 아마도 변화의 중간단계를 거침으로 해서 이후의 등장할 버전이 주는 변화의 충격 내지는 낯설음을 최소화하고, 또 새로운 시도에 대한 변화에 대해 얼리어답터들의 현장적용후 돌아오는 피드백을 충분히 받아서 그것을 토대로 부족한 부분을 보완하여 어느정도 검증된 안정적인 모습으로 3.x 단계에 안착하기 위함일 것이다.

 

또 한가지 주목할만한 부분은 2.5가 기존의 프로젝트구조와 기반이 되는 자바기술레벨을 최대한 유지한 채로 기능을 중심으로 확장한 것이라면, 3.0은 그부분에서 과감한 변신을 시도한다. 즉, 2.5에서 바뀐 프로그래밍 스타일과 API와 같은 외부 인터페이스는 일정 부분 보완하는 것으로 그치지만, 프레임워크의 내부와 그 자체의 기술적인 특성은 1.0이래로 가장 큰 변화를 주게된다.

3.0은 자바의 언어적인 면에서 가장 큰 변화가 있었던 Java5로 소스코드 자체를 모두 업그레이드 하고 있다. 물론 기존에도 JDK1.5, 1.6의 최신 기능을 필요한 곳에 최대한 적용했다. 컨테이너 기동시 JDK버전을 체크해서 주요한 기능에서 각 JDK에 맞는 최적화된 또는 호환성이 보장되는 JDK API를 사용하도록 되어있었다. 따라서 당연히 스프링 자체가 사용하는 JDK레벨도 1.5+으로 상승될 뿐만 아니라, 그에 따른 언어적인 변화들, 애노테이션이나 제너릭스 같은 부분들이 스프링 자체에서 적극 사용된다. 당연히 API레벨에서도 그동안 불편했던 부분들이 최대한 보완이 될 것이다. 물론 그럼에도 기존버전을 기반으로 작성된 코드가 동작하는데는 아무런 문제가 없도록 API레벨에서는 완벽한 구버전호환성을 제공할 것이다.

보통 이렇게 코드의 전반적인 기술변화가 있을 때는 "새로운 버전은 모든 코드를 맨땅에서 부터 다시 깔끔하게 작성했습니다~"라고 내세우는 오픈소스 프로젝트들이 많이 있다. 사실 그 말은 "기존 코드는 엉망으로 만들어진 스파게티 코드라서 발전시키고 보완하는 것보다 새로 짜는게 났습니다"라는 뜻이다. 동시에 사용자 입장에서는 "이 새버전은 정식버전이 나와봤자 엄청난 버그투성일 것이 분명하니 멋모르고 쓴 멍청한 사용자들이 먼저 고생고생하는 과정을 거치며 몇 단계 더 마이너 업그레이드 되기 전에는 절대 사용하지 말자" 라고 받아들이게 된다. 그래서 나는 메이저 버전 업데이트시 코드를 처음부터 새로 개발하는 프로젝트는 일단 신뢰하지 않는다.

구지 기존 코드를 다 버리고 새로 개발하지 않더라도 오픈소스 제품의 버전 업그레이드는 구버전과의 호환성를 보장하지 못하는 경우가 많다. 사소한 API의 변화 정도라면 어떻게 수용해보겠지만, 프로그래밍 모델이 바뀌고 기존 버전에서 작성한 코드를 그대로 사용할 수 없는 경우엔 매우 불편하고 짜증이 난다. 호환성이 보장 안되는 이유는 프레임워크의 설계 자체가 자꾸 바뀌기 때문이다. 단순하고 빠르게 웹 애플리케이션을 개발할 수 있다는 RoR 같은 경우 이제 2.2버전이 나왔다. 큰 틀이 확 바뀐 것은 아니지만 버전이 올라갈 때마다 기존 버전으로 개발한 코드를 그대로 가져다 쓸 수 없는 호환성의 문제를 계속 가지고 있다. RoR의 최대 장점 중의 하나가 다양한 플러그인 시스템이다. 역시 버전에 따른 플러그인의 적용 가능성도 문제가 된다. 심지어 "플러그인을 사용하려면 그 소스를 모두 분석해볼 각오가 있어야 한다"라는 이야기도 들었다. 끔찍한 얘기다.

바로 그런면에서 스프링의 발전과정은 놀랍다. 특정 영역과 기술에 제한된 프레임워크도 아닌고, 엔터프라이즈 영역의 거의 모든 계층과 모든 기술을 총 망라하고 있고, 한 기술에 대해서도 다양한 계층의 추상 프로그래밍 모델을 지원하는 스프링이 1.0부터 시작해서 지금 3.0에 이르기까지 거의 완벽에 가까운 기존 버전 호환성을 유지하고 있는 것은 정말 대단한 일이 아닐 수가 없다. 스프링의 소스 자체를 깊이 분석해본 사람이라면 그만큼 빠르게 발전하고, 대규모인 소스코드가 그렇게 유연하고 확장성이 뛰어난 형태로 만들어 질 수 있었다는 사실에 놀라지 않을 수가 없을 것이다. 스프링은 이미 1.0부터 그런 확장을 위한 거의 모든 준비가 다 되어있었다. 예를 들어 @Autowired같은 애노테이션을 이용한 DI를 생각해보자. 이 기능을 추가하기 위해서 스프링의 핵심 컨테이너의 구조를 바꾸고 핵심 코드를 뜯어고졌을까? 아니다. 스프링이 그토록 강조하는 DI를 이용해서 컨테이너 자체를 간단히 확장시켰을 뿐이다. Open-Close-Principle을 가장 잘 지켜서 만든 프레임워크가 바로 스프링이 아닐까? 그만큼 스프링은 확장에 대해서 유연하다. 그것은 비단 스프링 자체 개발자 뿐만 아니라, 스프링을 사용하는 일반 개발자도 얼마든지 가능하다. 그래서 그토록 다양한 스프링 기반 또는 연관 프레임워크가 등장할 수 있고, 스프링이 버전이 올라가더라도 기존의 그런 확장기능들은 그대로 적용이 가능하다. 이런 것이 바로 스프링이 지지하고 주장하는 객체지향적인 장점을 살린 애플리케이션 개발이 주는 매력이 아닐까 싶다. 자바와 같은 스태틱타이핑 언어는 OO적이지 못하다고 주장하고, 디자인패턴이란 결국 그런 언어의 한계를 땜빵하기 위한 수단에 불과하다라고 비웃는 최신의 OO언어들에 과연 이만큼의 OO적인 장점을 살린 제품이 존재하기는 할까?

얘기가 좀 샜는데… 아무튼 스프링 3.0은 내부구조의 변화가 크다. Java5+ 이상의 호환코드로 발전한 것은 프레임워크 메인소스만이 아니다. M1에서 다 적용되어있지는 않지만 최신의 소스를 보면 테스트코드도 Java5+에서 사용가능한 JUnit4 방식으로 변환하고 있다. Easymock만 해도 generics을 사용할 수 있다면 그만큼 심플하고 편리하게 쓸 수 있으니까. 아마 3.0 정식버전이 나올즘에는 거의 7천여개에 달하는 거의 모든 테스트 코드도 JUnit4.x로 변환되어 있을 것으로 기대한다. 이왕이면 4.4+에서 지원하는 assertThat을 적용하고, mock은 Mokito를 썼으면 좋겠는데…

 

3.0의 또 다른 큰 변화는 프로젝트 레이아웃의 변화이다. 스프링을 패키징된 jar모듈(OSGi호환 번들이기도 하다)로 받아서 바로 사용하는 사람이라면 별 상관이 없을지도 모르겠지만, 스프링 소스를 관심있게 보는 개발자라면 프로젝트 레이아웃과 빌드시스템의 변화에 주목해 볼 필요가 있다.

스프링은 1.0이래로 Ant를 이용한 단일소스-프로젝트 빌드구조를 유지해왔다. 한때 Maven팀의 유혹도 있었지만(better build with maven 문서에 나온 스프링2.0의 메이븐 프로젝트로 마이그레이션 하는 예제를 생각해보라) 이게 흔들리지 않고 Ant기반의 단일소스-프로젝트 구조를 지켜왔다. 하지만 스프링이 2.0부터 본격적으로 세부모듈로 나뉘어 패키징되기 시작했고, 특히 OSGi번들화 되면서 각 모듈(번들)의 독립성이 중요하게 부각되었다. 게다가 각 스프링 세부 모듈의 3자 라이브러리에 대한 의존관계의 복잡성 때문에(스프링 탓은 아니다) 스프링을 이용해서 새 프로젝트를 구성하는 개발자들이 초반에 많은 삽질을 하게 만들기도 했다.

스프링이 단일 프로젝트(즉, 단일 소스 폴더를 가졌다는 말인데, 사실은 Tiger(Java5+)부분은 독립적이긴하다)이면서 멀티모듈로 손쉽게 패키징을 할 수 있었던 것은 스프링의 소스 레이아웃이 아주 완벽할 정도로 잘 구성이 되어있었기 때문이다. 유겐 할러는 스프링 초창기부터,스프링이 계속 발전하면서 소스 구조가 커지고 모듈화가 필요할 때를 고려해서 패키지 레벨의 순환참조가 전혀 없도록 소스를 잘 유지해왔다. 이전에 소스코드 순환의존관계에 대해서 한번 분석했던 글에서 얘기한 것처럼, 오픈소스 프로젝트 중에서 스프링만큼 완벽하게 순환의존관계(cyclic dependency) 없는 깔끔한 패키지구조와 의존성관리를 해온 제품도 없다.

패키지레벨의 순환의존관계가 없다면 어떤 장점이 있는가? 다양한 장점이 있지만 그 중 대표적인 것은 어떤 소스패키지라도 독립적인 모듈로 분리해내기가 쉽다는 점이다. 이렇게 분리한 모듈은 한 방향으로의 의존관계만 가지므로 꼭 필요한 모듈만을 삽입할 수 있다. 기존에 썼던 글에서 분석해본 바에 따르면 우습게도 세부 옵셔널 서브모듈로 기능을 분리해 놨는데 막상 메인 모듈이 옵셔널 모듈에 의존하고 있어서 결국은 jar만 분리되어있지 무조건 같이 사용해야 하는 경우도 있다. 그 외에도 복잡한 클래스-패키지 의존관계는 객체지향적으로 건전한 설계가 아니고, 따라서 깨지기 쉽고 변화에 취약한 문제 등을 가진다. 아무튼 스프링은 서브패키지를 포함해서 거의 모든 레벨의 패키지에서 상호의존관계가 없으므로 매우 세세하게 재 패키징해서 jar로 구분하고, jar단위의 최소 의존관계만 따라서 꼭 필요한 모듈만 가져다 사용할 수 있다. 작은 단위의 기능 모듈로 구분해서 OSGi번들화 하기에 이만큼 쉬운 프로젝트가 있었을까 싶을 정도다.

따라서 비록 단일 소스트리를 가졌지만 빌드시 세부 모듈로 구분해서 어렵지 않게 패키징을 할 수 있었다. 하지만, 뭔가 자연스럽지 않은 것은 사실이었다. 앞에서 말한 각 세부모듈이 가지는 라이브러리 및 다른 모듈에 대한 의존성도 바로 파악이 안되고 말이다.

결국 3.0에서는 이 프로젝트 빌드시스템과 프로젝트 레이아웃을 드디어 멀티 구조로 변경했다. 멀티 서브 프로젝트를 지원하는 가장 흔하게 사용하는 툴은 Maven이다. Maven을 이용하면 프로젝트 트리 형태로 서브 프로젝트를 구성하고 빌드설정을 상속하게도 할 수 있고, 한번에 손쉽게 전체 빌드를 수행하거나 관리할 수 있다. 하지만, 아직까지는 이클립스와 같은 대표적인 툴에서 지원이 완벽하지 않은데다 모든 빌드 방식을 아직은 완벽하다고 보기 힘든 Maven이라는 툴에 의존시켜야 한다는 단점이 있다. 또, Maven은 OSGi번들과 유사한 jar단위로 편집되고 POM정보를 가지는 작은 모듈들을 Central이라고 불리는 통합 리포지토리에 등록하게 하고 이를 통해서 의존라이브러리를 손쉽게 가져와서 적용할 수 있는 뛰어난 기능이 있다. 스프링이 OSGi를 적극 밀기 시작하면서 필연적으로 OSGi용으로 재 패키징된 다양한 자바 라이브러리들을 지원해줘야 했고, 결국 스프링 자체도 그렇게 리포지토리를 통해서 제공하는 것이 필요했다. 그래서 s3서비스에 스프링 전용 리포지토리를 만들어 스프링의 모듈을 마일스톤 단위까지 제공했다. 또, 스프링 소스의 리포지토리에서 OSGi용으로 패키징된 의존 라이브러리도 제공했고. 그래서 SpringDM/OSGi 프로젝트는 기본적으로 Maven빌드를 채용했다. 개발자들의 취향일 수도 있겠지만, 그보다 OSGi라는 작은 단위의 모듈을 기반으로 한 개발의 특성이 주는 영향이 컸을 것이라고 멋대로 추측해본다. -_-;

결국 스프링도 3.0에서 각 패키징 모듈 단위로 프로젝트를 구분하는 멀티프로젝트 구조로 변신한다. Ant를 이용한 빌드 스크립트 방식은 그대로 유치하고 있다. 하지만 같은 Ant를 이용하지만 기존의 Ant스크립스트를 그대로 사용하는 것이 아니다. 멀티 프로젝트를 기반으로 하는 매우 모듈화된 최신 Ant스타일(스프링3.0빌드는 Ant 1.7이상만 가능하다)이 적용되었다. 또 한가지 큰 변화는 Ivy라는 Ant의 확장기능을 이용한다. Ivy는 Maven과 비슷하게 의존관리가 가능하도록 해줄뿐더러, 리포지토리에서 빌드시 자동 다운로드도 지원한다. 이렇게 스프링3.0은 프로젝트 구조와 레이아웃, 빌드 방식을 완벽하게 바꿨다.

또 Spring3.0은 기존에 사용하던 소스포지의 CVS를 벗어나서 독자적인 SVN 리포지토리를 사용하고 있다. 흥미로운 것은 이 새로운 소스코드 리포지토리에는 Spring3.0과 함께 Spring JavaConfig이 자리잡고 있다. 그리고 이 JavaConfig이 바로 스프링 프로젝트에서 최초로 Ant-Ivy를 이용한 멀티 프로젝트 방식을 택한 것이다. 자세히 소스를 비교해보면 JavaConfig에 작년 초부터 적용했던 새로운 빌드방식과 프로젝트 구조가 거의 그대로 Spring3.0에 적용되어있다. 일단 간단한 프로젝트에 적용해서 검토해보고 스프링으로 이전한 것인지, 아니면 JavaConfig에서 써보니 좋다는 소문이 나서 가져다 사용하기로 한 것인지는 잘 모르겠다. 아무튼 이 JavaConfig 프로젝트를 현재 리드하고 있는 Chris Beams가 바로 Spring3.0의 레이아웃 변경과 Ant-Ivy적용을 거의 대부분 담당하고 있다. SVN 히스토리를 보면 최근에는 유겐 할러보다 이 크리스 빔스가 더 자주 등장하는 것도 그 이유에서 이다. M1에서 대략 프로젝트를 구분하기는 했지만, 그 이후에 계속해서 멀티 프로젝트로 변경한 것을 다듬는 작업을 하고 있다. 특히 testsuite으로 테스트 코드를 몰아놨던 것을 이제 각각 해당 모듈 프로젝트로 테스트 코드를 옮기고 JUnit 4.x대로 변경하는 작업이 작년 말에 마지막으로 한창 진행되었던 것이다.

 

과연 이렇게 멀티 프로젝트로 변경한 것이 좋은 선택일까? 일단은 그렇다고 봐야겠다. 개념적으로 독립된 번들을 지향하는 OSGi컨셉을 따라서 스프링도 재구성을 했으니, 당연히 프로젝트/번들이 맞다. 또한 모듈간 의존관계관리나, 라이브러리 의존성의 체크 등이 그런면에서 손쉬워진 것도 사실이다. 그럼 Ant-Ivy의 선택은 Maven으로 변환보다 나은 선택일까? 이건 개발자들이 어떤 방식에 익숙한가에 달린 것이지만 안정적인 빌드방식을 계속 유지하기 위해서는 잘한 선택이라고 본다. Maven도 플러그인을 만들어서 확장하는 것이 충분히 손쉽게 가능하지만, 여전히 불안한 듯한 Maven의 기본 플러그인 구조나 여러가지 꾸준히 지적된 2%쯤 부족한 기능과 완성도 등을 생각할 때, 세밀한 빌드제어를 위해서 모듈화된 Ant빌드를 사용하는 것이 더 나았으리라고 본다. Ivy덕분에 리포지토리도 손쉽게 사용할 수 있으니 말이다. 당연히 빌드도 한방에 손쉽게 할 수 있으니 CI에도 문제는 없다.

 

다음은 내 입장에서 본 3.0의 변화이다. 스프링 소스를 분석하고, 항상 최신의 소스를 가지고 스프링을 살펴보기를 좋아하는 나에게는 이번 변화가 사실은 좀 부담이다.

새 소스를 SVN에서 받아서 이클립스에 임포트 해보자. M1이후에 계속 이 시도를 하고 있는데 몇가지 불편한 점이 있다. 일단 이클립스는 Ivy설정등을 제대로 지원하지 못한다. Ivy플러그인이 있지만 설치하면 스프링 프로젝트는 몽땅 다 Ivy에러가 떠버린다. 아직은 성숙하지 않은 플러그인인듯 하다. 물론 Ant스크립트를 그냥 실행시키면 아무 문제는 없다. 하지만 당장 Ivy리포지토리에서 라이브러리를 참조해야 하는데, 그것부터 에러가 난다. 결국 Ant실행 후, Ivy리포지토리를 이클립스 빌드에 추가해줘야 한다. 최신의 Maven 플러그인에서 해주는 한방 Import가 부럽기도 하다.

두번째 문제는 멀티 프로젝트이다. 각각의 프로젝트를 매번 import 기능으로 가져오는 것도 지루한 작업인데다, 프로젝트가 많아질 수록 이클립스의 빌드시간과 성능은 대폭 떨어진다. 그래서 소스의 변화가 있을 경우 이를 가져오고 새로 빌드할 때 시간도 많이 걸릴 뿐더러, 종종 빌드에러가 난다. 요즘에 빌드에러가 나는 이유는 리포지토리에 있는 최신 trunk의 이클립스 프로젝트 설정이 잘못되어있는 경우가 있기 때문이다. 예를 들어 이클립스 설정 calsspath에는 aspectj 1.5로 세팅이 되어있는데, 막상 Ivy dependency항목에 보면 1.6이다. 아마도 Ant-Ivy의 빌드를 계속 재구성하고 다듬기만 하고 이클립스에서 순수한 개발작업을 하면서 이클립스 프로젝트 설정을 바로 반영해주지 못한 탓인 듯 하다. 그렇다고 Ivy->Eclipse 플러그인이 있어서 한방에 이를 반영할 수 있는 것도 아니고, 제대로 빌드를 성공하려고만 해도 한참을 프로젝트를 잡고 씨름해야 한다. 멀티 프로젝트이기 때문에 불편한 점은 점차로 개선되긴 하겠지만, 그래도 가끔은 옛날 단일 프로젝트 구조가 그립기도 하다. 참.. 내가 제일 싫어하는 src-main-java 스타일의 폴더구조도 적용되어있다. Maven도 아니면서 왜 이런 만행을!!

이클립스에서 빌드하려는 목적이 아니라면 단순히 Ant 스크립트를 실행해서 한방에 빌드할 수 있다. 조건은 JDK1.6+, ANT1.7+이면 된다. 단, ANT_OPTS에서 최소한 512m이상 메모리와 128m이상 MaxPermSize가 설정되어있어야만 한다. 아니면 빌드중 메모리 에러가 날 것이다.

마지막으로 한가지 아쉬운 것은 예제가 현재 달랑 하나만 있다. Pet Clinic인데.. 다른 다양한 예제들을 더 보강되었으면 좋을 것 같다. 또 한가지는 레퍼런스 문서의 부재이다. M1을 받아본 사람들은 알겠지만 API문서만 있고 레버런스 문서는 아직 없다!! 예제 코드를 가지고 대략 추정해서 새로운 기능을 살펴봐야 한다. 언제쯤 새로운 레퍼런스 문서를 제공하려는지… 현재 가장 아쉬운 부분이다.

 

아무튼 이런 큰 스프링의 내부구조의 변화가 3.0의 화려한 변신과 안정적인 프로젝트 관리에 모두 좋은 영향을 주기를 기대한다. 3.0의 정식 발표 계획은 4월이다. 이번 봄에는 새로운 스프링의 선물을 받을 수 있으려나..(스프링 책도…..)

Related posts:

  1. Spring 3.0 (2) R-518 스프링의 새 모듈 OXM(Object/XML Mapping)
  2. Spring 3.0 (53) Spring Dependency Matrix 업데이트
  3. Spring 3.0 (42) Spring Dependency Matrix 업데이트
  4. Spring 3.0 (35) Spring 3.0 Reference Document 공개
  5. Spring 3.0 (26) Spring Expression Language와 @Value
  6. Spring 3.0 (7) Spring 3.0 Dependency Matrix
  7. 스프링 이슈트래커로 본 Spring 3.0의 전망
  8. Spring 3.0 (44) Spring 3.0과 JEE6
  9. Spring 3.0 (4) – Maven에서 Spring 3.0 최신버전 사용하기
  10. Spring 3.0 (38) Spring Reference 업데이트
  11. Spring 3.0 (13) Context 모듈의 선택 라이브러리 분석
  12. Spring 3.0 (24) 3.0 M2 공개 이틀전
  13. Spring 3.0 (45) Spring 3.0 M4 버전 추가
  14. Spring 3.0 (50) JUnit 4.5~4.7 겨우 지원성공 그리고 계속되는 악몽
  15. Spring 3.0 (19) Test 모듈의 선택라이브러리 분석

Facebook comments:

to “Spring 3.0 (1) 프로젝트 구조와 빌드 시스템의 변화”

  1. 이런건 좀 쪼개서.. 써.
    독자를 생각해야지… 그림도 좀 넣고 말야
    이래가지고 책 쓰겠어.. 어디.. :)

  2. 영회/ 책 쓰는데 시간을 많이 투자하다보니 블로그는 후다닥~

  3. 언제 이렇게 많은 내용을 분석하셨습니까?
    좋은 내용들로 감사드립니다.

    단 아쉬운 점은..ㅋㅋ 영회님 말씀처럼 읽기 좋게 단락이라도 좀더 구분해 주셨으면..ㅋㅋ

  4. 레퍼런스 좀 빨리 내놨으면 좋겠어요!
    역시 점심 먹고 여유롭게 읽으니 좋내요^^

  5. 잘 지내시죠…
    기억하실런지 ㅎㅎㅎ
    영회님이나 토비님 사이트를 방문할 때면 늘 이렇게 괴리감이 드는지…
    쪼개서 쓰자는데 한표여~

  6. ㅋㅋ읽기 포기… 나중에 퇴근할 때 출력해서 봐야겠네요.

  7. 토비님 글에는 주장이 있어서 좋습니다.

    잘봤습니다.

  8. 혹시 책 언제 나오나요….^^ 구글번역 돌려감서 보기 너무 힘드네요 >.<

  9. Karas/ 빠르면 다음 달 말쯤 나올 듯 합니다.

  10. b3tsEw bpyxdlebcdsm, [url=http://nnufmfulgyte.com/]nnufmfulgyte[/url], [link=http://yfflvqdmjtbt.com/]yfflvqdmjtbt[/link], http://vuapgzhxtguf.com/

  11. More posts of this qaulity. Not the usual c***, please

  12. That’s a nicely made aswner to a challenging question

  13. shoes stores Spring 3.0 (1) 프로젝트 구조와 빌드 시스템의 변화 » Toby’s Epril

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha