사람은 후천적으로 배우는 자인가? 타고난 재능으로 살아가는 자인가? 라는 질문들은 어려서부터 많이 들어왔던 질문이고, 스스로에게 또는 주변에 많은 사람들과 여러가지 상황에서 반문하는 질문일거다.

회사에서, 학교에서 그리고 가정에서 또는 남자라면 당연히(?) 다녀오는 군대조직에서 어떤 목적을 향해서 탁월한 리더십을 보여주는 사람들이 있고, 이들을 자신의 역할 모델(role model)로 삼아서 닮으려고 노력할 것이다.

사람은 사회적 존재라 사람들과 여러가지 형태로 관계를 맺으면서, 살아가고 있고 이러한 관계속에서 조직의 형태가 나타나기도 하지만, 외부에서 바라볼때는 결과론 적으로만 리더십을 바라볼 것이다.
어떤면에서 이러한 것이 객관성을 부여할지도 모르지만, 이 자체로는 개개인이 생각하는 역할모델을 모두 만족시키기 어려울 뿐더러, 여러가지 상이한 이견들이 존재할 것이다.
하지만 궁국적으로 자신이 생각하는 모습이 있을 것이고, 이를 통해서 자신이 생각하고 있는 가치관이 자연스럽게 발현될 것이다.

내가 어렸을때부터 배웠던 리더십은 섬김의 리더십이었다. 다른이들을 자신과 같이 동등하게 또는 보다 우월하게 여기면서 배풀고 배려하는 리더십이었다. 일반적으로 약하자가 강한자를 돕기보다는 강한자가 약하자를 돕는 것이 흔히볼 수 있는 풍경이다. 우리가 살고 있는 상식적인 세상에서는 말이다.
섬김의 리더십 역시 강한자가 약한자를 돕기 위한 리더십이고, 이러한 리더십으로 인해 세상의 시계는 정상적으로 돌고 있는 것이다.

내가 철이들고 일을 시작하면서 보고 배웠던 리더십은 역할모델을 통한 리더십이었다.
이는 내가 닮고 싶어하는 열망과 배우고 싶어하는 강한 욕구가 만들어 내었던 것이었는데, 여러 종류의 다양한 사람들이 이 안에 포함된다.
부족한 내면의 모습과 역량들을 다른 사람을 통해서 알고, 이를 배워서 나의 부족한 부분들을 채우려 했던 것이다. 어떤 때는 좋은 모습을 배울수 있었고, 어떤 때는 좋다라고 생각했던 모습이 내가 수용할 수 없었던 적도 있었다. 하지만, 부족한 부분들은 메꿈에 있어서는 정도에 차이는 있었지만 나에게 유익했다고 생각하고 있고, 지금도 내게 영향을 주고 있다.

누군가는 이글을 보고 이렇게 이야기 할지 모른다. 가치관이 형성되고 있고, 이를 통해서 인격이 형성되고 있는 것이라고 말이다. 나도 그 이야기에 100% 동의한다.
리더십이란, 리더가 리더십을 이야기함으로써 세워지는 것이 아니라, 리더를 바라보는 사람들이 그를 쫒기를 결정함으로써 만들어지기 때문이다. 스스로 만들어 세우는 것은 제대로 된 리더십을 세울수 없기 때문에 사람들 또는 팀원들에게 강요가 되고, 강제가 될 수 있고, 때로는 공포가 될 수 있다.

내가 만났던 다양한 리더십들의 소유자들은 강력한 카리스마를 가졌던 사람들도 있었지만, 그 영향력은 그렇게 오래 지속되지 않았었다. 스스로 그를 배우려고 노력하는 사람들이 없어지면, 아무리 강한 카리스마 조차도 조만간 사라지고 말 뿐이다.
좋은 리더를 만나면, 단지 혜택만 누려서만 안된다. 결국 배우고 받은 것들을 나누어 주어야, 영속성이 생기고 계속 누릴 수 있는 것이기 때문이다. 그리고 이용해서도 안된다. 그 리더십이 더 큰 힘을 받을 수 있도록 옆에서 도와 주어야 한다. 결국은 희생이 없이는, 노력이 없이는 가치가 유지되기 힘들다.

자, 그러면 나는 어떠한 리더십을 가졌을까? 사람들이 나를 배우려고 노력을 하나? 과연 나는 내 자신의 얼굴을 바로 세울만큼 잘 살고 있는 것일까? 이러한 것이 단이 남을 의식하는 것인지? 아니면 스스로를 반문하면서 자신의 모난 부분을 깨뜨리는 과정일지 스스로에게 물어보게 된다.

이러한 것이 너무 길다면, 간단한 질문이 내게 있다.
결과적으로 내가 사랑하는 아이에게 나는 어떤 사람으로 생각되어 질까?

내가 살아가면서, 좋은 사람들을 많이 만나게 해다라고 기도하곤 한다. 그리고 그들을 만나서 같이 일하고 이야기 할 수 있는 것들이 너무나도 감사하다. 다들 하는 일과 목표하는 것들이 잘 풀려서 잘 살았으면 좋겠다.

오늘 갑자기 여러 생각들이 들어서, 펜을 들어 글을 썼는데, 이유는 팀을 옮기면서 좋은 사람들을 많이 만날수 있어서이고, 이전에 같이 일하다가 대학교 교수로 자리를 옮겨간 누군가와 오늘 기분좋게 만나게 되어, 기뻐서 이기 때문이다. 이런 와중에 호주에서 잠시 한국에 들어와 지난 토요일과 일요일, 연 이틀동안 나를 바람 받게한 일민(Toby)가 생각났기 때문이다.

이런 와중에도 갑자기 "무슨 부귀영화를 누리려고..."라고 말했던 류모씨가 생각이 나는 까닭은 무슨 연고인가? ^^
Posted by 행복상자
기다렸던 사람들이 많았을 것 같다. 이제야, 오늘에야 Spring 3.0.0 RC1이 나왔으니까 말이다. 물론 Toby(일민)이를 비롯한 몇몇 선행적인 개발자들이 이미 열심히 공부하고 있고, 이의 전달도 열심인 것에 비하면, 최근에 나는 크게 관심을 두려고 노력하지 않았다. 개인적으로는 다른 사업부로 옮겨와서, 새로운 일을 맡아서 관심이 적어진(?) 것도 있지만, 사실은 그것 보다도, 기존에 내가 만든 Framework는 스프링 2.5.5 또는 2.5.6을 기반으로 설계되어 있다. 그리고 이것을 이용하여 여러 솔루션들이 개발되고 있는 중이어서, 자체 개발한 Framework의 Minor 체인지가 아닌 Big 체인지를 결정하기 쉽지 않기 때문이다. 만약 그것을 결정해야 한다고 해도 2년 후가 될 것이다. (상품으로 그리고 서비스를 하고 있는 시스템을 변경하기란 많은 결정해야할 문제에 직면해야 하는 용기가 필요한다. 그러나 이것은 모험이 아니다.)

현재 Springframework에서 제공하고 있는 메이져 Branch는 2가지이지만 앞으로는 3가지가 될 것이다.
Springframework 1.2 와 2.5 그리고 향후 주축이될 3.0이다.
그리고 이제는 3.0 Release Candidate 1이 나왔다. 이제는 또 열심히 공부할 시점이 된 것이다.
여러가지 변경된 API라이브러리들도 있고, 추가된 라이브러리들이 있는데, 이중에서 가장 먼저 눈에 들어왔던 것은 Jackson JSON라이브러리이다. 이른 아침에 Jackson 투터리얼을 보면서 시간 가는줄 몰랐다.
앞으로 정식 버전이 나올날이 멀지 않았지만, 언제가 될지는 잘 모르겠다. 올해 안에는 나오지 않을지...

Springframework 3.0 RC1의 변경 사항은 다음의 링크를 보면된다.

그리고, 아래는 이번에 RC1에 추가된 내용이다.

Changes in version 3.0.0.RC1 (2009-09-25)
-----------------------------------------

* upgraded to CGLIB 2.2, AspectJ 1.6.5, Groovy 1.6.3, EHCache 1.6.2, JUnit 4.7, TestNG 5.10
* introduced early support for JSR-330 "javax.inject" annotations (for autowiring)
* introduced early support for JSR-303 Bean Validation (setup and MVC integration)
* added default editors for "java.util.Currency" and "java.util.TimeZone"
* refined PathMatchingResourcePatternResolver's treatment of non-readable directories
* PathMatchingResourcePatternResolver understands VFS resources (i.e. works on JBoss 5.x)
* revised AccessControlContext access from BeanFactory
* AbstractBeanDefinitionParser can deal with null return value as well
* PropertyOverrideConfigurer's "ignoreInvalidKeys" ignores invalid property names as well
* PropertyPlaceholderConfigurer supports "${myKey:myDefaultValue}" defaulting syntax
* BeanFactory's default type conversion falls back to String constructor on target type
* BeanFactory tries to create unknown collection implementation types via default constructor
* BeanFactory supports ObjectFactory as a dependency type for @Autowired and @Value
* BeanFactory supports JSR-330 Provider interface as a dependency type for @Inject
* BeanFactory prefers local primary bean to primary bean in parent factory
* protected @Autowired method can be overridden with non-annotated method to suppress injection
* private @Autowired methods with same signature will be called individually across a hierarchy
* @PostConstruct processed top-down (base class first); @PreDestroy bottom-up (subclass first)
* ConfigurationClassPostProcessor detect @Bean methods on registered plain bean classes as well
* support for default "conversionService" bean in an ApplicationContext
* MBeanServerFactoryBean returns JDK 1.5 platform MBeanServer for agent id "" (empty String)
* changed NamedParameter/SimpleJdbcOperations parameter signatures to accept any Map value type
* refined logging in JMS SingleConnectionFactory and DefaultMessageListenerContainer
* introduced "ui.format" package as an alternative to PropertyEditors for data binding
* @RequestMapping annotation now supported for annotated interfaces (and JDK proxies) as well
* @RequestParam and co support placeholders and expressions in their defaultValue attributes
* @Value expressions supported as MVC handler method arguments as well (against request scope)
* JSR-303 support for validation of @MVC handler method arguments driven by @Valid annotations
* refined response handling for @ExceptionHandler methods
* @ResponseStatus usage in handler methods detected by RedirectView
* all @SessionAttributes get exposed to the model before handler method execution
* @Event/ResourceMapping uniquely mapped to through event/resource id, even across controllers
* MultipartRequest is available as a mixin interface on (Native)WebRequest as well
* removed outdated "cacheJspExpressions" feature from ExpressionEvaluationUtils
* introduced common ErrorHandler strategy, supported by message listener container
* Jpa/JdoTransactionManager passes resolved timeout into Jpa/JdoDialect's beginTransaction
* HibernateJpaDialect applies timeout onto native Hibernate Transaction before begin call
* Spring's Hibernate support is now compatible with Hibernate 3.5 beta 1 as well
* Spring's JPA support is now fully compatible with JPA 2.0 as in EclipseLink 2.0.0.M7
* SpringJUnit4ClassRunner is now compatible with JUnit 4.5, 4.6, and 4.7
* SpringJUnit4ClassRunner once again supports collective timeouts for repeated tests
* deprecated @NotTransactional annotation for test classes in favor of @BeforeTransaction








Posted by 행복상자
지난번에 글을 쓸때는, 예상했던 것보다 시간이 많이 필요했는데, 어느덧 이른 6시, 출근할 시간이 되어서 이야기를 다 마무리 못하고 펜을 집어 넣어야만 했다.

지난번 글에서는 자바에서 Exception Handling이 어떻게 생성되고, 호출하는 코드로 어떻게 알려주게 되는지를 간략하게 이야기 하였다. (뭐 간략하다고 했지만, 이미 알고 있는 내용들이 었을 것이다.)
그리고 RuntimeException의 유형의 예외들은 컴파일러에서 신경을 쓰지 않기 때문에, 반드시 Try-Catch로 블록을 만들어 줄 필요가 없다는 것을 이야기 했다. (이 경우는 개발자가 코드상에서 해결해 주어야 한다는 것도 같이 이야기 했다.)

마지막으로, Eclipse와 같은 IDE에서 자동으로 생성되는 예외 처리 코드에 관해서도 이야기 했는데, 자동으로 생성되는 메커니즘도 이야기 했었는데, 더불어서 사용할 때 주의해야 할 것은 자동으로 생성된 코드로 인해서 예외처리가 끝났다고 착각하지 말아야 한다는 것이다. 실제 예외에 대해서 프로그램 또는 클래스에서 예외처리에 대한 코드가 들어가야하고, 이를 로그로 저장하거나 화면에 뿌려줄때는 좀더 사용자 친화적인 내용으로 저장하고, 보여주어야 추후에 유지보수하기 쉽다.

오늘은 이전에 시간이 모자라서 하지 못했던 이야기를 하려고 한다.
일반적으로 try-catch블럭의 사용을 잘 알고 있을 것이고, 더불어서 finally의 사용 또한 잘 알고 있을 거라 생각한다. 호출해야 할 코드는 try블록에다 정의하고 만약 예외가 호풀되면, 이를 제어하기 위해서 catch 블록에서 정의한 코드가 호출되고, 그리고 다시 코드가 실행된다. (try 블록에서 예외가 발생했던 코드 라인 이후는 호출이 되지 않는다.)

만약, 여기에 finally구문을 사용할 경우가 있는데, 아시다 시피 이는 try 또는 catch블록에 정의된 내용이 실행과 상관없이 정의되어 있다면 만드시 실횅되도록 정의되어 있다.
이 경우에 try 또는 catch구문에 return 문이 있다면 어떻게 될까?
try 또는 catch 블록에 return 문이 있다면, 일단 finally구문에 정의된 소소 코드들을 실행하고 나서 다시 return문으로 돌아 온다는 점에 유의 해야 한다.

예외도 객체이기 때문에 이를 상속받아서 새로운 예외들을 만들수 있다. 때문에 예외처리시에 아래와 같이 모든 예외를 한번에 다 잡을 수도 있지만, 이는 바람직하지 않다. 이전글에서 설명한 것처럼 어떤 메소드를 호출할때 어떤 메소드가 호출될 것인지가 클래스와 메소드 정의서가 정의된 문서를 보면 확인할 수 있다.

try {
      runAnyCode();
} catch (Exception ex) {
     recoveryCode();
}

위의 코드의 경우는 예외느 다 잡을수 있을지 모르지만, 어떤식으로 예외를 관리할지는 전혀 알수 없다. (물론 때에 따라서는 상위의 예외로 부터 하위의 것을 모두 잡는 것이 유용할 수도 있다. 따라서 유의해서 사용해야 한다.) 꼭 필요한 경우가 아니라면, 예외별로 잘 정의해서 사용해야 한다. 아래는 예이다.

try {
      runAnyCode();
} catch (anyCodeException aex) {
     recoveryCode();
}

마지막으로 정말 중요한 것은, 예외 처리에서 순서가 있다는 것이다.
그렇기 때문에 다중으로 예외를 선언한 경우에 주의가 필요하다. 만약 어떤 예외를 상속 받아서 새로운 Exception 들을 만들었다면, 상속 받았던 에외들을 먼저 선언해 주어야 한다. 그렇지 않다면, 원하지 안는 결과를 얻을 수도 있다.
왜냐하면, JVM 에서는 첫번째 Catch블록에서 부터 호출된 예외를 처리한 Catch블럭을 찾아 내려오기 때문이다. 만약 가능한 예외 블록이 있다면, 비교를 멈추고 catch블록에 정의된 예외처리 코드들을 실행하게 된다.
따라서 만약에 첫번째 catch블록이 catch(Exception ex)라고 정의되어 있다면, 컴파일러는 다른 catch블록이 전혀 필요 없다고 생각할 것이다. (왜냐하면 이외의 catch 블록의 코드는 전혀 실행되지 않을 것이기 때문이다.) 
아래 코드에서 어떤 코드는 실행되지 않을 까요? 
try {
      runAnyCode();
} catch (Exception ex) {
     recoveryCode();
} catch (anyCodeException aex) {
     recoveryCodeNotRun();
}

내가 하고 싶은 이야기는 사실 마지막에 이야기 하고 싶은 내용이었다. Exception에도 순서가 있고 진행되는 방향이 있다. 하지만 이를 모르고서 코드를 작성한다면 의미없는 코드를 생성하게 되고 결국은 나중에 코드의 문제를 찾는데 많은 시간을 들여야 한다는 것이다. 가장 기본 적인 이야기지만 간과하는 부분이기도 해서 이야기 하고 싶었다.

이전에 인도 개발자들이 만들어 낸 코드들 분석하면서, 내가 경험했던 것들인데, 예외 처리를 했기 때문에 문제가 없을 거라는 막연한 믿음보다는 예외처리시에 필요한 코드상에서 처리해 부분(RuntimeException)들과 catch문을 사용할 때도 우선 순위를 생각하면서 정의할 것등을 반드시 숙지해야한다.
무엇보다도 가장 판단하기 어려눈 것은 try-catch문을 아무 생각 없이 중첩해서 사용하는 경우인데, 이 경우는 가독성도 떨어지지만, 예외 처리 코드를 분석하기 매우 어렵기 때무에 되도록이면 피해야 한다.




Posted by 행복상자
일반적으로 자바에서는 C++와 마찬하지로 try catch 구문을 사용하여 예외 처리(exception handling)을 하게 되어 있다. 하지만, 개발자들이 잘 알지 못하고 사용한다면, 양날의 검처럼 작용할 수 도 있고, 유익하지 않을 수도 있다.

작년과 올 상반기까지 회의 연구소 인력들과 같이 협업하는 프로젝트가 있어서, 설계와 구현을 이들과 일정 부분 코드를 나누어서 진행하였다.
일반적으로 인도쪽 개발자들은 인건비가 싸고, 개인적인 개발 능력이 뛰어 나다고 알려져 있는데, 근 1년 이상 협업을 하면서 느낀점은 사실은 그렇지 않을 수도 있다는 것이다. 일반적으로 인도는 Windows 애플리케이션 개발과 C/C++ 을 잘사용하는 개발자들은 많기 때문에 쉽게 구할수 있기 때문에 그 중에는 능력있는 개발자들이 많이 있을수 있다. 하지만 Java라는 언어를 알고 있는 개발자는 적고, 그 중에서 웹과 J2EE의 영역들을 이해할 수 있는 개발자는 지극히 드물다. 따라서 실력있는 개발자를 Java쪽에서는 찾기가 매우 힘들다.

이야기가 길어졌는데, 인도 개발자들이 작성한 코드를 우리쪽에서 Prevent라는 툴을 이용하여 정적분석을 시켰는데, 몇가지 Critical한 내용들이 보고되었다. 그래서 이를 인도 개발자에게 코드 리뷰를 하고 수정하도록 했는데, 정적분석 수행시 마다, 동일한 위험요인에 대해 지속적으로 검출되었다. 개발자는 매번 확인하고 수정했고 코드에는 예외처리가 다 되어 있어서, 문제가 있을 수 없다고 했는데도 툴은 지속적으로 문제점을 검출하고 있었다. 그래서 결국은 내가 그들이 작성한 코드를 분석하고 리뷰를 하였는데, 여러 면에서 놀라야만 했다.
이들은 자바 프로그래밍에 대한 초보자들이었다. 거의 C/C++ 방식의 코딩과 Excepion 처리를 통한 회피에만 집중하고 있었다. 너무나도 복잡하고 다중적인 예외처리 문을 사용하는 것에 대해서 혀를 내둘러야 했다. 일단 좋은 코드는 보기도 좋아야 하는데, 무슨일을 하고 무엇을 말하려고 하는지 알수 없을 정도록 예외 처리문을 반복적으로 사용하였다. 어떤 식으로든 예외를 처리하고 나오도록 코드는 되어 있지만, 몇가지 간과한 점들이 있었는데, 그 중에 중요한 점은 예외 처리에도 순서가 있다는 것이다.

예외 처리(exception handling)시에도 지켜주어야할 순서거 있고, 이를 잘못하면 원하는 결과를 얻을 수 없을 뿐더러, 코드가 복잡해 진다.

일반적으로 예외를 처리한다는 것은 어떤 메소드를 호출하고 실행할 때, 그 메소드가 어떤식으로 동작할지 아로 있어야 한다. 이는 메소드가 결과값을 반환할 뿐만 아니라, 어떠한 경우에 예외를 호출할지를 정확히 알고 있어야 한다. 

예를 들어 "java.lang.ClassLoader"라는 클래스를 사용하려고 한다면, 이 API는 아래와 같이 정의된다.

loadClass

public Class <? > loadClass(String  name)
                   throws ClassNotFoundException 
지정된바이너리명을 가지는 클래스를 로드합니다. 이 메소드는,loadClass(String, boolean) 메소드와 같은 방법으로 클래스를 검색합니다. Java 가상 머신이 이 메소드를 호출해, 클래스 참조를 해결합니다. 이 메소드를 호출하는 것은,loadClass(name, false) 를 호출하는 것에 상당합니다.

파라미터:
name - 클래스의바이너리명
반환값:
결과적으로 얻을 수 있는 Class 객체
예외:
ClassNotFoundException - 클래스가 발견되지 않았던 경우

위처럼 정의되는 API는 실행해서 결과값을 정상적으로 반환하고, 만약 실행 중에 문제가 될 경우, 이를 어떤식으로 호출하는 메소드에 알려 줄지를 정의하고 있는 경우이다. 위의 예제는 ClassLoder 클래스를 실행시 클래스가 발견되지 않는 경우에 "ClassNotFoundException"이 호출된다.
따라서 위와 같은 명세를 정확히 개발자가 알고 있어야 메소드 호출시에 어떻게 동작할지를 예측하고 코드를 작성할 수 있다.

try-catch 구문을 사용하는 것은 호출할 메소드에서 예외를 발생시킬수 있다는 것을 알고, 이를 컴파일러에 알려주는 역할을 하는 것이다. 그리고 이때 호출되는 exception도 객체로 정의되어 사용되어 진다.
그렇다면, Exception 객체는 어디에서 정의 되는 것일까? 이 객체는 개발자가 사용하고자 하는 메소드에서 정의되게 되는데, 메소드에서 "throws"구문을 찾으면 된다. 이렇게 정의된 예외는 예외가 정의된 메소드를 를 호출하는 곳으로 던져지게 된다.

자바 개발자들이 많이 사용하는 Eclipse와 같은 IDE에서는 어떤 메소드를 호출할 때 자동으로 try-catch문으로 호출하는 메소드를 감싸주는 기능을 자주 사용하게 된다. 이는 내부적으로 호출되는 메소드 내부에 "throw"구문이 호출된다는 것을 IDE툴이 알고 있기 때문이다.

한가지 더 나아가서, 자동으로 생성하는 예외코드는 보통 아래의 예외 같은 형태로 IDE상에 추가된다.
java.io.File file = new java.io.File("c:\\test.txt");
try{
    file.getCanonicalFile();
catch (IOException e) {
    e.printStackTrace();
}

한가지 주위해야 하는 것은 위와 같이 "e.pringStackTrace()"를 툴에서 자동으로 생성해 주었다고, 예외 처리가 모두 끝나는 것이 아니다. 
1. 위에서 처리해야할 예외에 대한 후 작업이 있다면 코드를 생성해 주어야 한다.
   ==> 이것은 대부분의 개발자들이 잘하고 있다.
2. 위의 예외를 Log에 남길지를 결정해야 한다. 
   ==> 이 부분은 개발자와 개발팀 내부의 결정에 따라서 정리하면 된다.
3. 위와 같은  형태가 아니라, 개발자가 나중에 알수 있는 형태의 메시지 형태로 재 정의 해서
    메시지를 뿌려 주어야 한다.
   ==> 결국은 개발자가 어떤 상황에서 에러가 발생했는지를 알수 있어야 하고, 이를 로그로
        남겨야 후처리에 도움이 될 것이다.
위와 같이 간략하게 3가지로 정리하였지만, 대부분(?)의 개발자들이 IDE툴에서 제공하는 원형 그대로의 메시지를 사용한다. Log를 남길때도 "e.printStackTrace()"의 원형 그대로 남기는데, 어떤 경우에 예외가 호출되었는지에 대한 정보를 남겨주어야 제대로 된 예외처리라 할 수 있다.

컴파일러에서는 RuntimeException과 특수한 유형을 제외한 Exception을 관리하게 되는데, RuntimeException을 확장한 예외 클래스는 그냥 모두 통과된다. (자동으로 무시된다는 의미)
이는 대부분의 RuntmeException들은 실행 중에 어떤 조건에 문제가 생기는 경우보다는 코드의 논리에 예측 및 예방할수 없는방시으로 문제가 생기는 경우에 발생하기 때문이다.
예를 들면, 배열에서 인덱스의 범위를 벗어났는지에 대해서는 배열의 길이(Size 또는 Length)를 이용해서 확인하고 방지할 수 있다.

예외 처리에 대해서, 이야기 했는데 아직 내가 하고 싶은 이야기에는 도달하지 못했다. 이는 다음에 계속 이어서 말하려 한다.

Posted by 행복상자
요즘은 생각만큼 바쁘게 사는 것인지, 틈틈히 영화를 보고 그 때의 감흥을 되새기면서 글을 쓰는 것을 잊고 있다. 아니 실제로는 바쁜 것보다 마음의 여유가 없어서 일지도 모른다. 그동안 몇개의 영화를 보았는데, 하나도 손을 대지 않고 지나쳐 버렸다. 지나고 보니 아쉬움만이 남는데, 약간의 변화를 주기 위해서 다시 글을 쓴다.

이 영화는 약 2주전에 내가 본 영화이다.
한국인 배우가 나온다고, 개봉전부터 사람들의 관심을 끌기 시작하였는데, 말을 안해도 이미 누가 나오는지는 잘 알거라 생각한다. 맞다 우리가 월드스타의 반열을 올랐다고 생각하는 배우가 몇명 있는데, 그 중의 한명인 "이병현"씨이다.

내가 이 영화를 보게 된 것은 "국가 대표"와 "해운대"가 흥행을 하는 시점에서, 지금 보지 않으면, 곧 상영관에서 내려올지도 모른다는 불안감에서 보게 되었는데, 그래도 주된 이유는 한국인 배우가 나온다는 것이었다.

영화는 블록 버스터를 좋아하는 나에게는 어떤 면에서는 맞을 지도 모르지만, 정체 불명의 단체와 시대에 맞지 않는 과학기술과 테크날로지는 영화를 보는데, 반감 또는 어색함을 주었지만, 영화를 즐기는데는 큰 어려움이 없다.

영화의 구성과 시나리오를 볼때는 몇가지 반전 사항들이 있었지만, 이는 왠만큼 영화를 즐겼던 사람들에게는 식상할 만큼 반전요소들이다.

영화는 다양하고 특이한 캐릭터들을 선보이는데, "이병헌"씨의 캐릭터는 누구보다도 눈에 잘 들어온다. 이 영화는 잘 알려진 배우들이 등장하지는 않지만, 그가 우리에게 잘 알려진 배우이기 때문일 수도 있다. 그러나 무엇보다도 그의 연기력 때문이라고 생각한다.그의 정제된 연기는 극에서 분위기와 인물을 잘 살려주고 있다.

영화 속에서 나오는 한국어는 역시 어색하다. 그러나 영화나 미국 드라마에서 한국어의 사용이 늘어나는 것운 어느 정도 우리나라의 위상이 올라가고 알려지기 때문인듯하다.

영화속에서 동양은 한국, 일본 그리고 중국이 혼재되어 있는 것으로 표현되어 졌는데, 인물들의 한국어를 사용하지만, 일본풍의 건축물과 중국의 주방과 음식물들이 보이고, 소림사를 연상케하는 연무장의 풍경등은 나에게는 이질적이다. 그러나 외국인(서양인)의 눈으로 보면 다 똑같아 보일런 지도 모른다. 

영화는 스토리와 전체적인 진행으로 보면 적당한 흠도 있고, 무리한 측면도 있지만, 만화적이고 공상과학적인 측면으로 접근한다면, 2시간 내내 볼만한 흥미거리들이 가득차 있다.

아마도, 차기 작품을 예고하는듯한 앤딩장면은 2편이 계획되고 있음을 말해주고 있다.
블록버스터를 즐기는 방법은 깊게 생각하지 않고 장면 장면을 즐기는 것이다. 더불어 감동을 줄 수 있는 영화라면 더할 나위 없겠지만, 너무 많은 것을 바란다면 재미가 반감된다.

언제 나올지 모르는 속편이지만, 좀더 군더거기 없고 말끔한 스토리 전개로 이어졌으면 좋겠다.

Posted by 행복상자
작년말 올해초에 걸쳐서, 여러 인터넷 매체와 블로그들을 통해서 "웹 브라우져 시장의 뜨거운 경쟁"에 대해서 이야기되고 논의되어 왔다.

이와 더블어 한국에서는 절대로 빼어 놓고 이야기 할 수 없는 부분이 있는데, 이는 "Active X의 지원"에 대한 이야기이다. 웹 표준은 계속해서 발전 또는 변화하고 있기 때문에, 과거와 현재의 브라우져가 동일한 결과들을 사용자에게 제공하지 못한다. (여기서 내가 변화라는 단어를 사용한  이유는 완벽한 호환성을 제공할수 없기 때문이다. 어떠한 이유에서 인지, 기존에 제공되었던 기능들이 사라지거나 제거 되고 있다.)

10년전에도 비슷한 상황들이 있었지만, 그때만 해도 Microsoft의 IE와 Netscape의 Nevigator 브라우져의 싸움이었다. 이당시에는 브라우져가 지원하려는 기능들이 지금의 것보다 제한되어 있고, 지금만큼 네트워크 망이 안정적이고, 빠르게 구성되어져 있지 않기 때문에, "표준화된 스펙을 따르기 보다는, 조금도 많은 기능들을 추가하고 좀더 빠르게 사용자에게 제공할 수 있을까?"가 경쟁의 주요 포인트 였었다.
이러한 관점에서 마이크로소프트는 자신들의 모든 역량을 브라우져 개발에 집중하였었고, 브라우져의 기능적인면과 속도의 향상적인 측면에서 넷스케이프를 압도할 수 있었다.

당시에는 두 회사의 기술적인 차이는 늦게 웹부라우져 시장에 진입한 마이크로소프트사의 주도면밀한 기능의 추가와 전략들을 선보였다. 이중에도 HTML4를 IE4에서 지원하기 시작한 것이 가장 이상적인 것이었고, 웹 브라우져를 ActiveX 컨트롤(OLE)의 컨테이너로 사용하는 것이 두번째로 인상적인 것이었다. 세번째는 브라우져와 OS가 하나의 시스템을 구성하고 있기 때문에 절대로 분리할 수 없다는 것으로, 지금도 나는 믿지 않고 있지만, 같은 시스템의 리소스를 사용하고 있다는 것이다.

이때에 벌어지기 시작한 기술적인 변화와 차이들은 두 브라우져의 간극을 더 크게 벌리기 시작하였다. (이 외에도 제품의 시장성에 대한 부분도 있지만, 이야기가 길어져서 논하지 않으련다. 당시만 해도 넷스케이프는 돈을 받고 파는 제품이었다.)
왜냐하면, 이때는 과도기였기 때문에 개발자와 사용자들이 표준화보다는, 자신이 원하는 기능들을 쉽게 개발해서 제공하 수 있었기 때문이다. 사용자들은 새로운 환경으로 적응하는 단계였기에, 기존에 PC 애플리케이션 만큼의 기능들을 웹에서 구현해서 사용하기를 원했다. (제한된 네트워크 속도와 사용성 측면에서 웹이 독립 애플리케에션을 따라가기는 쉽지 않았다.)

일례로, 1998년경에 PC통신 서비스를 웹 기반의 서비스로 만들 회사들이 있다. LG에서 만든 채널아이와 SK에서 만든 넷츠고 라는 회사였는데, 이 회사들은 웹 기반이라고 하지만, 내부는 PC 애플리케이션에서만 볼수 있는 "데이타 그리드"를 사용하여 사용자로 하여금 쉽게 사용할 수 있도록 만들어 주었다.
아마도 그때 이들 프로그램을 사용했던 사용자들은 쉽게 기억할 수 있을 것이다. 

최근의 웹 브라우져 시장에서의 경쟁은 Firefox로 부터 비롯되었다고 해도 과언이 아니다. Firefox는 첫 번째 버전부터, 사람들에게 많은 관심을 끌기 시작하였는데, 이는 몇가지 눈에 띄는 개선 사항들 때문이다.
기존 넷스케이프코드의 속도는 항상 관심사하이었지만 관심 밖이었다. 너무 브라우징 속도가 늦다는 것을 알고는 있었지만, 변경한다는 것이 쉽운 일이 아니었다. 이를 가감히 버리고 새로 브라우징 엔진을 제작한 것이 Firefox였고, 이 결정은 성공적인 결과물들을 만들어 내고 있다. 그리고, Addon 애플리케이션의 지원이 또한 이전과 차별화된 개선 사항이다. 오픈소스 개발자들이 만들어진, 질 좋은 Application들을 쉽게 찾고 사용할 수 있도록, Echo System을 갖추어 놓았다는 것이 사용자와 개발자들을 머무르고 지속적으로 사용하도록 만든다. 

Apple의 사파리 브라우져 역시 빠른 브라우징 속도와 사용자 경험을 무기로 내세워서 조금씩 사용자들에게 알려지기 시작하고 쓰이고 있는 중이다. 최근에 속도를 내면서 버전업을 하고 있는 구글 크롬 브라우져 역시 애플과 비슷한 전략을 취하고 있지요.

중요한 점은 이들 새로운 브라우져들이 특징으로 HTML5를 지원하려 한다는 것이다. 따라서 앞으로 새로운 웹 표준을 지원하기 원한다면, HTML5의 지원이 선행되어져야 하는데, 이를 사용한다는 것은 호환성을 보장 받지 못한다는 의미가 될수도 있다. 앞서도 이야기 되었지만, 기존에 지원되던 기능들이 여러 이유들로 인해서 삭제되고, 사용할 수 없는 것들이 있기 때문이다. 반대로 생각하면, 좀더 쉽게 개발할 수 있는 기능들도 같이 새로 들어 가기 때문에 좀도 쉽게 개발할 수 있다는 의미로 받아 들일 수도 있다.
아래 링크를 보면, HTML5의 신규 기능들을 볼 수 있다.
속도와 새로운 기능들로 무장한 새로운 브라우져들이 우리 앞에 나타났고, 현재 유럽에서는 IE의 시장 점유율이 40%대로 떨어졌다고 한다. 여기에는 많은 브라우져들의 노력이 있지만, IE에 대한 MS의 지속적인 지원들이 없었던 것에도 기인한다고 할 수 있다. 마치 우리가 잘아는 토끼와 거북이의 우화 처럼 말이다.

아래의 이미지는 온전한 HTML5를 지원하는 브라우져를 만날 시점들을 브라우져의 버전별로 정리한 표이다. (참조: http://www.hagenburger.net/2009/05/4-useful-html5-browser-support-overviews

 
위 내용으로 보면 IE는 9.(2010년경)에서나 겨우 만나 볼 수가 있을 것이다. (붉은 색으로 표시된 것은 준비가 안된 상태임).

최근 브라우져 시장은 여러 브라우져들을 출중한 기능들로 인해서, 굉장히 복잡하고 어떤식으로 진행될지 예측하기가 어렵다. 하지만, 이로 인해서 덕을 보는 사람들은 사용자와 개발자(?)들인데, 이전까지 경험하지 못한 새로운 것들을 쉽게 접할수 있고, 이로 인한 즐거움은 역시 즐기고자 하는 사람들이다.

브라우져 개발사는 개발사대로 열심 있어야 하지만, 개발자들은 개발자 나름대로 준비를 해야 한다. 새로 변경되고 바뀌는 것에 대해서 제대로 알고 있어야, 원하는 서비스를 잘 만들수 있기 때문이다.

MS의 최근 고민은 ActiveX를 죽이는 것에만 있는 것이 아니다. MS는 IE6 버전을 죽이기(?)위에서 애를 쓰고 있다, 최근 10년간 표준 처럼 사용되었던 IE는 근 1~2년 사이에서 3개의 새로운 버전을 개발해서 시장에 내보내고 있다. 결국은 유지보수와 호환성 그리고 보안성의 이슈가 나오기 마련인데, IE6를 현재까지 사용하는 사람들이 아직도 많기 때문이다. (관련 기사: http://www.etnews.co.kr/news/detail.html?portal=001_00001&id=200909100186)

새로운 기능을 탐재한 브라우져들이 계속해서 나오고 있다. 개발자의 관점에서 보면, 이들 브라우져들 모두를 지원하기 위해서 좀더 많은 노력과 시간이 들어간다고 투덜거릴수도 있지만, 결과적으로는 좋은 방향으로 흘러갈 것이다. 그렇게 때문에 새로운 게임의 법칙이 만들어 지거나, 온전한 표준화가 진행되어져야만 브라우져를 만드는 개발사들과 이를 통해서 서비스를 제공해야 하는 개발자와 이를 즐기는 고객들이 행복해 질수 있을 것이다.
Posted by 행복상자

최근에 아는 지인과 이야기 하다가, PNG 파일의 변환 이야기가 나왔다. 하고 있는 일이 있는데, 몇가지 풀리지 않는 이미징 프로세싱상의 문제점이었는데, 나의 호기심을 자극하였다.

내가 그동안 알고 있는 PNG파일에 대한 내용은
1. 라이센스가 없다.
2. R,G,B 와 알파 채널을 제공한다.
이것이 전부이다. 그래서, 쉽게 쓰고, 편하게 쓰자 였다.

요즘 왠만한 웹사이트와 개발되는 프로그램들은 PNG파일들을 대부분 기본으로 지원하고 있다. 이는 개발툴과 Application 기본적으로 지원하고 있다는 말이다.  iPhone에서도 기본 이미지는 png 파일을 이용해서 메뉴 아이콘을 구성하고 있다.

관련 자료들은 내가 잘 이용하는 위키디피아에서 찾아 보았다.
PNG파일데 대한 다음 링크를 브라우져에서 열어보면, 아래와 같은 목차가 나타난다.


세부 사항들은 위에서 각 링크를 찾아 보면 되고, 간략하게 PNG파일에 대해서 요약하면,
PNG 는 Potalble Network Graphics의 약자로, 무손실 데이터 압축을 사용하는 비트맵 이미지 포맷이다. PNG는 GIF 포맷을 개선하고, 대체하기 위해 만들어진 포맷으로 파일 포맷에 대한 라이센스를 필요로 하지 않는다. PNG는 palette기반의 24bit RGB color와 greyscale RGB 그리고 RGBA (알파체널을 포함한 RGB) 이미지들을 지원한다.
그리고, 이 파일 포맷은 인터넷상에서 전송을 위한 목적으로 설계되었기 때문에, 전문 적인 디자인을 위한 CMYK와 같은 color space는 제공하지 않고 있다.

마지막으로 PNG 파일은 "PNG" 또는 "png" 확장자로 사용되고, 인터넷에서 주로 사용하고 있는 Mine media type으로는 "image/png" 로 정의해서 사용한다.

PNG file의 헤더는 8 byte로 되어 있다. (필드의 세부 내용은 아래 참조)
Bytes Purpose
89 Has the high bit set to detect transmission systems that do not support 8 bit data and to reduce the chance that a text file is mistakenly interpreted as a PNG, or vice versa.
50 4E 47 In ASCII, the letters "PNG", allowing a person to identify the format easily if it is viewed in a text editor.
0D 0A A DOS style line ending (CRLF) to detect DOS-UNIX line ending conversion of the data.
1A A byte that stops display of the file under DOS when the command type has been used—the end-of-file character
0A A UNIX style line ending (LF) to detect UNIX-DOS line ending conversion.



PNG 파일을 사용하는 .Net Framework의 예제는 아래와 같다.
(물론 여러 툴에서 각각 UI 에서 지원하기 위한 클래스와 API가 있지만, 단지 내가 좋아하는 VB를 좋아하기 때문에 예제도 MSDN에서 찾아 보았다.)

다음 링크를 따라 가면, 2개의 예제가 있다.

사용하는 예제는 무척 간단한다. Encode 또는 Decode 클래스를 이용하면되는데, 기본적인 사용법을 알아두면, GIF 나 JPEG 의 Encode 또는 Decode 클래스를 쉽게 이용할 수 있다.

[PNG Image를  Decodeing 하는 예제]
' Open a Stream and decode a PNG image
Dim imageStreamSource As New FileStream("smiley.png", FileMode.Open, FileAccess.Read, FileShare.Read)
Dim decoder As New PngBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default)
Dim bitmapSource As BitmapSource = decoder.Frames(0)

' Draw the Image
Dim myImage As New Image()
myImage.Source = bitmapSource
myImage.Stretch = Stretch.None
myImage.Margin = New Thickness(20)

[PNG Image를  Encodeing 하는 예제]
Dim width As Integer = 128
Dim height As Integer = 128
Dim stride As Integer = width
Dim pixels(height * stride) As Byte
' Define the image palette
Dim myPalette As BitmapPalette = BitmapPalettes.Halftone256
' Creates a new empty image with the pre-defined palette
Dim image As BitmapSource = System.Windows.Media.Imaging.BitmapSource.Create( _
width, height, 96, 96, PixelFormats.Indexed8, myPalette, pixels, stride)
Dim stream As New FileStream("new.png", FileMode.Create)
Dim encoder As New PngBitmapEncoder()
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString()
encoder.Interlace = PngInterlaceOption.On
encoder.Frames.Add(BitmapFrame.Create(image))
encoder.Save(stream)


Posted by 행복상자
미국 시간으로 지난 9월3일 (한국 시간으로 9월 4일)자로 Release 되었다. 이번에 릴리즈된 버전은 Java와 Python 버전으로 각각 제공되는데, 이는 XAPP를 지원하기 위한 것이다.
XMPP는 eXtensible Messaging and Presence Protocol (XMPP) 로 알려져있는 XML기반의 Real time Messaging 서비스이다.

아래의 링크에서 다운로드 하면된다.
- Download: http://code.google.com/p/googleappengine/downloads/list

이번 1.2.5 릴리즈에 포함된것은 그동안 이슈트랙커에 올라온 신규 기능들에 요청중에 많은 사람들의 우선적으로 지원해 주기를 바랬던 기능이었기 때문이이다.

이번에 제공되는 새로운 API들을 이용하면, XMPP기반의 네트워크 프레임워크 상에서 다른 사용자들과 메시지 교환이 가능해 진다. Google Talk와 Google Wave와 같은 Application 과도 마찮가지로 메시지를 교환할 수 있다.

다음 링크를 살려보면, Google App에 포함된 XMPP의 간략한 설명과 예제를 살펴볼수 있다. Java와 Python버전이 있다.

- Java: http://code.google.com/intl/ko-KR/appengine/docs/java/xmpp/
- Python: http://code.google.com/intl/ko-KR/appengine/docs/python/xmpp/

위 링크들을 따라가면, 예제를 살펴볼수 있는데, 코드와 이를 App Engine에서 사용하기 위해서 Config에 추가할 내용들이 있는데, 이는 간단하지만, 주의 깊게 살펴볼 필요가 있다.

그리고, 마지막으로 googlel app engine의 API들은 제약조건들이 있는데, 이것들을 잘 살펴보아야 한다.
예전에 Twitter의 Open API를 테스트하다 보니, 테스트 코드를 몇번 실행을 안했는데, 계속 서버에서 블록킹 되고 결과는 정상적으로 나오지 않았던 적이 있었다. 알고보니 트위터에서는 시간당 100개의 Request와 하루에 2000개의 Request를 사용할 수 있다는 제약이 있었다.

Quter와 제약에 대한 내요은 아래와 같다.

Each XMPP service request counts toward the XMPP API Calls quota.

Each outgoing XMPP chat message counts toward the following quotas:

  • XMPP Data Sent
  • XMPP Recipients Messaged
  • Outgoing Bandwidth (billable)

Each outgoing XMPP chat invitation counts toward the following quotas:

  • XMPP Data Sent
  • XMPP Invitations Sent
  • Outgoing Bandwidth (billable)

Each incoming XMPP message counts toward the following quotas:

  • CPU Time (billable) (50 ms/message)
  • Requests
  • Incoming Bandwidth (billable)

Computation performed in a request handler for incoming XMPP messages applies toward the same quotas as with web requests and tasks.

For more information on quotas, see Quotas, and the "Quota Details" section of the Admin Console.

In addition to quotas, the following limits apply to the use of the XMPP service:

Limit Amount
incoming message size 100 kilobytes
outgoing message size 100 kilobytes


Posted by 행복상자