Clean Code that Works.

봄 부터 꾸준히 추진해 왔던 봄싹 사이트 개발 계획은 나름 순조롭게 진행중이다.
기선이 형이 개인 사정으로 인해서 당분간 봄싹에는 손을 안데시기로 해서.. 사이트 개발 쪽은 내가 좀 진행하기로 했다.
능력이 되시니가 잘 될꺼라 믿는다..
헉!!! 근데 난 잘 몰라!!! ;ㅁ;

이번주부터 매주 토요일(4주간인가?) 강남에서 기선이형이 진행하는 스프링 교육을 듣기로 했는데, 공부도 하면서 개발중에 이슈나 모르는 것은 거기서 물어봐야겠다.

후반기에 내가 해야 할 것은 게시판 모듈 개발 & 스터디 디자인 개선 인데..
지금까지 봄싹에서는 주로 리팩토링 및 잘잘한 기능 추가밖에 안해서,
이번에 추가될 게시판 모듈이 내가 개발한 것에서는 가장 큰 내용이 될 것같다.

열심히 개발해서 Clean Code That works. 하도록 해야지.
디자인은 베끼는 사이트...( 창작은 모방으로 부터 시작한다지..)에서 잘 참조해서 :)

게시판 개발에 대해서 어느정도 요구사항이 나오긴 했는데, 이것을 가지고 어떻게 개발할 지 고민중이다.
아직 디비 테이블도 안만들었는데.. 기본적인 요구 사항을 가지고 TDD 형식으로 진행 해 볼지(좀 익숙해 져야 TDD에도)
윤석군하고 좀 해봐야겠는데 ㅋㅋ

웁스.. 또 하고싶은것만 늘어나는것은 아닌지 걱정이구만.

토비의 스프링3 9장에 나오는 애플리케이션 정보 아키텍처에 대해서 읽고 있다.
책에 있는 내용을 조금 정리해 보았다.

이전에 어렴풋이 알고 있던 내용에 대해서 확실하게 알 수 있었다.

여기서 몇몇 아키텍처에 대한 내용이 나오는데.
애플리케이션에서 서로 흘러다니는 정보를 어떤 식으로 다루는 방식에 대한 아키텍처이다.
간단하게 엔터프라이즈 애플리케이션에 존재하는 정보를 데이터로 다루는 경우(주로 맵) 오브젝트로 다루는 경우(도메인 오브젝트)를 기준으로 구분할 수 있다.

  • DB/SQL 중심의 로직 구현방식
  • 거대한 서비스 계층 방식
  • 빈약한 도메인 오브젝트 방식
  • 풍성한 도메인 오브젝트 방식
각각 방식에 대해서는 책에 자세히 설명이 되어 있다.

실무에서는 어떻게 구성이 되어있는지 이야기를 해 보면,
지금 내가 진행하고 있는 프로젝트가 DB/SQL 중심의 로직 구현방식(90%), 거대한 서비스 계층 방식(10%)을 사용한다.

기선이 형한테 프로젝트 구성을 보여주면서 어떻게 스프링을 쓰면서 이렇게 쓰지? 하면서 성토를 했던 적이 있는데,
이게 바로 위의 두가지 구현방식을 사용한 것이었다.

정보 흐름을 살펴보면 DB/SQL을 통해서 맵으로 데이터를 가져오고(거의 가공하지 않고) 바로 맵을 통해서 뷰에 보여준다.
거대한 서비스 계층 방식은 DB/SQL을 통해서 뷰에 보여줄 데이터를 보여주기 어려운 경우(리포팅 같은 경우에는 리포팅에 맞게 데이터를 재 가공 해줘야 한다)에 사용을 한다. 일단 데이터를 가져온 다음 서비스 계층에서 이를 가공한다.( 토스3에 나온 내용처럼 서비스계층이 거대해 지기 때문에 거대한 서비스 계층 방식이라고 한다)

이 개발 방식의 장점은 업무별로 독립적인 개발이 가능하므로 초기 개발 속도가 빠르고, 개발자 사이에 간섭 없이 독립적인 개발이 가능하다. 하지만 객체지향적인 설계가 없고(적용하기 힘들고), 개발자 개개인의 코딩습관이나 실력에 따라서 서비스 로직의 구현 방식이 달라진다.(유지보수가 힘들어진다.)
가장 큰 단점으로는 처음에는 개발하기 편하지만 중복이 많아지기 쉽고 장기적으로 코드를 관리하고 발전시키기 힘들다.
(토스 3)

정말 공감하는 내용이다.
지금 하고 있는 프로젝트가 화면 하나당 각각 컨트롤러, 서비스가 존재한다.(엄청난 수의 컨트롤러와 서비스들) 이를 어떻게 관리할지 난감하다. 결국엔 나중에 가면 이전 서비스들은 버리고 다시 재 개발 해야 한다.

빈약한 도메인 오브젝트 방식은 이전에 내가 스터디 하면서 개발을 하던 방식이었다.
도메인 오브젝트가 존재 하긴 하지만 거의 VO 로만(getter/setter)로 만 구성되어 있고, 도메인 오브젝트에 다른 비즈니스로직이 들어 가 있지 않다. 이 방식은 이전 방식보다 낳기는 하지만 비즈니스 로직이 서비스에 집중되어 있기 때문에 서비스의 크기가 커지고 서비스에 비즈니스 로직이 들어가 있기 때문에 이를 다른 서비스에서 사용하기 위해서는 사용하려는 서비스에 DI 해 주어야 한다.
사실 이 방식밖에 몰랐다.(스프링 샘플 소스도 이 방식이다)

하지만 더 낳은 방식인 풍성한 도메인 오브젝트 방식이 있다!!
사실 이 방식은 봄싹에서 봤다. 처음 봤을 땐, 응? 왜 도메인 오브젝트에 비즈니스 로직이 섞여 있지?
라는 느낌이었는데, 이번에 책 보면이 이 방식의 장점을 알 수 있었다.
이 방식은 도메인 오브젝트안에 로직을 담아 두면 이 로직을 서비스 계층의 메소드에 따로 만드는 것 보다 응집도가 높다.
빈약한 도메인 오브젝트 방식에 비해서 서비스 계층의 코드가 간결해 지고 비즈니스 로직 코드도 훨씬 이해하기 쉬어진다.

더 발전된 방식으로 도메인 계층 방식이 있는데
이 부분은 토스 3를 참조 하세요 @_@

토비의 스프링 3
이일민 저
예스24 | 애드온2

http://code.google.com/intl/ko/webtoolkit/usingeclipse.html

STS 다운로드 사이트에 들어가보니
이전에는 2.3.3(Eclipse Helios).M 버전으로 존재 하던 것들이

2.5.0.M3 이렇게 변했다.
2.5로 해서 나올려나 보다.

아무튼 GWT Integration을 받아서 실행시켜 보니..
New Web Application Project가 보이지 않았다.
음, 업데이트 사이트에서 확인해 보니 설치가 된것 같은데 표시가 안되는것 같기도 하고..

하여 그냥 STS 2.5.0 받아서 구글 GWT 가이드에 있는 플러그인 주소로 업데이트 하였다.
http://dl.google.com/eclipse/plugin/3.5
나는 Helios(3.6)이니깐 뒤에다가 3.6 해보니깐 3.6 버전들도 있었다.

그래서 플러그인 설치 하고, 이클립스 재부팅 후 
가이드대로 하니깐 실행 완료. - 3-

나도 스텝 별로 다 해보고, 배치 모니터 만들어 봐야지

스프링 배치 하면서, 전에 해봤던 스케쥴링도 같이 하고..

화면 UI는 GWT로 한번 그려보자 @_@;

음 몇시간 또 삽질을 했다 -ㅅ-;;

스프링 배치 공부겸 해서 간단한 샘플을 만들어 보고 돌리는 중이었는데.
이놈의 배치가 계속 실행 되는 것이었다.

한번만 실행되고 멈추면 좋겠구만 -_-;;

그래서 배치 어드민 샘플, 배치 샘플 뒤져가며 보았는데..
안됬었다. ㅠㅠ

하여 여기저기 해결책을 찾아 보다가..

소스를 비교해 보니..

내가 만든 테스트용 ItemReader 는 계속 return "test"; 해서 리턴 값이 있었다.
근대 샘플 소스는 처리를 하고 나면 return null을 하는 것이었다.

응..?

그러니까,
배치 잡이 ItemReader에서 읽을 값이 없어야 배치 실행을 끝내고 종료를 하는데
계속 스트링을 return 하고 있어서
계속 잡이 실행 되는 것이었다.

허...

이런것이었군. ㅠ

추가 하면..
CHUNK 단위로 배치를 실행 하는데,
ItemReader에 처리 해야 할 데이터가 남아 있으면 당연히 배치가 계속 동작하는게 맞는 것 같다.
reader에서 어느 수 많큼(commit-interval="10") 읽어 들이고
그 후에 writer에 쓰고, 근데 reader에 읽어 들일 데이터들이 계속있으니
read & write가 반복 되는 구조.

한번만 더 생각해보면 알 수 있는 문제 인데 이걸~
아우~


6~8월 사이 공부를 조금 하긴 했나보다. -_-;;
뭐 모르는게 이리 많아!!!!

남은 9~12월 까지는 정말 열심히 해야겠다.
내년에는 해야할 것이 많으므로...

개인적으로는 토비의 스프링 3 좀 열심히 보고, 웹플로, 배치, 시큐리티 삼종 세트를 개인적으로나마 잘 정리 했으면 한다.
잘 살펴보고 설계에 대해서도 좀 더 보고, 스터디도 좀 열심히 나가고 포스팅도 다른사람들 읽기 편하게 잘 정리해 보고.

허허허.
목표는 많아 ㄱ-


간단한 App의 경우 보통 시큐리티의 Url 및 Roll 가지고 보안관련해서 처리를 할 수 있다.

Complex applications often will find the need to define access permissions not simply at a web request or method invocation level. Instead, security decisions need to comprise both who (Authentication), where (MethodInvocation) and what (SomeDomainObject). In other words, authorization decisions also need to consider the actual domain object instance subject of a method invocation.

Imagine you're designing an application for a pet clinic. There will be two main groups of users of your Spring-based application: staff of the pet clinic, as well as the pet clinic's customers. The staff will have access to all of the data, whilst your customers will only be able to see their own customer records. To make it a little more interesting, your customers can allow other users to see their customer records, such as their "puppy preschool" mentor or president of their local "Pony Club". Using Spring Security as the foundation, you have several approaches that can be used:


간단한 예를 들면 내가 작성한 글을 나와 관리자만 볼 수 있고, 다른 사람은 못보게 하자.
이런 내용.

영어공부를 많이 해야 하는데 -_-..
이거 원 맨날 내맘대로 번역이야.



봄싹 서버가 PostgreSql을 사용하기 때문에 기존에 만들어 두었던 시큐리티를 좀 바꾸어야 했다.
테스트 돌리는 중간에 프로퍼티 참조를 잘 못해서 삽질을 완전 많이 했다. -_-;;;

프로퍼티 홀더에서 프로퍼티를 찾는 순서는 어떻게 되고, 동일 키 값을 가진 프로퍼티를 나중에 찾은 값이 덮어 씌우는 것인거 같은데, 이것 좀 확인해 봐야겠다.

아직 하이버네이트 공부를 제대로 하지 않아서, 도메인 클래스 만드는데도 약간 고생을..
시큐리티 문서에 있는 ACL 스키마를 가지고 도메인 클래스를 만드는데(쿼리가지고 테이블 생성하기 싫어서, 무엇보다 봄싹에선 도메인 클래스를 가지고 하이버네이트가 자동 생성하는 형식을 사용하고 있다.)

처음에는 그냥 자바 기본 데이터 타입으로 도메인 클래스를 생성하였는데, 그러다가 문제에 봉착 하였다.
identity가 생성이 안되는 것이었다.

You will have to set the classIdentityQuery and sidIdentityQuery properties of JdbcMutableAclService to the following values, respectively:

  • select currval(pg_get_serial_sequence('acl_class', 'id'))

  • select currval(pg_get_serial_sequence('acl_sid', 'id'))


PostgreSQL에서는 위같은 방법으로 시퀀스를 자동 생성한다.

왜 안될까. 하고 찾아 보다가 PGSQL 문서를 찾아 보았다.
pg_get_serial_sequence(table_name, column_name)
get name of the sequence that a serial or bigserial column uses
이런 내용이...
serial, bigserial 타입의 컬럼만 시퀀스를 생성해 준단다.
어우 치사해 -_-;;

아무튼 자바에는 저런 타입이 없다.
그럼 어떻게 해야할 까..

도메인 클래스의 @Column에 속성중에 데이터 타입을 명시해 줄 방법이 있었다.
하이버네이트 어노테이션 설명
columnDefinition (optional): override the sql DDL fragment for this particular column (non portable)
이 속성을 명시 해 주면 된다. 아래와 같이..

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(columnDefinition="bigserial")
    private int id;

스프링 속성 설정은 아래와 같이 해주면 된다. ACL은 DB별로 속성을 타지 않게 하려고 전부 표준 SQL로 동작을 하는데, identity 가져 오는 것은 DB마다 다 다르므로 각각 DB 타입에 따라 명시해 주어야 한다. (기본은 Call Identity())


이제 시큐리티 설정도 어느정도 마무리 되어 가고,
9월 즈음에 스터디 게시판 설계 마무리 하고 테스트 작성하면서 ACL에 대해서 더 포스팅 하도록 해야겠다.


나왔다 @_@

http://www.springsource.org/node/2740

뭐가 바뀐거지...

그중에 눈이 가는거 두개가 있는데...
support for Hibernate Core 3.6, Hibernate Validator 4.1, EclipseLink 2.1, EHCache 2.2
요즘에 하이버네이트 좀 보고 있어서 하이버네이트 관련 부분과,

JSR-303 Pattern message resolvable through Spring MessageSource (despite special characters)
JSR-303 Validation 쪽 보면서 메시지들 처리 아마 클래스명.변수명 형식으로 한다고 하는걸 어디선가 본거 같은데..
맞을꺼야 아마도. -ㄴ-..




게시판 개발 하면서 ACL 다시 한번 정리해서 포스팅 합시다!!

아자 아자!!!