태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

현대 프로그래밍 언어나 프래임웍중에 스캐폴딩이라는 개념이 있다. 


이게 원래의 사전적인 의미는 다음과 같다.



출처: http://experientia.co.kr/?p=244


스캐폴딩(scaffolding)의 개념

– 스캐폴딩이란 교수자가 학생에 대하여 적절한 교수학습적 도움을 제공함으로써 유의미한 학습을 수행할 수 있도록 하는 것으로, 특히 학습자들로 하여금 자신의 현재 기능수준을 넘어서 다음단계의 수준까지 이르도록 돕기 위해 제공되는 지원


프로그래밍 언어에서의 스캐폴딩은 Data Model을 이용해서 CRUD(Create/Read/Update/Delete) 동작을 자동으로 제어해주는 코드를 생성해주거나 기능을 제공하는 것을 이야기한다.  Ruby on rails 에서 이런 기능을 제공하면서 인기를 끌게 되면서 다른 언어나 프레임웍에서도 비슷한 기능들을 제공하기 시작했다. 


PHP yii 프레임웍이나 나 groovy on grails에서도 이런 비슷한 기능들이 제공된다. 


사전적 의미에서 처럼 이런 기능을 제공하는 의미는 기본적인 코드를 제공함으로써 생산성 향상과 튜토리얼의 의미 모두를 만족시키기 위함이 아닐까 생각이 된다. 


웹개발에서 이런 CRUD개발이 50%이상의 시간을 쓰는점을 본다면 이 코드를 기반으로 개발을 시작하게 되면 좀더 빠른 생산성을 가져갈수 있을것이다.


또한 관리자툴 같은곳에서는 이 기능만 활용해도 거의 대부분의 기능을 구현해 낼수가 있다. 


현재 진행하는 프로젝트에서도 운영자툴을 위하여 이러한 솔루션을 몇가지 검토를 해보았는데, 


Spring Roo와 OpenXava 이 두가지가 가장 좋아 보였다. 



두 프로젝트 모두 Model 클래스를 통하여 CRUD기능을 하는 화면까지 생성을 해준다. 


OpenXava의 경우는 코드를 생성해주는 방식은 아니고 모델을 런타임에 분석하여 해당 기능들을 제공하는 방식이다. 





이 프로젝트들의 단점은 무엇보다 도큐먼트의 부족이다.


특히 Spring roo의 도큐먼트는 매우 부족한 수준이다. 

그리고 프로젝트 초기에 이런 프레임웍으로 개발하겠다고 결정하고 시작을 해야 생산성 향상에 도움이 될것 같다. 프로젝트 중간에 이런 툴들을 integration시키려면 여러가지 문제가 속출해서 그것을 해결하다가 보니 오히려 생산성 저하가 오는것 같다. 


여러가지 이유로 OpenXava를 도입하려고 했었는데 이것도 이것 자체가 웹프레임웍이라서 spring MVC와 연동을 하기에는 쉽지 않고, 커스터마이징 기능을 개발하기에도 이미 개발해놓은 코드들을 재사용하지 못해 불편함이 따른다. 


관리자툴 개발에 시간을 절약하기 위하여 도입검토를 한건데 이런식이니 그냥 간단하게 비슷한 역할을 해주는 것을 개발하기로 결정했다. 


향후 시작하는 프로젝트에서는  시작전에 미리 검토를 하고 시작해야 겠다. 







Posted by Breeze.Kang

댓글을 달아 주세요






일명 배치잡(Batch Job) 이라고 하는 주기적으로 구동시켜야 하는 작업들을 Spring에서 구동 시키기 위하여서는 Spring Batch 라는 프로젝트가 따로 존재 합니다. 




Spring Batch가 배치작업의 끝판왕이라면 Spring이 주로 사용되기 이전부터 Quartz라는 라이브러리를 java쪽에서는 많이 사용을 했었는데요. 


Spring에서도 이 Quartz를 지원해서 간단하게 주기적인 배치작업을 구동시킬수 있습니다. 




이렇게 스케줄러를 이용해서 Spring project상에서 배치작업을 Invoke시키는 방식은 통합적인 코드로 스케줄 작업들을 관리할수 있기 때문에 관리 측면에서 유리한 점이 있습니다. Spring 프로젝트 배포 시스템에서 따로 설정을 해주거나 관리를 해줄 필요가 없구요. 


반면 WAS서버가 여러대가 동시에 구동되는 실제 대용량 환경을 고려해본다면 실제 배치잡이 한군데에서만 구동되어야 하는 경우가 있을 것입니다. 두개의 인스턴스가 동시에 구동이 된다면 로직상에 문제가 생길만한 작업의 경우에 말이죠. 


예를 들면 주기적으로 보상을 해주거나 리셋을 해야 한다거나 통계를 내야 한다거나 하는 작업들이 있겠네요. 


이렬경우는 배치작업이 셋팅된 프로젝트를 따로 분리하여 한대의 서버에만 설치를 한다거나,  한대의 서버에서만 배치작업이 구동되게 설정을 바꾼다거나 하는 작업이 필요 해집니다. 


이럴경우 좀 번거롭게 되는것이 사실입니다. 


그래서 그냥 간단하게 외부 라이브러리 없이 Async하게 작업을 구동시키는 컴포넌트를 만들고,  내부URL에서만 접속가능한 Controller를 만들어서 패키지를 모든 배포하고 cronjob을 한대의 서버에서만 셋팅해서 내부 URL을 원하는 타임에 호출하게 해주면 어떨까 생각해 봤습니다.


interface 

PvpRankingRewardWorker.java 



Implementation
PvpRankingRewardWokerImpl.java


Controller코드는 간단하므로 생략했고, 

cronjob에는 wget같은 유틸을 이용해서 wget URL 같이 등록을 해주면 될것 같습니다.


이런방식이 Spring batch나 Quartz를 사용하는 방식보다 간단해 보이는데 어떻게 생각하시나요?






Posted by Breeze.Kang

댓글을 달아 주세요


http://www.cloudping.info


한국에서 가장 빠른 곳은 일본(Tokyo) region 으로써 51ms를 기록하고 있네요.


나쁘지 않습니다만 한국 IDC에 올라가 있는 서버에 비하면 아직 좀 느리기는 하네요.


한국쪽 서버는 대략 0.00X seconds  ( X ms ) 정도가 나올것 같습니다.


예전에 비하면 상당한 발전으로 이젠 느려서 못쓰겠다는 소리는 못할것 같습니다.







Posted by Breeze.Kang

댓글을 달아 주세요

맨날 헷갈리는 부분이다.


한눈에 정리되는 HashMap TreeMap LinkedHashMap의 차이점 


출처는 아래와 같다. 



출처 : 

http://stackoverflow.com/questions/2889777/difference-between-hashmap-linkedhashmap-and-treemap




결론 :  Sorting이 필요 없으면 괜히 TreeMap 같은거 쓸필요 없다. 


Posted by Breeze.Kang

댓글을 달아 주세요

Apache commons의 하위 프로젝트였던 HttpClient 프로젝트가 HttpComponent 프로젝트로 독립되면서 다양한 기능 지원과 함께 사용방법이 많이 바뀌었다.


Spring에 integration해서 사용하기 위한 문서도 매우 부족하고 검색에서 나오는 예제들은 모두 이전 버전대에 해당하는 것들이라서, 기본적인 사용법을 참고 삼아 보라고 함 올려본다.


Spring configuration



Code 


Posted by Breeze.Kang

댓글을 달아 주세요

제목이 길고 이해하기가 어렵지만.


콤마로 구분된 스트링 (Comma separated string)을 array로 변환하여 사용하고자 할때가 많이 있습니다.


예를 들면 서버들이 여러대가 있을경우 property에서


server.host = server1, server2, server3


이렇게 표현을 하는게 심플하기 때문이죠.


물론 


server1.host = server1

server2.host = server2

..


뭐 이렇게 표현을 할수도 있습니다만 왠지 이런건 싫잖아요?




설정을 담을 수 있는 bean을 하나 만들어줍니다.


1
2
3
4
5
6
7
8
9
10
11
12
13

public class ChatServerBean {
 
    private String[] servers;
 
    public void setServers(String[] values) {
        this.servers = values;
    }
 
    public String[] getServers() {
        return servers;
    }
}


application-context.xml  같은 설정 파일에서..


1
2
3
4
5
 
<bean id="chatServerBean" class="com.oolblue.hunter.gameworld.bean.ChatServerBean">
        <property name="servers" value="server1,server2,server3"/>
 </bean>
 

이렇게 해서 chatServerBean을 필요한 곳에 injection 하셔서 사용하시면 됩니다.




Posted by Breeze.Kang

댓글을 달아 주세요

최근에 굉장히 많은 수의 Data Serialization / Deserialization 라이브러리들이 나오고 있어서, 어떤 라이브러리를 선택해서 사용을 해야 하는지 고민하는 프로그래머들이 많으실것 같습니다. 


위키피디아를 보면 정말 수많은 라이브러리들이 존재하고 있고 여기에 올라와 있지 않은 라이브러리들도 많은 실정입니다. 


http://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats


저도 상황에 따라서 그때 그때 적당한 라이브러리를 선택해서 사용하고 있는데요. 


그 기준에 대하여 이야기를 해보도록 하겠습니다.


우선 가장 먼저 고민을 해야 하는 것은 내가 사용하는 언어 지원 여부 입니다. 


 Data Serialization / Deserialization 들은 보통 다양한 언어 지원이 기본이지만 대부분 JAVA , C++ 같은 메이저한 언어들만 지원하는 경우도 있고  C#  같은 언어들은 3rd party지원등으로 하는 경우도 있어서  지원하는지 안하는 ,  공식 지원인지 아닌지 부터 확인을 해봐야 합니다. 

아무래도 공식 지원이 아닌 경우는 버그가 많거나 버전업의 경우 제대로 업데이트가 안되는 경우도 있어서 꺼려지는게 사실이죠.


다음 고민해야 할것은 스키마 지원(고정타입) 여부 인것 같습니다.


스키마가 지원 될때는 Type checking이 가능하여 좀더 단단한 코드를 작성할수 있지만 자주 스키마가 변경되는 경우 클라,서버 업데이트에 부담이 될수 있습니다. 게임의 경우는 IOS버전, AOS(안드로이드)이 심사 일정등으로 업데이트 주기가 다른경우 이런 스키마 방식은 부담스러울수 있습니다. 


스키마가 없는 Dynamic type 방식은 그 반대로 생각하시면 될것 같습니다.


스키마가 존재하는 것은 Proto buffer,  Thrift등이 있고  스키마가 없는 경우는 MessagePack Avro가 있습니다. 


그리고 스키마 방식인 경우도 어떤 타입이 지원하는지를 확인해보셔야 합니다.


- Protocol Buffers: int32, int64, uint32, uint64, sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, double, float, bool, string, bytes, repeated, message

- Avro: int, long, float, double, boolean, null, float, double, bytes, fixed, string, enum, array, map, record 

- MessagePack: Integer, Float, Boolean, Nil, Raw, Array, Map (=same as JSON) 


https://news.ycombinator.com/item?id=2834010



그 다음 고민 해야 하는 부분이  Data Serialization / Deserialization속도와 데이터 사이즈 인것 같은데요.


이 부분은 각종 벤치마크 자료를 비교해보시거나 직접 사용해보실 데이터로 테스트 코드로 벤치 마크를 해보셔야 합니다.


제 경우에는 Dynamic Type이 필요해서 Bson을 테스트 해보았으나 성능상이나 데이터 사이즈상으로 매우 실망스러운 결과를 얻었습니다. 





Posted by Breeze.Kang

댓글을 달아 주세요

CSV 파일을 파싱해서 처리해야 하는 경우 선택가능한 라이브러리가 여러개 있는게 가장 많이 사용하시는게 3가지 정도 있는것 같습니다. 


1. commons-csv : apache commons의 csv 라이브러리  


http://commons.apache.org/proper/commons-csv/


2. openCSV  :  http://opencsv.sourceforge.net


3. superCSV :  http://supercsv.sourceforge.net/



그중에 CSV파일을 Bean 오브젝트로 간단하게 변환하는 것을 제공하는 것은  OpenCSV입니다. 


아래 같이 사용하시면 되는데요.



    public List getCsvObjectList(File file, Class className) throws IOException {

        InputStreamReader in = new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));

        CSVReader reader = new CSVReader(in);


        HeaderColumnNameMappingStrategy start = new HeaderColumnNameMappingStrategy();


        start.setType(className);


        CsvToBean csv = new CsvToBean();

        List list = csv.parse(start, reader);

        reader.close();

        return list;

    }



javadoc을 참조하시면 총 3가지의 MappingStrategy를 제공하고 있습니다.


ColumnPositionMappingStrategy 

HeaderColumnNameMappingStrategy 

HeaderColumnNameTranslateMappingStrategy



ColumnPositionMappingStrategy :  이건 컬럼 순서대로 읽어서 수동으로 처리를 해줘야 하는 방식.


HeaderColumnNameMappingStrategy  : CSV 한줄을 bean으로 변환하는 방식 


HeaderColumnNameTranslateMappingStrategy  : CSV의 특정 컬럼만을 뽑아내서 bean으로 매핑하는 방식 



이렇게 지원을 합니다.


직접해보시면 아주 간단합니다. 





Posted by Breeze.Kang

댓글을 달아 주세요

Spring에서 json포멧으로 결과를 출력하는 다양한 방법이 존재 합니다. 


가장 간단한거로는 ModelAndView에서 출력하는 View를  json포멧으로 수동으로 찍어주는 방법도 있구요. 


View를 상속받은 JsonView 같은 거를 만들거나 라이브러리를 사용하여 Controller에서 리턴해주는 방법도 있구요. 


ViewResolver에서 JacksonJsonView를 매핑하여 사용하는 방법도 있습니다. 3.1버전 이상에서 부터 지원됐던걸로 기억합니다. (확인필요)

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
  <property name="mediaTypes">
    <map>
      <entry key="atom" value="application/atom+xml"/>
      <entry key="html" value="text/html"/>
      <entry key="json" value="application/json"/>
    </map>
  </property>
  <property name="viewResolvers">
    <list>
      <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
      </bean>
    </list>
  </property>
  <property name="defaultViews">
    <list>
      <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
    </list>
  </property>
</bean>


Gson이라는 Google에서 만든 Json라이브러리를 사용하기위하여 찾아보던중에... 발견한것인데요.   Spring4.1 버전에서 부터는 각종 message converter를 기본 지원하기 시작하는데요... 그중에 Gson도 지원을 하기 시작했습니다. 


따라서 간단한 설정만으로 기존 오브젝트들을 간단히 json포멧으로 변경이 가능합니다. 


예를 들면 

<bean id="gsonHttpMessageConverter" class="org.springframework.http.converter.json.GsonHttpMessageConverter"/>


설정을 추가 하고, 


controller에서 @ResponseBody 어노테이션을 추가해주면 


@RequestMapping(value = "/user/list", produces = MediaType.APPLICATION_JSON_VALUE)

@ResponseBody

public ResponseBean listUser(

            @RequestParam(value = "page", defaultValue = "0") int page,

            @RequestParam(value = "keyword", defaultValue = "") String keyword) {


        int pageSize = 10;


        List<User> users = null;

        if (keyword.equals("")) {

            users = userService.getList();

        }

        return new ResponseBean(ResponseCode.SUCCESS, users);

    }


결과값이 json으로 변환되어 출력이 됩니다. 


@ResponseBody에 대한 추가적인 정보나,  Jackson을 이용한 방법은 다음 주소에서 확인하세요.


http://ismydream.tistory.com/140



spring4.1이 아직 stable버전이 나오지 않았다는 것은 함정.  ㅋㅋ 


물론 Jackson을 사용한 같은 방식도 이미 전부터 지원을 했습니다만 4.1 부터는 Gson도 지원합니다. 










Posted by Breeze.Kang

댓글을 달아 주세요

  1. swagger 검토해보삼. api 명세 + test web form 이 그냥 뚝딱 만들어진당께~

    http://blog.zenika.com/index.php?post/2013/07/11/Documenting-a-REST-API-with-Swagger-and-Spring-MVC

    2014.08.11 17:28 신고 [ ADDR : EDIT/ DEL : REPLY ]


ProtoBuffer와 spring을 이용하여 Rest 서비스 구현하기

Protobuffer를 차기 프로젝트에서 사용 예정인데, 이를 이용하여 바로 RESTful한 API를 구현할수 있는 방법이다.   

딱 내가 찾던 방식인데 실제 서비스에서 사용할지는 미지수. 


http://www.slideshare.net/mokeefe/javaone-2009-ts5276-restful-protocol-buffers





Posted by Breeze.Kang

댓글을 달아 주세요