아마 Moneycomb 프로젝트를 할 때였던 것 같다. 나는 그때도 JSON으로 메시지를 변환하기 위해, 책과 튜토리얼에서 빈번하게 등장하고, 다들 문제없이 쓰는 것으로 보이던 MappingJacksonHttpMessageConverter를 '나도 당연히 되겠지?' 하며 튜토리얼들을 따라 서블릿 컨텍스트에 빈을 설정했다.


지옥의 시작

왜인가? 어째서인가? 남들 다 된다고 댓글에도 "Thank you!"가 넘치고, 누구하나 되지 않는다는 이 없는데, 나는 왜 안되는 것인가.

지금도 그렇지만 그 때에도 Google의 JSON 라이브러리인 Gson을 즐겨썼다. API가 복잡하지 않고 설정도 간단했기 때문이다.

하지만 스프링에서 기본적으로 제공하는 JSON 메시지 컨버터는 Jackson에 의존성이 있었는데, 일단 Jackson이라는 라이브러리 자체가 낯설었고, 스프링 MVC의 동작을 깊이 파악하고 있지 않았던 탓에 하라는 대로 하는 것 외에는 손대볼 수 있는게 없었다.

열심히 설정하고 코드를 따라서 친 후 실행, 두근거리는 마음으로 Postman으로 메시지를 날려보았다.

@RequestBody 애너테이션이 붙어있는 파라미터에서도 변환이 되질 않고, @ResponseBody 애너테이션이 붙어있는 파라미터에서도 변환이 되질 않는다.

이때는 log4j 설정도 잘 몰라서, 콘솔에서는 어떠한 로그도 뜨지 않길래, 스프링이 아무말 없이 응답으로만 "안돼"라고 하는 줄로만 알았다.


Content-Type, Accept

스프링 컨트롤러에서 @RequestMapping 애노테이션에는 Content-Type과 Accept를 설정할 수 있는 consumes와 produces 속성이 있다. JSON의 미디어 타입이 application/json 인 것은 웹 하는 사람이라면 누구라도 알고 있을 것이다.

튜토리얼에서는 명시적으로 지정해주지 않았지만, 안되길래 consumes와 produces에 "application/json"이라고 적어주었다. 안된다. 이게 문제가 아닌가보다.


오늘도 삽질

그 때와 똑같은 행태를 반복해서였는지는 모르겠지만 오늘도 똑같은 현상이 나타났다. JSON 직렬화도, 역직렬화도 안된다.

그 때는 해결하지 못했던 문제였지만 오늘은 나름 해결을 하긴 했다.

여러가지 오해와 착각과 습관과 편견과 게으름의 결과였던 듯 하다.


1. 반환 타입

다른 테스트 클래스를 만들거나 모델 클래스를 반환하려니 값을 넣기도 귀찮아서

@RequestMapping(....)

@ResponseBody

public Object test(@RequestBody ....) { ... }

위 처럼 Object를 반환했다. JSON 자체에서도 { } 라고 쓰기도 하거니와, Gson에서는 Object 객체도 잘 변환한다. 빈 객체를 표현할 수도 있으니 당연하다고 생각했는데, Jackson에서는 Object 객체를 JSON으로 직렬화할 수 없다.

"Can not create bean serializer for Object.class" 란다. 어떤 정책으로 인해서 이렇게 정해졌는지는 알 수 없지만, 이것 때문에 한방.


2. 테스트 Ajax 요청

테스트로 JSON 객체를 보낼 때도, 필드 몇 개를 대충 보내거나 했는데, 이 전 버전의 Jackson(codehaus)은 JSON에는 있지만 변환될 자바 타입에서 없는 속성, 빈 문자열은 변환할 수 없고 예외를 발생시킨다.

애초에 테스트 JSON 문자열을 잘 썼으면 문제가 없었을지도 모르지만... 이 역시 Gson을 쓰면서 Gson이 동작하는 대로 생각해서 였던 것 같다. Gson에서는 없는 프로퍼티는 무시하고, 빈 JSON 문자열의 경우 null을 반환한다.


어쨌든 이번 일로 인해 좀 더 MessageConverter의 동작을 명확히 알게 되었고, 더불어 아래와 같은 것 잡지식(?)이 늘었다.

- com.fasterxml.jackson은 org.codehaus.jackson를 승계한 프로젝트

- com.fasterxml.jackson은 MappingJackson2HttpMessageConverter와 바인딩

- org.codehaus.jackson은 MappingJacksonHttpMessageConverter와 바인딩

- Spring 4부터 GsonHttpMessageConveter가 내장

- Spring 4부터 MappingJacksonHttpMessage는 없어짐





Gson 기반의 메시지 컨버터 설정 (Maven, Spring 4.1.6.RELEASE)


Maven Dependency 추가

<dependency>

<groupId>com.google.code.gson</groupId>

<artifactId>gson</artifactId>

<version>2.3.1</version>

</dependency>


servlet-context.xml 설정

<beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">

<beans:property name="messageConverters">

<beans:list>

<beans:ref bean="jsonMessageConverter"/>

</beans:list>

</beans:property>

</beans:bean>


<beans:bean id="jsonMessageConverter" class="org.springframework.http.converter.json.GsonHttpMessageConverter">

   </beans:bean>



※ 참고 자료

- http://www.leveluplunch.com/java/tutorials/023-configure-integrate-gson-spring-boot/

- http://www.studytrails.com/java/json/jackson-create-json.jsp

- http://docs.spring.io/spring/docs/current/javadoc-api//org/springframework/http/converter/json/GsonHttpMessageConverter.html

- http://erictus.tistory.com/entry/Spring-JSON-View-구현하기2-ResponseBody


Rabbit MQ의 ConnectionFactory를 아래처럼 연결의 각 프로퍼티를 지정해주고,


 ConnectionFactory factory = new ConnectionFactory();

 factory.setUsername("test");

 factory.setPassword("password");

 factory.setVirtualHost("vhost");

 factory.setHost("localhost");

 factory.setPort(5672);


새로운 커넥션을 생성하면 아래 메시지와 함께 예외가 발생한다.

ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile.


검색해보니 3.3.1 버전부터 guest 계정으로 루프백 주소 이외에는 연결할 수 없도록 바뀌었다고 하는데, guest 계정을 사용한 것도 아니고, 다른 호스트도 아닌데 인증에 실패했다.


조금 방법을 바꿔서 각 프로퍼티를 세터로 설정하는 대신 factory.setUri()메서드를 이용해 연결 설정을 하고 새로운 커넥션을 생성하면 정상적으로 연결된다. 아래와 같은 모습이다.

String urlEncodedPassword = URLEncoder.encode("test", "UTF-8");

factory.setUri("amqp://test:" + urlEncodedPassword + "@localhost:5672/vhost");


빠진 연결 정보가 없는데도(굳이 따지자면 amqp 스키마 정도..?) URI를 통해서는 연결이 되고, 프로퍼티를 설정해주었을 때는 연결이 되지 않는다.


이유를 알 수 없어서 ConnectionFactory의 setUri() 메서드의 소스코드를 봐도, 명확한 이유는 알 수 없었다.


Uri 객체로부터 host, port, username, password, virtualhost를 가져와서 동일하게 세터를 호출하여 값을 설정한다.


문제가 고쳐지긴 했지만 찝찝하다. 뭘 잘못하고 있는걸까



----- 추가

연결이 되지 않은 이유는... 패스워드에 오타가 있었습니다. 하하;;

3.3.1 버전부터 guest 계정으로는 localhost만 접속할 수 있다고 합니다. 링크를 참고하세요. http://www.rabbitmq.com/access-control.html#loopback-users


현재 진행 중인 프로젝트에서 오픈 소스를 분석해서 설계서를 역으로 만들고 있는데(클래스 설계서),

 

약 400여개의 클래스를 손수 MS 워드 문서로 옮겨야 하니 노가다의 절정이라고 생각된다..

 

R&D 사업이니 설계 산출물 자체에 의미가 있다기보다는 예산에 대한 증빙 자료인 셈이다.

 

 

 

각론하고, 다행히 오픈 소스가 Java로 작성되어 있어 리플렉션으로 클래스 정보를 읽은 후 HTML 문서로 출력하고,

 

워드로 옮기면 되겠다. 라고 생각하고 작업을 했는데, 메서드의 파라미터 이름을 가지고 올 수 없었다.

 

 

 

이 문제를 해결하기 위한 방법을 두 가지 찾았는데, 하나는 Java 8의 리플렉션에 추가된 Method.getParamter()를 통해 얻은 파라미터 정보에서 getName()을 이용해 파라미터의 이름을 알아내는 것이고,

 

두 번째는 Java Parser를 이용하는 것이었다.

 

 

 

수작업을 줄이려고 시작한 건데 일이 커지기 시작했다.

 

거기에 더해 오픈소스를 분석한다는 의미는 사라지고 설계서를 만든다는 것만 남았다. (...)

 

 

 

 

 

Java Parser로 테스트를 해 보기 전에 잠시 Java 8에서 테스트를 해보았는데, 파라미터 이름이 arg0 과 같이 실제 이름이 아닌 컴파일러에서 치환된 이름으로 변환되어 나와서 더 찾아보지 않고 Java Parser로 테스트를 했다.

 

 

 

Java Parser를 이용할 때는 원하는 대로 파라미터를 출력할 수는 있었지만, 구조화된 타입이 아닌 파라미터 선언부의 문자열로만 값을 가져올 수 있었고, 한 가지 문제점으로는 public void test(/*Param1*/String param) 과 같은 메서드 선언에서 주석을 같이 읽어오게 되어 예외 케이스에 대한 처리가 복잡해질 것 같아서 다시 Java 8 리플렉션을 통해 파라미터 이름을 얻어올 수 있는 방법을 찾아보게 되었다.

 

 

 

검색을 하면서 하나 놓친 것이 있었는데, 자바 컴파일 옵션에서 -parameters 옵션을 주면 메서드 파라미터의 이름이 그대로 컴파일 된 바이트코드에서도 유지된다.

 

Eclipse에서도 아래와 같이

Store information about method parameters (usable via reflection) 체크박스에 체크하면 파라미터 옵션을 줄 수 있다. (Java 1.8로 컴파일러가 설정된 경우에 활성화된다)

 

 

 

 

 

 

 

 

파라미터 이름을 얻는 소스코드는 아래와 같다.

 

 

 

 

 

 

이 외에도 paranamer라는 라이브러리가 있었지만, 매뉴얼을 대강 읽어보니 Java8에 추가되었다고 노트되어있었다.

 

 

 

 

 

참고 자료

 

https://docs.oracle.com/javase/tutorial/reflect/member/methodparameterreflection.html

 

https://github.com/javaparser/javaparser

http://stackoverflow.com/questions/2237803/can-i-obtain-method-parameter-name-using-java-reflection

 

 

덧붙여,

이 작업을 하고 있는 둘은 한 명은 클래스 명세표 양식을 출력하는 웹 애플리케이션을 만들고 있고, 한 명은 클래스를 리플렉션해서 필요한 메타데이터를 뽑아내는 툴을 만들고 있다. 이쯤 되면 배보다 배꼽의 배꼽 수준인 듯 ㅋㅋ

이니시스의 로그가 깨져 나오길래 PuTTY의 인코딩이 잘못 설정되었나 싶어, 원격 쉘의 인코딩과 설정을 동일하게 하기 위해서 찾아보았다.


터미널은 환경 변수를 통해 문자 인코딩을 설정하기 때문에 해당 환경 변수를 출력해보면 된다.

$ echo $LC_CTYPE

$ echo $LANG



혹은 locale 명령을 통해 확인할 수 있다.

$ locale charmap



출처 : http://stackoverflow.com/questions/5306153/how-to-get-terminals-character-encoding

간단하게 배치 파일을 작성할 일이 있어서 작성 중에 echo에서 줄바꿈, 혹은 공백 라인 출력을 하려고

@echo 도 해보고

@echo \n

@echo 공백

@echo ㄱ+한자+9 도 해보았으나 되지 않아 검색해보니


@echo text & echo.next line 이 정답.

도대체 추측할 수조차 없는 줄바꿈 방법이었다.


출처 : http://stackoverflow.com/questions/132799/how-can-you-echo-a-newline-in-batch-files

회사에서 OpenPaaS 프로젝트와 CSB.IO 개발을 함께 할 분들을 채용하고 있어서, 이력서를 살펴보고 있다. 지원 조건은 경력 2년 이상, 자바 웹 서비스 개발 이력이다. 부가적으로 우대 요건으로는 Open PaaS 프로젝트와 CSB.IO에 맞는 경력이나 관심 사항이 있으신 분이다.


지원해 주신 분들이 첨부해주셨던 간단한 자기 소개와 이력서를 평가자의 입장에서 보고 있으면, 함께 일을 하는데 맞는 조건을 가진 분들을 찾게 되지만, 장점보단 단점이 먼저 눈에 들어오게 된다. 즉 '깔 요소'를 먼저 찾게 된다.

경력 2년 이상으로 조건을 걸었지만, 지원하신 분들 대부분이 10년 이상의 경력을 가지신 분들이 대부분이고, 마흔을 넘기신 분들이 많다.

경력 상으로도, 경험 상으로도 나보다 더 많은 프로젝트를 하시고, 산전수전을 다 겪으셨을터인데, 내 경력과는 상관없이 이 분들을 평가하게 되고, 적합하신 분을 찾아 이력서를 보고 계신 분들과 의견을 나눈다.


내가 속한 팀(이라고 해도 현재는 2명이지만)과 같이 일하게 될 사람이고, 현재 팀에서 PL을(어쩌다보니) 내가 담당하고 있어 나도 이력서 검토와 면접을 함께 진행하게 되지만, 이력서를 검토하면서 이력서를 지원하신 분들을 다소 부정적으로 평가하고 있었고, 문득 '나는 그럴 자격이 되는가?'라는 질문을 하게 되었다.


"이직 주기가 너무 애매한데..."

"하셨던 프로젝트가 너무 방향성이 없는데..."

"퇴사 사유가..."

"새로운 기술에 대한 관심이 부족한 것 같은데..."

"프로젝트에서 무엇을 했다는 건지 잘 안보이는데..."

"비전공이신데 이론적인 부분이 약하진 않으실까"

"학원 단기 교육으론 좀 부족한 것 같은데..."


나는 그들을 평가한 질문으로부터 당당할 수 있는가? 분명 그렇지 않다. 어쩌면 더 부족할지도 모르겠다.


나는 단순하게 개발 자체, 개발에 관련된 지식들을 배우는 것을 좋아하지만, 특별하게 어느 하나가 더 좋다, 더 잘한다라고 할 수 있는게 아직은 없는 것 같다.

군대 전역 후 게임만 하고, 성적은 바닥을 치던 2학년 2학기엔 수업이 끝나고 학교를 떠나면 게임을 하거나 놀기만 했던지라, 이래선 안되겠다 싶어 들어갔던, 다분히 학교에 있을 생각으로 들어갔던 자연어처리 연구실의 선배가 이런 얘길 했었다.

"넌 다 잘하는 것 같은데 특별하게 잘하는 게 없는 것 같다"

그 때에도 혼자 늘 했던 고민이기도 했지만, 타인으로부터 내가 고민하는 나의 상태를 듣게 된것은 꽤나 충격인 일이었다. 그리고 그 고민은 그 후로 몇 달 동안은 수면 위로 올라와서 학기 내내 생각했던 것 같다. 이 문제는 고민만 한다고 해결될 문제도 아니고, 그렇다고 마음대로 난 이걸 해야겠다 하고 잘 맞지 않을지도 모를, 좋아하지 않을 수도 있는 것을 잡고 가는 건 또 성격에도 맞지 않아서 스트레스만 만들어낸다.

'제너럴리스트가 되자'라고 하는 건 나에겐 어쩌면 지금 내 상황을 합리화하려는 변명일지도 모르겠다.

역시 '무엇을 잘하는가?"에 대한 질문은 스페셜리스트가 답일 수밖엔 없는 걸까


얼마 전 예전 지메일 계정의 메일을 보다가 소프트웨어 마에스트로를 하려고 마음 먹었을 때 교수님과 주고 받았던 메일을 다시 보게되었다. 주고받은 메일의 골자는 '소프트웨어 마에스트로라는 과정이 있고, 학교에서는 실무적인 내용이나 개발 전반의 폭넓은 내용을 배울 수 없어서 이 과정을 통해 배우려고 합니다.', '스티브잡스를 양성한다고 하지만 그냥 개발자를 양성하는 프로그램인 것 같다. 졸업을 늦춰가면서 그 과정에 참여하는 것 보다는 연구를 계속해서 한 방향으로 가는 것이 더 좋을 것 같다.'이었다. 전자가 내 의견이고 후자가 교수님의 의견이다.

소프트웨어 마에스트로에서 연수를 받으면서 배운 것, 그리고 좋은 멘토, 멘티들을 많이 만나서 득이 되었던 것도 많지만, 만약 그때 교수님의 조언을 듣고 자연어 처리 쪽으로 더 깊게 파보았다면 지금은 어떻게 달라져 있을까?


대학생 때 했던 고민은 여전히 진행 중이다. 여전히 내가 일하고 있는 분야에서 내가 특별히 잘할 수 있는 기술을 꼽으라면 아직은 없는 것 같다. 나는 무엇이 되어야할까?

아키텍트가 되고 싶다는 막연한 생각은 있지만 아직 노력과 의지가 부족한 것 같다. 지금은 그 전에 부족한 것들을 채워나가려고 애쓰고 있다. 이를테면 영어, 수학. 관심 분야도 조금은 줄여봐야겠다. 쓸데 없이 이것 저것 흥미를 잘 가진다. 하하..


내가 하고 싶은 것

내가 잘 할 수 있는 것

내가 해야하는 것

내가 좋아하는 것

내가 이루고자 하는 목표에 있어서 필요한 것들

단기/중기/장기적인 계획


위의 것들을 잘 정리하고 다듬어서 조금씩 채워나가야겠다. 조바심 내지 않고.




'마음이 뛰다' 카테고리의 다른 글

드디어 몸무게 앞자리가 6을 찍었다!  (2) 2015.07.29
도돌이표  (0) 2015.05.15
문제 찾기  (1) 2015.02.09
아이스 스케이트 잘 타고 싶다.  (0) 2015.01.23
연락처  (0) 2015.01.23

OpenPaaS 프로젝트에서 형상관리는 GitHub로, CI툴은 Travis-CI를 사용하기로 결정되어 개발환경 구성을 위한 설정을 진행 중입니다. 기존에 회사에서 쓰던 CI툴은 Jenkins였는데, 사용법이나 워크플로우, 화면 구성 등이 다르다보니 새로이 파악해야하는 부분들이 있어 정리하게 되었습니다.



 Travis-CI

Travis-CI는 루비로 작성된 오픈 소스 기반의 CI로, 분산 CI 호스팅 서비스를 제공합니다.무료로 사용할 수 있는 travis-ci.org와 프로 버전인 travis-ci.com으로 서비스하고 있습니다.

GitHub 아이디를 통해 가입하고, 해당 아이디의 프로젝트를 연결하여 테스트, 빌드 및 배포를 수행할 수 있습니다.

GitHub 아이디를 통해 가입한 후에 접근 권한이 있는 저장소를 읽어와서 연결하게 되고, 프로젝트(저장소)별로 빌드 수행 여부를 설정할 수 있습니다.

Travis-CI를 통해 빌드하기 위해서는 저장소의 루트에 .YAML 포맷으로 작성한 travis.yml 파일이 있어야 하며 .travis.xml 파일을 통해 설정을 관리합니다.

저장소를 연결하여 빌드를 활성화하면 해당 저장소의 Web Hook에 자동으로 Travis-CI 웹 훅이 등록됩니다. 로컬에서 작업한 후 원격 저장소인 GitHub로 커밋하면 웹 훅을 호출하여 자동으로 Travis-CI를 통해 빌드를 진행합니다.


현재 지원하는 언어로는

  • C
  • C++
  • Cloujure
  • C#
  • D
  • Dart
  • Erlang
  • F#
  • Go
  • Groovy
  • Haskell
  • Java
  • Javascript (Node.js)
  • Julia
  • Objective-C
  • Perl
  • PHP
  • Python
  • R
  • Ruby
  • Rust
  • Scala
  • Visual Basic

이렇게 23개 언어를 지원하고 있습니다. 각 언어의 특성에 맞는 빌드 설정을 설정 파일인 .travis.yml 파일 내에 작성하여 프로젝트를 빌드하거나 배포할 수 있습니다. 예를 들어 자바의 경우에는 Maven, Gradle, Ant를 지원하고 프로젝트에 맞게 선택하여 적용할 수 있으며, Oracle JDK 7, Open JDK 6과 같이 JDK의 버전을 선택할 수 있고, 커스텀 스크립트를 통해 JDK8이 필요한 경우 JDK 6이 필요한 경우를 나누어 작업을 진행할 수도 있습니다.


Travis-CI를 사용하기 위한 간단한 순서입니다.


1. 회원 가입

Travis CI를 사용하기 위해서는 GitHub 계정을 통해 가입하게 됩니다. Travis CI 홈페이지에서 가입할 수 있으며

GitHub의 과금 정책과 유사하게 http://www.travis-ci.org 에서는 공개된 저장소(Public repository)만 사용할 수 있고, 비공개 저장소(Private repository)를 사용하기 위해서는 프로버전인 http://www.travis-ci.com에서 유료로 사용할 수 있습니다.

프로 버전에서는 플랜에 따라 병렬로 진행할 수 있는 작업(Job)의 수가 달라지며 플랜은 아래와 같습니다.

(Open Source 라고 표시되어 있는 부분이 travis-ci.org 입니다)


https://travis-ci.com/plans


GitHub 계정을 통해 가입하게 되면 저장소에 대한 접근 권한을 허용할 수 있는 페이지가 나타납니다. 여기서 원하는 저장소에 대해 접근 권한을 설정한 후 가입을 완료하게 되고, 추후에 GitHub의 계정 설정 페이지에서 수정할 수 있습니다.


2. GitHub 웹 훅 확성화

로컬에서 작업 후 GitHub로 푸시하게 되면 웹 훅을 통해서 Travis CI에서 자동으로 해당 커밋에 대한 빌드를 수행할 수 있도록 GitHub에서 저장소에 웹 훅을 추가해주어야 합니다. 저장소 설정에서 웹 훅을 추가하기 위해서는 해당 저장소의 설정을 수정할 수 있는 관리자 권한이 있어야 합니다.

웹 훅 설정은 GitHub에서 저장소로 이동한 후 저장소 세팅 페이지에서 "Webhooks & Services" 메뉴를 선택하여 설정할 수 있으며 혹시 Travis CI 서비스가 자동으로 추가되지 않았다면 추가해주면 됩니다.

(저는 웹 훅 활성화가 자동으로 설정이 되어있어서 따로 손 댈 부분은 없었네요.)



3. 저장소에 .travis.yml 파일 추가

Travis CI에서 프로젝트를 빌드하기 위해서는 저장소의 루트에 .travis.yml 파일을 추가해주어야 합니다. 

만약 .travis.yml 파일이 없거나 유효하지 않은 경우에는 Travis CI는 해당 프로젝트를 Ruby언어로 작성되었다고 간주하고 기본값으로 빌드를 수행하게 됩니다. Travis CI의 문서 페이지를 통해 언어별로 상세한 옵션을 확인할 수 있습니다.


제가 테스트를 위해 작성한 .travis.yml 파일은 아래와 같습니다.

language: java

jdk:

  - oraclejdk7

after_success:

  - ls -la ./target

deploy:

  provider: openshift

  user: junyoung.plum@gmail.com

  password: $OPENSHIFT_PASSWORD

  domain: nnoco

  app: travistest


언어는 Java로 되어있고, JDK는 oraclejdk7을 사용하며, 빌드가 성공적으로 완료된 후에(after_success) ls -la ./target 명령을 수행하고, 배포는 Openshift로 하도록 설정한 모습입니다.


참고로 Travis CI에서는 환경변수 설정을 지원합니다. 테스트로 사용하는 GitHub의 저장소는 Public인지라 .travis.yml 파일도 노출이 되는데 처음에는 아무 생각없이 오픈시프트의 password를 적으려고 하다가 공개된다는 걸 깨닫고는 Travis CI에서 지원하는 저장소 자체의 환경 변수를 이용해 패스워드를 설정했습니다. (오픈시프트로 배포하는 경우에 인증을 위해 Token을 사용할 수도 있지만 아직은 지원이 되지 않는다고 하네요)


위와 같이 .travis.yml 파일을 저장소 루트에 저장하고, 커밋하면 제가 테스트로 수행한 경우에는 Maven으로 빌드 관리를 하고 있으므로 Travis CI에서 루트에 있는 pom.xml 파일을 자동으로 탐지하여 Maven을 이용해 빌드를 수행하게 됩니다.


4. GitHub 저장소로 푸시하여 빌드 수행

.travis.yml 파일을 추가해준 후 처음으로 로컬에서 GitHub로 푸시하면 Travis CI의 빌드 큐에 작업이 추가되고, 언어에 따라 사용가능한 워커가 선택되어 빌드를 수행하게 됩니다.

Travis CI의 문서에서는 Travis CI에서의 프로젝트 첫 빌드 수행시에는 GitHub의 테스트 훅 버튼을 사용하지 말라고 되어있네요.



5. 빌드 설정 수정

프로젝트의 성격에 따라 빌드 설정을 수정해 줍니다. 예를 들어 테스트를 수행하기 전에 데이터베이스를 생성하거나 기본 설정과 다르게 빌드를 구성하여 수행할 수 있습니다.


빌드 설정 커스터마이징에 대한 내용은 Travis CI 문서의 customize your buildhow to install dependencies for your project 에서 확인하실 수 있습니다.


빌드 설정을 수정한 후에는 travis-lint 명령을 통해 올바른 YAML 포맷으로 작성되었는지 확인해 주시면 됩니다.




이 후에 필요한 추가적인 정보는 Travis CI의 문서 페이지에서 확인하실 수 있습니다.

프로젝트의 언어나 빌드 툴에 따라 문서 페이지에서 설정을 확인하여 적용하여 사용하시면 되겠네요.

(추가적으로 Travis CI를 사용하면서 테스트한 Deploy에 관한 설정이나 Travis CI의 Build Lifecyle 등에 대한 내용을 추가적으로 포스팅할 예정입니다.)



※ 참고 자료


자바 애너테이션 기반의 HTTP 클라이언트 라이브러리.


안드로이드 관련 프로젝트를 진행하면서 안드로이드 애플리케이션이나 SDK에서 안드로이드 SDK를 제외하고 가장 많이 공통적으로 쓰였던 부분은 HTTP Client가 아니었나 싶다.

HTTP 통신은 비교적 손이 많이 가는 편이고, 핵심 코드에 비해 주변코드가 많이 작성된다. DB를 프로그래밍 할 때와 비슷하게 주변코드는 공통적으로 처리되는 부분이 많고, 핵심 코드에 집중해서 HTTP 클라이언트를 작성하고 싶다는 생각을 항상 하고 있어서, 이를 애너테이션 기반으로 만들어보면 어떨까 하는 생각에 구상하게 되었다.


프로젝트 네이밍은 자바의 애너테이션 기호인 @을 우리말로 읽을 때 '골뱅이'라고 많이 읽는 것에서 '골뱅'으로 하고, 영어로 쓰면 'gol bang'이므로, 의미는 없지만 '#!' 을 해쉬뱅(Hash bang)으로 읽으니 'Gol!' 으로 축약하였다. (하이고 의미없다, 그치만 개인적으로는 마음에 든다 하하;)


Gol!의 목표는 HTTP 통신을 간편하게 핵심코드만으로 처리할 수 있도록 하는 것이다. 즉 핵심 로직에만 집중할 수 있도록 하여 생산성을 향상시키는데 있다. 고려해야하는 것들은 HTTP 프로토콜, 비동기 요청의 처리 및 비동기 요청 시의 콜백 처리 등이다.

Gol!의 기본적인 개념은 메서드와 HTTP 요청을 1:1로 매핑하는 것이고, 메서드 호출이 곧 HTTP 요청이며, 메서드 파라미터는 쿼리스트링이나 HTTP 메시지 본문이 되며, 리턴 타입이 응답 메시지이다. (비동기의 경우에는 리턴에 대한 처리를 콜백에서 하도록 해야한다.) 이 외에 요청에 관한 데이터(헤더, 요청 URL, 메서드 등)은 애너테이션을 통해 메타 데이터로 제공한다. 애너테이션의 경우 리터럴 상수만 인자로 받을 수 있으므로, 동적으로 요청에 대한 정보를 변경할 수 없다. 따라서 메서드 파라미터 애너테이션을 통해 요청에 대한 정보를 동적으로 제공할 수 있도록 설계하여야 한다.

개별 요청에 대한 정보는 메서드 및 메서드 애너테이션으로 제공하고, 서버에 대한 공통적인 설정은 인터페이스에서 할 수 있도록한다.


기본적으로는 위와 같은 모습으로 메서드가 작성이 되고, 자바의 동적 프록시를 통해 HTTP 요청을 공통으로 처리할 것이므로, 위 요청 메서드는 인터페이스 내에 작성하도록 한다. 따라서 Gol! 사용시에는 요청에 대한 데이터만 인터페이스로 제공하고, 요청에 대한 세부적인 로우레벨의 코드 구현은 최대한 배제할 수 있도록 한다.


예상되는 가장 큰 이슈는 메모리와 속도 이슈가 아닐까싶다. 애너테이션은 리플렉션을 통해 실제 값을 얻을 수 있으므로 여기에서 한번 속도 및 메모리 이슈가 발생하고, 사용자의 구현을 단순하게 하게 위해서 동적 프록시를 적용하게 되므로 또 한번 속도 및 메모리 이슈가 발생한다. 또한 사용자 구현은 단순화되지만, 라이브러리 자체의 복잡도가 높아져서 설계를 잘해야할 듯 하다.. ㅜㅜ


조금씩이라도 부지런하게 작성하고, 개선해봐야겠다. :)

점심으로 돈수백이란 식당에서 돼지국밥을 먹었더랬다. 다 먹고서는 티슈로 입 주변을 닦았는데 피가 묻어나왔다.
양쪽 입가에서 묻어 나오길래 입술이 건조해서 갈라지는 바람에 피가 났나하고 생각했다. 입술 끝에 티슈를 지긋이 대고 있어봤지만 피는 묻어나오지 않았다. 그새 튼 곳이 아물었나?
식당에서 나오는데 입안에 피맛이 감돌았다. 응? 침을 뱉어보니 붉은 빛이 어른하다. 잇몸이나 치아가 아픈 느낌은 없는데 멈추지 않고 계속 난다.
잇몸에서 피가나나..? 보통은 양치하다 피가 나도 금방 멈췄는데 계속 나고 있다.
치과를 가봐야하나..? 여기 근처에 치과 간판을 본 것 같은데 그리로 가볼까?
양치를 하고 나니 피가 좀 멈추어서 잇몸 건강에 대한 걱정은 조금 줄었다.
혓바늘이 난 것 같다. 거울에 혀를 비추어보미 혀끝 오른쪽에 혓바늘이 난 모습이다.
그제서야 나는 밥을 먹다 혀를 깨문게 생각이 났다. 밥을 먹고 나서부터는 혓바늘과 같은 느낌의 신경쓰임과 통증이었던지라 마냥 혓바늘로만 생각했다. 헌데 그게 아니라 혀를 씹어서 피가 났던 거고, 혓바늘이 아니라 그냥 혀에 상처가 난 거였다.
내 몸이고 내 입속이니 상처에 대한 피드백은 당장에 내가 알 수 있을건데 그걸 깨닫지 못하고 잇몸에서 피가 나는 줄로만 생각했다.
내 몸의 문제도 정확하게 인지하지 못하는데, 실재하는 문제들, 서로 이해하지 못하는 문제들을 인지하거나 해결하는 건 어쩌면 당연하게도 쉽지 않은 것일 수 있겠단 생각이 들었다.

Open PaaS 사업이 2차년도에 접어들면서(일정상으로는 3월부터 2차년도 시작이지만 올해 초부터 이미 2차년도 일이 진행되었다.) 업체별로 개발 범위가 정해지고 예산이 책정되고, 클라이언트가 없이 요구사항을 도출하고, 유스케이스를 작성하고 있다.
프로젝트 특성상 여러업체가 참여하고 있다보니 용어가 하나로 일치되지 않고, 혹은 일치되었더라도 의미를 다르게 해석하는 일이 종종있다.
더군다나 나같은 경우에는 1차년도에 분석했던 OpenShift를 개발하는 것이 아니라 다른 업체가 분석했던 CloudFoundry를 기반으로 개발을 진행하다보니 같은 말인 듯 다르게 생각하거나, OpenShift는 이렇지 않은데 CloudFoundry는 왜 그렇지? 하는 생각이 들 때가 많다.
어쨌거나 유스케이스의 액터의 역할이 정확하게 정의되어있지 않고, 다르게 알고 있던터라 오전에 다른 업체, 품질팀의 수석님과 함께 액터 도출 및 역할 정의에 대해 회의를 했다.
역할은 어느정도 정해졌지만, 액터명에 대해서는 서로 합의하고 정하긴 했지만 나에게는 영 석연치않다.
이를테면 PaaS에서 애플리케이션을 개발하는 조직을 관리하는 액터의 이름은 Paas사용자(관리자) 로 정해졌다.
기존에 같은 역할의 액터 이름은 애플리케이션 관리자였는데 이는 애플리케이션을 서비스할 때 운영하는 사람으로 느껴진다 해서 이를 새로이 정한 것이다.
애플리케이션 관리자보다는 조금은 역할을 포괄하는 의미에 가까워지긴 했지만 보다 명확한 액터 이름으로써 정해졌으면 했다.
조직 관리자로 하자는 의견을 냈으나, CloudFoundry에서 사용하는 Organization과 용어가 겹쳐서 새로 접하는 사람들에게는 혼동의 여지가 덜하겠지만, 현재 프로젝트에 참여하고 있는 사람들이 헷갈릴 수 있기 때문에 수용되지 않았다.
이런 쪽, 저런 쪽으로 의견을 내어보아도 이미 서로가 어느정도 생각이 정해져 있기 때문에 이해하거나 설득하기가 어렵다.
이쯤되면 나는 더이상 의견을 내고 설명하고 설득하는데 지쳐서 마음에 들지 않더라도 현재 상태에서 수긍하고 받아들이게 된다.
사실상의 포기인 셈이다. 계속해서 얘기해도 벽에다 얘기하는 기분이 들기때문인데, 어쩌면 상대도 비슷하게 느낄지도 모르지만, 보통 나는 상대의 의견을 따라가는 편이 된다.

이런 상태에서 끝까지 물고 늘어져 내가 원하는 모습으로 만들어내야하는 건지, 이쯤에서 합의를 하고 이 문제에 대해 고민하거나 거론하지 않아야 하는건지, 답이 있는지 모르겠다.
비단 오늘의 이 회의 뿐만이 아니라 이전에도 그러했다. 상대의 논리가 명확해서 거기에 깔끔하게 동의할 수밖에 없는 상황은 별로 없었고, 사실 논리를 떠나서 이해득실이나 개개인 또는 단체의 욕심도 이 문제에 개입이 될 것이라 생각한다.
시간이 지나서 '봐라. 그때 내가 맞았니', '니가 맞았니' 해봐야 그때에 바꿀 것이 아니고서야 마음의 응어리를 덜어내는 것 말고는 바뀌는 것이 없다. 반대로 누군가는 응어리가 질 수도 있는 거고.
괜히 퍼실리테이터 같은 직업이 나오고 필요로 하는 게 아닌 것 같다.
회의로 인해 인력, 심력, 시간을 낭비하는 것보다, 꼭 완벽한 답은 아니더라도 적정선에서 합의를 보고 결과를 내야하는 걸까?

'마음이 뛰다' 카테고리의 다른 글

도돌이표  (0) 2015.05.15
정작 나는 준비되어 있는가?  (0) 2015.03.27
아이스 스케이트 잘 타고 싶다.  (0) 2015.01.23
연락처  (0) 2015.01.23
나름 다듬어 가기  (2) 2015.01.08

지금 근무지가 시청 건너편이라 서울 광장과 거리가 아주 가깝다. 걸어서 3분 정도.


장소가 장소인지라 행사나 시위를 하는 날이 많은데, 창 밖에서 들려오는 소리가 도로 위를 지나는 자동차소리 밖에 들리지 않는다면 아주 조용한 날이다.

시위나 농성은 그들의 목소리를 내기 위한 방법이지만, 처음엔 좋게 받아들이려 해도 주변에 이렇게 피해를 주면서까지 해야하는 건가 라는 생각이 들 정도로 앰프의 볼륨이 높다. 정말 소음이다.

정말 소리가 컸던 날은 소리 때문에 창문이 우우웅 하고 울렸으니 시청을 길건너에 두고 있는 우리 건물은 그 소리가 그대로 들릴 수 밖에 없다.

이제는 몇 달 그런 소릴 듣다보니 익숙해져서 노래나 멜로디도 흥얼거리며 따라 부를 정도가 되었지만 초반에는 집중도 안되고 스트레스를 받기 일수였다.


이제 겨울이 되니 이곳이 좋은 점이 있다.

아이스 스케이트장이 서울 광장에 세워졌다. 다음 달 8일까지 오픈이니 부지런히 타야지

여자친구는 나에게 신기하다고 했던 나의 '잘하고 싶은' 욕구에 대해 얘길 나누었던 적이 있는데, 여러가지 이유들로 인해 나는 내가 하는 것들을 잘하고 싶어한다.


스케이트의 경우라면

1. 사람들이 많더라도 자유롭게 탈 수 있을 만큼 타고 싶다.

2. 잘 타는 사람들이 무척이나 부럽다. 눈이 가게 된다.

3. 내 자신의 실력에 대한 욕심이 난다.

4. 실력이 늘어남에 따라 성취감을 느낄 수 있다.

5. 잘하는 것 그 자체를 좋아한다.

6. 이곳에서 탈 수 있는 건 2월 8일까지이다.

정도로 정리할 수 있겠다. 참 쓸데없다. ㅋㅋ


스노우 보드를 배울 때는 동영상 강좌가 조금이나마 있어서 강사에게 배우지 않아도 어느정도는 익힐 수 있었는데, 아이스 스케이팅은 생각보다 동영상 강좌를 찾기 어려웠다. 그래서 대안으로 인라인 스케이트를 비교적 쉽게 찾을 수 있어서 이를 보면서 용어나 연습 방법들에 대해서 찾아보고 있다.

강좌를 찾으려고 했던 것보다 스케이팅할 때 정강이 쪽의 근육을 과하게 사용해서 펌핑이 심하게, 근육이 땡땡해질 정도로 굳어짐과 통증이 있어서 이유를 찾아보려고 했는데, 인라인 스케이트를 타시는 분들도 그런 증상이 있어서 왜 그런지 이유를 알 수 있었다.

헌데 용어가 어려워서 뭐라는지 잘 이해하지 못한 건 함정.

뭐래더라 백푸시가 어쩌구 저쩌구랬는데.. 어쨌거나 생각한대로 올바르지 않은 자세인가보다~하고 이해했다.

뒤로 넘어지지 않으려고 발 앞꿈치를 항상 들고 있는 상태라 정강이쪽 근육에 항상 힘이 들어가있어서 그렇다고 했다.



'마음이 뛰다' 카테고리의 다른 글

정작 나는 준비되어 있는가?  (0) 2015.03.27
문제 찾기  (1) 2015.02.09
연락처  (0) 2015.01.23
나름 다듬어 가기  (2) 2015.01.08
멀쩡하던 OpenShift가 죽었다.  (0) 2014.10.17

+ Recent posts