2012-09-15

mac에서 iso를 usb로 옮기기. 부팅 가능하게.

우선 아래 명령으로 usb 의 device명을 알아낸다.

$ sudo diskutil list

나의 경우는 /dev/disk4 였다.

usb를 꽂고 diskutil 로 erase 를 해준다. ms-dos (FAT)로.

그런 다음 partition을 unmount하자. 이 때 usb는 diskutil에 여전히 표시되고 있다.

이제 터미널에서 다음을 입력한다.

sudo dd if=myfile.iso of=/dev/disk4 bs=8192

음... 부팅안되는구나. 미안. ㅋ

2012-09-12

roo 를 적용하면서 오늘 하루 종일 기존 repository (가내 수공업 repository)를 active record 로 모두 바꾸고 있는데, 웹 서핑 하다 보니 다시 spring jpa 기반 repository로 바꾸고 싶다. active record 는 작은 프로젝트, repository 는 큰 프로젝트에 알맞다고...(?)

2012-09-11

참... 별 일이 다 있네. 경품에 당첨되다니... ㅋㅋ

2012-09-07

어제 내가 관리하는 서버가 ssh 접속이 안된다고 카페24에서 전화가 왔다. 덜컥... 후덜덜... 아직 정식으로 사용하는 시스템이 아니긴 해도, 백업 설정도 안되어 있는데...

또, 내 주제에 시스템 보안을 완벽히 할 자신도 없다는 생각도 든다. 

이럴 바에야 클라우드로 가는게 좋겠다는 생각이 드는데... 클라우드로 가도 시스템 보안은 마찬가지인가? 그렇다면 paas로 가야 하나?

jade4j

java에서 jade를 쓰고 싶어서 scalate를 쓰게 되었는데, jade4j로 갈아 타야겠다. 복잡한 페이지는 컴파일하는 시간도 오래 걸리고. 메모리는 왜 일케 많이 잡아 먹는거야. app reload하면 2~400메가씩 점유량이 올라가니 tomcat메모리를 max 2G 줘도 몇번 코드 수정하고 나면 빌빌댄다.

반면 jade4j는 그냥 text를 parse하여 변환하는 것 같다. pegdown, ognl 같은거 쓰더라. 에러 났을 때 보여주는 ui는 play와 닮았던데 그대로 가져온 모양이다. 멋지다. 페이지 inheritance도 훨씬 잘되어 있고. mixin은 써본 적 없지만 잘만 하면 좋은 용처가 있을 것 같고.

슬슬 옮겨 가자.

--

ognl을 사용하므로 scala 문법의 if, for 등을 ognl 구문으로 바꾸어야 한다.

.getXXX 메소드 호출을 .xxx 와 같이 property 접근으로 바꾸어야 한다. sublime text에서 작업해야만 했다.
Find: \.get(.)
Replace: .\L\1

jade4j 에서는 BigDecimal 을 표시할 때, scale 대로 표시해준다. db에 설정된 scale대로 값을 가지므로 사실상 정수임에도 불구하고 .0000 과 같이 소수점이하 자리가 표시된다. ognl 은 객체의 메소드 호출을 지원하므로, 이런 류의 포맷팅을 위한 객체 및 메소드를 만든 다음, 이 객체를 페이지의 모델에 포함시켜, 페이지에서는 이 객체의 메소드를 호출함으로서 원하는 조작을 할 수 있다. 이 외에도 그 객체에 유틸리티 메소드를 정의해두면 좋을 것이다.

uri method를 f.uri로 바꾸기.

Find: =\{uri(.+)\}
Replace: =f.uri\1

ConversionService와 @ModelAttribute 를 이용한 Entity Update (수정) 처리

스프링 사용자 그룹에 질문을 던졌다.

ConversionService 를 이용한 id -> ModelAttribute 변환

결론은 허탈하게 해결되긴 했지만 그래도 나름 내부 구조를 이해하는데 도움이 되기도 했으니 다행이다.

하지만 나로서는 더 중요한 문제가 해결되었다. 수정폼의 submit을 매우 간단하게 처리할 수 있게 되었다.

예전에는 이렇게 했다. http://blog.jabberstory.net/2012/08/blog-post.html

하지만 이제 매우 간단해졌다. 그냥 uri 와 @ModelAttribute로 받고 저장하면 끝. controller를 분리할 필요도 없다.

@RequestMapping(value="/user/{user}", method=RequestMethod.PUT)
public String update(@ModelAttribute("user") User user) {
   UserRepository.save(user);
}

여기서 uri에 있는 "user"와 @ModelAttribute에 붙어 있는 "user"가 같아야 한다. 그리고 String -> User 변환을 위한 Converter를 등록해 두어야 한다. 이 converter는 db에서 주어진 user 문자열로 User를 찾는 작업을 한다.

예전에 했던 방식은 UserDto로 @ModelAttribute으로 받은 다음, 별도로 find한 User에 필드 복사를 일일이 해주었다. (bean의 속성을 복사하는 유틸리티 클래스를 이용하기도 했다)

이렇게 하다가 귀찮아서 merge()를 사용했는데, merge()도 위험하다. 수정 폼에 모든 필드가 없다면 @ModelAttribute으로 받은 dto에는 null 필드가 있을 것이고, 이게 db필드로 들어갈 위험성이 있기 때문이다.

이에 대한 해결책으로 토비 책에는 @SessionAttributes을 사용하라는 얘기가 나온다. 하지만 이것도 해결책은 될 수 없는데, 동시에 열려 있는 여러 User에 대한 수정폼을 처리할 수 없다. session에 저장된 user는 하나이기 때문이다. (3.1 이전에 출간되었기 때문에 어쩔 수 없지 않았나 생각한다)

하지만 ConversionService와 @ModelAttribute을 동시에 이용하면 위의 문제를 모두 해결할 수 있다.

success !

2012-08-29

Junit에서 Hamcrest 최신버전 사용하기

maven pom.xml을 다음과 같이 바꾸면 됩니다.

<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-all</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit-dep</artifactId>
    <version>4.10</version>
    <scope>test</scope>
</dependency>

요약하면 junit을 junit-dep 이것을 사용하면 됩니다. hamcrest를 뺀 것이죠.

2012-08-28

Spring ROO 적용

spring mvc 로 잘 만들고 있던 프로젝트였는데, 갑자기 Roo 가 눈에 들어왔다. Roo의 ActiveRecord가 좋아 보였던 것. 그리고 Controller들의 기본 구현 등...

머.. 사실 ActiveRecord 를 쓸지, Repository를 쓸지 아직 고민이긴 하지만..

딴거 할일은 많았지만... 이미 내 손은 Roo를 적용하고 있다. ㅠㅠ.

기존 프로젝트를 Roo기반으로 바꾸면서 일어 났던 일을 (뒤늦게)기록해 본다. (처음부터 기록하면서 작업했으면 좋았을걸)

아무래도 Roo가 생각하는 기본 프로젝트 구조가 있기 때문에, 테스트로 Roo 프로젝트를 하나 만들고 jpa, web mvc 까지 다 세팅한 다음, 이 놈을 참고 하면서 작업하는 것이 좋을 것이다.

우선 web.xml.

web.xml에 스프링의 xml 설정 파일을 지정하는데, roo는 기본적으로 소스의 resources 쪽에다가 applicationContext.xml 을 만들고, WEB-INF 쪽에 webmvc-config.xml 를 만들고 있다. 나도 그에 따라서 spring의 xml 파일 대거 리팩토링!

그리고 나는 hibernate를 쓰고 있었는데, roo는 jpa를 선호하는 것 같으니 jpa설정까지 해 줌. (설정을 복사하는 수준).

덕분에 pom.xml 파일도 수정이 필요했는데, roo프로젝트의 pom.xml을 참고해서 빠진 것들 복사함.

그런 다음 roo shell에서 jpa setup 명령했더니 ... 별로 하는 일 없음. 내가 이미 다 했음.

이제 도메인 클래스들을 손볼 차례인데, 이 부분이 작업이 크다. Controller, Repository 모두 손봐야 한다.

이제 entity jpa --class <기존 클래스> --testAutomatically
했더니.. 뜨아... 내 클래스 덮어 씀. 그냥 기존 클래스 위에
@RooJavaBean
@RooToString
@RooJpaActiveRecord
@RooEquals
네개의 annotation 추가. 글고 테이블에 version 칼럼 추가.

이 때, 다른 화면을 실행 해보니 동작은 함. 하지만 jpa가 사용되고 있는 것은 아니고 여전히 hibernate 기반으로 동작하는 것이겠지. 방금 수정한 entity에 대한 controller는 에러 남.

IllegalStateException  Post-processor tried to replace bean instance of type XXX with (proxy) object of type [YYY] not supported for aspect-configured classes


하지만 

java.lang.IllegalStateException: Post-processor tried to replace bean instance of type [kr.co.gaon.irs.basic.Bank] with (proxy) object of type [$Proxy112] - not supported for aspect-configured classes!


왠지 늪에 빠진 느낌. 글고 sts 3.0으로 하고 있는데 이게 아직 안정화가 덜 되서 그런지 너무 느리다. 도대체 뭘 하고 있는지 모르지만 cpu는 100~200% 기본이고...

sts 재시작 한 번 해주고... (씁쓸하구만...) 그래도 문제 해결은 안되고...

검색해보니 @Configurable 과 @Transactional 을 같이 쓸 수 없다는 얘기가 나온다. 아니다. 어라... 되네? 아까 Build Automatically를 잠시 꺼두었던거 때문인가? 

계속하자. 이젠 Table 이름을 잘못 찾아가고 있다. @RooJpaActiveRecord(table="BankAccount") 라고 했는데, bank_account 라는 테이블로 sql이 날아간다. 
이 문제는 persistence.xml 에서 ImprovedNamingStrategy 때문에 발행하는 것. comment out하자.

이제 동작한다. 휴~~

하지만... 왜 일케 메모리 사용량이 많은겨... reload 한 번 하면 2G를 채워버리네...

<Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
이 녀석 때문인가? 


javaagent 방식으로 바꾸니 좀 낫구나. 아니다. 마찬가지구나.

<context:load-time-weaver aspectj-weaving="autodetect" />
삭제해도 잘 동작한다. 지우니 메모리 사용량이 떨어졌다.

오늘은 일단 여기까지.

2012-08-20

맥에서 vmware로 맵피 설치

맥에서 맵피 업데이트 하려고 vmware fusion 에서 삽질하고 있는데, xp가 sd카드를 자꾸 write protected로 인식해서 할 수 없이 깨끗한 xp vm에서 하니 제대로 sd 에 쓸 수 있게 되었음.

그런데 맵피 Smart Connector 가 한글이 다 깨지고... (내 xp가 영문버전이라 그럴 수 있음. 하지만 예전에는 잘 나왔다구!)

대충 설치에는 문제 없겠지 하며 전체설치를 진행하는데 이젠 머 다운로드가 안돼. 몇번을 해도 안돼. 또 다운로드 안돼서 설치 중단된 것 같은데 왜 오류보고 보낼라 그러나? 그러지 말라고 체크박스를 uncheck하려해도 클릭할 수 없다. ㅋㅋㅋ 할 수 없이 그냥 확인.


결국 오늘은 설치 포기. 내일 다시.

update. 08.22) 프로그램의 한글이 깨지는 이유는 XP 언어 설정 중에 유니코드가 아닐 경우 사용할 인코딩 설정이 영어로 되어 있었음. Korean 으로 바꿀려 했더니 xp 씨디 넣어라 하네. 귀찮음. 어쨌거나 이 설정 때문에 음성파일이 다운로드가 안되고 있었음.

eclipse의 tomcat launch configuraton

이클립스 workspace를 dropbox 폴더 안에 두고 사용하는데, 드랍박스가 너무 고생하는 것 같아 톰캣 webapp 경로를 temp 디렉토리로 변경했음.

-Dspring.profiles.active=DEV -Dcatalina.base="/Users/shawn/temp/wtp" -Dcatalina.home="/Users/shawn/apps/tomcat" -Dwtp.deploy="/Users/shawn/temp/wtp/wtpwebapps" -Djava.endorsed.dirs="/Users/shawn/apps/tomcat/endorsed" -Xmx1024m -XX:MaxPermSize=512m

2012-08-13

@PathVariable 이름만 바꾸었을 뿐인데

두개의 컨트롤러에서 같은 시그너처의 핸들러가 메소드만 다르고 모두 같을 때(클래스 레벨 매핑까지), 스프링 시작하면 에러 난다. 같은게 있다고. 이럴 수가... 했는데

PathVariable 이름을 바꾸니 된다. 헉. 그렇다면 PathVariable 이 없을 때는 어떻게 되나? 에이 테스트하기 귀찮아.

예방접종 안하는 이유

어린이 집에서 왜 예방접종을 안하는지에 대해 부모님의 의견서가 필요한 모양이다. 자꾸만 제출해 달라고 독촉이 온다.

현재 우리 아이는 29개월이다. 아직까지 한번도 예방접종을 하지 않았다. 현재 매우 건강하다. 밥도 매우 잘 먹고. 몇 번의 열과 감기 증상이 있었지만 병원과 한의원을 오가며 진찰을 받고 적절히 판단하여 필요하다면 약을 먹이거나, 혹은 굳이 먹일 필요가 없다고 판단될 때에는 각탕과 같은 요법을 처방했더니 스스로 이겨 내었다. 밥도 뚝딱 잘먹고 병치레도 거의 없으니 참으로 고마운 일이다. 아는 후배의 경우 아이가 자주 아파 걸핏하면 병원에 간다는데 우리는 그럴 일이 없으니...

사실 이렇게 건강한데에는 집사람의 노력이 컸다고 생각한다. 임신전, 임신중에도 스스로 먹거리를 매우 조심했고 운동도 열심히 했는데, 사실 이게 쉬운게 아니다. 우리가 일상에서 먹는 군것질 대부분이 아이에게 좋지 않다. 엄마의 건강이 아이의 건강이라고 했을 때, 우리 아이가 건강한 이유의 99%가 이러한 엄마의 노력 때문일 것이라고 생각한다. 지금도 군것질은 하지 않으려고 노력하고 있다. (그런데 요즘 점점 이 녀석이 군것질에 맛들이고 있다. 큰일이다. ㅋㅋ. 외사촌 누나 영향이 크다.)

제목에는 예방접종 안하는 이유라고 적었지만 사실 끝까지 안할 생각은 없다. 다만 지금 굳이 해야 하나 의심할 뿐이지. 오히려 백신을 통해 예방을 하는 것보다는 우선 몸 자체의 면역력을 올리는 것이 더 중요하지 않겠는가. 백신 접종은 열심히 하면서 먹거리와 자연 치유력에 신경쓰지 않는다면 너무 쉽게 몸을 생각하는 것이 아닌가.

그리고 백신의 위험성에 대한 두려움도 있다. 백신의 위험성에 대해서는 안전한 예방접종을 위한 모임 에서 좀 더 다양한 주장을 읽어 볼 수 있다. 이 사이트에 있는 주장을 믿느냐고 묻는다면 별로 할 말은 없다. 이런 주제는 워낙 양쪽 주장이 첨예하게 부딪치는 문제라 쉽게 어느쪽 주장에 손을 들어 주기는 어렵다. 단지 주장이 문제가 아니라 그 근거를 알려면 의학 및 관련 통계에 대해서도 지식이 풍부해야 한다. 나같은 일개 프로그래머가 머라 주장하기는 좀 힘들다. (하지만 살아보면 느낌이란게 있긴 하지).

그리고 나는 자본(제약회사. 병원. 그에 종사하는 이해관계자들)이 하는 일을 크게 믿지 않는다. 자본은 기본적으로 돈버는 일에만 관심이 있지 선량한 의지는 없다. 문제가 생기면 문제없다고 뻐팅기기만 하고, 결국 문제가 드러나면 슬그머니 후퇴한다. 백신의 역사도 그렇다. 백신의 부작용이 이렇게 알려진 것도 그 누군가의 피눈물과 항의가 있었기 때문이지 그들은 스스로 문제점을 인정하지는 않는다. (혹시 아직도 백신에 수은이 있나 모르겠네). 국가가 하는 일도 마찬가지다. 국가는 기본적으로 자본의 대리인이 아니던가. 국가는 백신 예방접종에만 신경쓰지 말고, 전 국민의 먹거리 안전과 자연 치유력 향상을 위해 더 노력해야 할 것이다. 하지만 그들이 과연 그렇게 해 줄까?

(웬지 제목이 검색에 너무 쉽게 노출될 것 같다. 댓글로 엄청 까일 것 같은 불길한 기분이...)

2012-08-10

스프링 @MVC 수정 폼 처리하기

Spring MVC 3.0: How do I bind to a persistent object

@ModelAttribute의 쓰임새는 무엇인고?

How does @ModelAttribute work?

@RequestMapping(value="/user/{id}", method=RequestMethod.PUT)
public String submit(@ModelAttribute User user) {
   ...
}

@ModelAttribute("user")
User loadUser(@RequestParam(defaultValue="-1") long id) {
    if (id == -1)
        return new User();
    log.info("Loading user info from db: " + id);
    return userService.findById(id);
}

이 코드가 의도하는 것은 @ModelAttribute 가 바인딩 되기 전에 db로 부터 User 객체를 로드하는 것이다. 이렇게 db에서 user를 로드한 다음 바인딩하면, User 필드에는 있지만 폼에는 필드가 없어서 기존 db 필드를 null로 지워버리는 불상사를 막을 수 있다.

문제는 위 코드의 경우 loadUser()가 이 컨트롤러의 다른 메소드에도 실행된다는 것이다. 이건 좀 깔끔하지 못하다. 좋은 방법을 모르겠다. 위 코드만 따로 뽑아서 새로운 컨트롤러를 만들 수도 있겠다. 이렇게 하면 엔티티마다 XxxModifyController 를 만들어야 한다. 이것도 그리 썩 좋지는 않지만 다른 방법이 없네.

ConversionService로도 안될 것 같고. @SessionAttributes를 사용하면 한 세션에 여러 엔티티에 대한 폼을 열 경우 문제가 된다.


update(2012.9.6): 위 해결책도 나름 방법이긴 하지만 ConversionService를 이용하면 된다. 그러나 스프링 3.1이후에서만 된다.

2012-07-27

인간에 대한 오해

두번째 오류는 서열화(ranking)다. 사람에게는 보잡한 자료들에 번호를 매겨 점차 상승하는 단계로 늘어세우려는 버릇이 있다. 진화상의 변화가 진보를 향해 나아가며, 점진적으로 발전한다는 통념이 대표적인 것이다(그러나 실제 진화는 반드시 진보적이지 않고 오히려 퇴화하는 것처럼 보이기도 하며, 대개 방향성보다는 다양성의 증가 형태로 나타난다). 이런 서열화를 위해서는 모든 사람을 한 줄로 늘어 세워야 하고 제각기 어울리는 지위를 부여하기 위한 기준이 필요하다.  
그리하여 나타나는 세번째 오류가 정량화이다. 이것은 숫자로 모든 것을 바꾸어 표현하는 것이다 (IQ검사와 같은 간단한 테스트...)...

- 하리하라의 '과학고전카페 1' 인간에 대한 오해 중

2012-04-16

밥따로 물따로


요즘 음식 조절 중이다. 밥따로 물따로.


아침 저녁 두끼만 먹고 있다. 물은 식사 전후 2시간에는 먹지 않는다. 국과 찌게는 먹지 않는다. 몸무게는 5kg 정도 빠졌다. 몸무게는 아직도 계속 빠지는 느낌이다. 더불어 간식도 먹지 않는다. 어쩌다 먹어도 단거, 짠거, 고기는 먹지 않는다.


몸무게가 빠지는 이유는 물을 안먹어서인 것 같다. 그 외에는 딱히 내 생활이 바뀐 것이 없으므로. 음… 술도 안먹고 있구나.


물을 안먹으면 갈증날 것 같아 어떻게 하지? 하고 생각하는 사람이 있을 것 같은데 의외로 갈증날 일이 없더라. 식사후 2시간 후에 물을 먹으면 되는데 2시간 동안 무언가에 집중하고 있으면 시간 금방 가고, 또 막상 물 먹어도 될 시간이 되어 먹을려고 하면 또 그다지 물먹고 싶은 맘도 없고.


밥따로 물따로에 대해서는 큰형이 아주 오래전(10년도 넘은 것 같아)에 소개해 주어서 알고는 있었는데 이번에 관련 책도 좀 더 조사해 보면서 더 자세히 알게 되었다. 관련 서적으로는 다음 정도 읽어보면 된다. 주요 서적은 ‘밥따로 물따로 음양식사법’이다.



그냥 소개만 받은 것이 아니고 우리 가족 중에 두 분이 이 방법의 혜택을 입었다. 아버지께서는 뇌경색으로 몸이 움직이지 못할 뻔 했는데 이 방법으로 단 몇개월만에 멀쩡해지셨다. 형수께서도 심장에 종양이 있었는데 몇개월 후에 종양이 사라졌다는 진단이 나왔다.


물론 책에는 이보다 더 많은 사례가 있다. 가장 생생한 사례는 ‘4개월의 기적’ 책을 읽어보면 된다. 사이트는 여기이고 이상문 선생님의 강의 동영상도 있다.


밥물의 핵심은 밥따로 물따로인데 부언하면 몸이 뜨거워져야 할 때에 물로 불을 끄는 짓을 하지 말라라고 요약할 수 있다. 몸이 장작불처럼 타오를 때에 아무 때나 시도 때도 없이 물을 마셔대니 몸이 축축해지고 활발함을 잃는다는 것이다. 그러니 병이 날 수 밖에.


내가 해 본 결과 일단 호흡이 안정됨을 느낄 수는 있었다. 이런 안정감 이전에는 무언가 항상 떨림이 있었다고 (지금 미루어) 생각하고 있다. 내 몸이 쓸데 없이 바쁜 것이다. 이로 인해 몸이 항상 긴장하고 있고, 들떠 있는 것이다. 밥물을 하면서는 호흡이 안정되니 복식 호흡도 더 잘된다. 그 외 더 좋은 점은 좀 더 해봐야 알겠고. 최소한 보름 이상은 해야 한다고 한다.


사실 내가 정확하게 밥물식사를 하고 있는지 잘 모르겠다. 언젠가 신대방에 있는 사무실을 찾아가서 코칭을 좀 받아야 될지도 모르겠다.


그런데 내가 왜 이런걸 하게 되었느냐.


요즘 소화가 너무 안된다. 그래서 저번 주에 병원가서 암 정밀진단, 심장정밀진단 받았다. 위내시경 결과로는 ‘만성위축성위염’, ‘장상피화생’이 나왔다. 이번주 금요일에 정확한 진단 결과가 나온다. 어디서 들어보니 ‘장상피화생’은 거의 위암 직전 단계더라. ㅠㅠ

2011-12-07

mysql utf-8 세팅

이런걸 위해 굳이 레퍼런스까지 찾아보기는 귀찮고, 나중에 참고하며 반복하기 좋으라고 기록해 둔다.

/etc/mysql/my.cnf 파일을 열고 아래 내용을 추가한다.

[client]

default-character-set=utf8

[mysqld]

default-character-set=utf8
default-collation=utf8_general_ci
init_connect=set collation_connection=utf8_general_ci
init_connect=set names utf8
character-set-server=utf8
collation-server=utf8_general_ci
character-set-client-handshake = TRUE

[mysql]

default-character-set=utf8

mac osx 에서는 위에 있는 것을 다 할 필요 없이 몇가지만 입력하면 되더라. mac에서는

/usr/local/mysql/support-files$ sudo cp my-medium.cnf /etc/my.cnf
한 다음 my.cnf 를 수정한다.

[client]

default-character-set=utf8

[mysqld]

character-set-server=utf8
collation-server=utf8_general_ci

[mysql]

default-character-set=utf8

아래와 같이 나오면 된듯 하다.

mysql> show variables like 'c%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
| collation_connection     | utf8_general_ci            |
| collation_database       | utf8_general_ci            |
| collation_server         | utf8_general_ci            |
| completion_type          | 0                          |
| concurrent_insert        | 1                          |
| connect_timeout          | 10                         |
+--------------------------+----------------------------+
14 rows in set (0.00 sec)

2011-07-20

몸 사랑 건강법

집에서 굴러 다니던 종이 쪼가리. 

소설로 읽는 프로젝트 관리 - 데드라인

읽어야지 하다가 이제 겨우 읽었다. 책 내용 중에 주인공인 톰킨스가 교훈을 일지로 남기는 내용이 있다. 책의 요약 정도가 될텐데, 책을 읽은 사람만 그 교훈을 제대로 느낄 수 있을 것이므로 여기에 옮겨 두어도 될 듯 하다. 

톰킨스의 일지에서...

훌륭한 관리를 위한 4가지 필수 요건
  • 적절한 사람들을 구한다.
  • 그들에게 알맞은 일을 할당한다.
  • 항상 동기 부여를 한다.
  • 팀이 결속하도록 하고, 그 상태를 유지하도록 돕는다.
  • (이 외의 나머지 일은 전부 허드레 관리업무다)
안전과 변화
  • 사람들은 안전하다고 느끼지 않는 한 변화를 수용하지 않는다.
  • 변화는 프로젝트를 성공시키기 위해서 (그리고 그만한 가치가 있는 대부분의 노력을 위해서도) 필수적이다.
  • 안전성이 부족하면 사람들은 위험을 감수하려고 하지 않는다.
  • 위험을 피하는 것은 치명적이다. 위험과 연관되어 있는 이점도 놓치기 때문이다.
  • 사람들은 직접적으로 위협을 받거나 자신들에게 악용될지도 모르는 권력을 인지할 때 불안함을 느낄 수 있다.
부정적인 압력
  • 협박은 실적을 유도하기에는 불완전한 방법이다.
  • 처음부터 할당된 시간이 충분하지 않다면 아무리 진지하게 협박하더라도 작업은 제 시간에 끝나지 않는다.
  • 설상가상으로, 목표한 바를 얻지 못한다면 협박한 대로 이행해야 할 수도 있다.
관리자가 가져야 할 필수 감각
  • 관리에는 마음과 본능과 정신 그리고 후각이 필요하다.
  • 그러므로
    마음으로 이끌고,
    본능을 믿고 (직감을 믿어라),
    조직에 정신을 심어 주고,
    거짓말을 식별할 수 있는 후각을 키워라.
관리의 메타포(metaphor): 전투지휘
  • 전투가 시작되면 관리자의 실제 업무는 이미 끝난 것이다.
인터뷰와 채용
  • 채용할 때는 모든 관리 감각이 필요하다: 마음, 정신, 후각, 그리고 본능 (하지만 대부분 본능이 필요하다).
  • 혼자 하려고 하지 마라 - 두 사람의 본능이 한 사람의 본능보다 두 배 이상 좋다.
  • 새로 채용한 사람에게 자신이 이미 증명했던 바로 그 수준의 프로젝트를 수행하게 하고, 능력을 확장할 수 있는 목표는 다음으로 미루도록 요청한다.
  • 조언을 부탁한다: 당신이 가장 채용하고 싶어하는 사람이 또 다른 훌륭한 사람을 알고 있을 수도 있다.
  • 말하기보다는 들어라.
생산성 향상
  • 생산성에 관한 단기적인 해결 방안은 없다.
  • 생산성 향상은 장기적인 투자의 결과다.
  • 즉각적인 결과를 보장하는 것은 모두 헛소리다.
위험관리
  • 프로젝트의 위험을 관리하는 것으로 프로젝트를 관리한다.
  • 각 프로젝트의 위험을 조사하고 관리한다.
  • 궁극적으로 바람직하지 않은 결과를 추적하는 것이 아니라 원인이 되는 위험을 추적한다.
  • 각 위험에 대한 발생 확률과 예상되는 소요 비용을 평가한다.
  • 각 위험에 대해 위험이 구체화되는 것을 나타내는 초기 증상을 예상한다.
  • 무엇이든지 '할 수 있다'는 자세를 갖고 일하지 않아도 되는 사람을 위험담당자로 임명한다.
  • 나쁜 소식이 조직의 계층 구조 상위로 전달되는 데 용이한 (필요하다면 익명으로) 채널을 수립한다.
방어하기
  • 손실을 줄인다.
  • 성공을 낙관하기 보다는 실패를 견제한다면 전반적인 효율성을 향상시킬 수 있다.
  • 실패한 작업은 초기에 적극적으로 취소하도록 한다.
  • 팀의 결속에 대해 위험을 무릅쓸 필요가 없다면 굳이 그렇게 하지 않는다. 이미 편성된 팀을 찾고 이용한다.
  • 후속 관리자가 더딘 결속력이나 결속이 되지 않는 팀으로 인한 문제를 피할 수 있도록 하기 위해 (팀원들이 원한다면) 훌륭한 팀은 계속 유지시킨다.
  • (이미 준비되어 있고 새로운 작업을 할 의향이 있는) 결속된 팀을 프로젝트 산출물의 하나로 간주한다.
  • 프로젝트 초기에 잃어버린 한 시간은 프로젝트 마지막에 잃어버린 하루와 같은 손실이 된다.
하루를 잃는 데는 수없이 많은 방법이 존재하지만, 하루를 만회하는 데는 단 한가지 방법조차도 존재하지 않는다.

개발 프로세스 모델링과 시뮬레이션
  • 작업을 완료하는데 필요한 프로세스에 관한 자신의 직감을 모델링한다.
  • 동료들간 상호교류와 프로세스가 어떻게 작동하는지에 대한 사고를 개선하는데 그 모델을 사용한다.
  • 결과를 모의실험하기 위해 모델을 사용한다.
  • 실제 결과에 따라 모델을 조정한다.
병적인 정치학
  • 직업을 언제든지 담보로 할 의향이 있어야 한다.
  • 하지만 그렇게 하는 것이 병적인 정치 때문에 영향을 받지 않는다는 것을 보장해 주지는 않는다.
  • 병적인 정치 논리는 어디서든지 자랄 수 있는데, 심지어는 가장 건강한 조직에서조차 생길 수 있다.
  • 병적인 정치학의 특성을 정의하자면, 개인적인 권력과 영향력으로 인한 목표가 조직의 현실적인 목표보다 우위에 선다.
  • 이 말은 병적인 목표가 조직의 목표와 완전히 반대가 되더라도 일어날 수 있다는 뜻이다.
  • 이 병이 갖는 부작용 중 하나는 알맞은 인원으로 된 프로젝트 팀을 갖는 것조차 위험해진다는 것이다.
측정 (Metrics)
  • 모든 제품의 규모를 측정한다.
  • 단위 때문에 고민하지 말라. 객관적인 측정 방법을 만들기 전까지는 주관적인 단위를 사용한다.
  • 이용할 수 있는 모든 원시적인 요소(소프트웨어를 계량화할 수 있는 특징)를 활용해 통합 측정모델을 만든다.
  • 완료된 프로젝트에서 생산성에 관한 경향을 파악하기 위해 과거 프로젝트에서 데이터를 수집한다.
  • 통합 측정모델에 의해 나온 값이 과거 프로젝트의 공수와 최적의 상관관계를 나타낼 때까지 그 공식을 가지고 계속 작업을 한다.
  • 데이터베이스를 가지고 통합 측정모델이 예상한 공수를 트렌드 곡선으로 그린다.
  • 이제 추정할 새로운 프로젝트마다 통합 측정모델로 값을 계산하고, 그 값을 트렌드 곡선에서 예상 공수와 비교하는 데 사용한다.
  • 예상치에서 어느 정도의 허용오차를 적용할지를 나타내기 위해 생산성 트렌드 곡선에 오차의 범위를 사용한다.
프로세스와 프로세스 향상
  • 좋은 프로세스와 지속적으로 향상되는 프로세스는 모두 훌륭한 목표가 된다.
  • 이들은 또한 매우 당연한 목표이기도 하다. 훌륭한 개발자들은 그렇게 하라고 말을 하든 안하든 간에 여기에 초점을 맞춘다.
  • 공식적인 프로세스 향상 추진 계획은 시간과 돈이 든다. 그러한 프로세스 향상작업은 프로젝트 작업을 뒤쳐지게 할 것이다. 생산성 향상이 실현된다 하더라도 그 계획을 실행한 프로젝트가 프로세스 향상에 들인 시간을 상쇄하지는 못한다.
  • 프로젝트에서 향상 방법을 하나만이라도 제대로 선정한다면 본전 (그러한 변화에 투자한 시간과 비용)을 뽑을 수 있을 것이라고 생각한다.
  • 프로젝트가 그 기간동안 하나 이상의 향상 방법을 수용하기를 바라는 것은 무리다. 여러가지 기술을 한번에 향상시키려는 계획(Multi skill improvement programs 예를 들어, 전체 CMM 레벨을 증가시켜서 얻을 수 있는)은 그 계획을 실행하지 않았을 때보다 프로젝트를 더 지연시킨다.
  • 표준 프로세스는 사람들이 중요한 지름길로 갈 기회를 놓치게 할 위험성이 있다.
  • 특히 인원이 과다하게 투입된 프로젝트의 경우 모든 사람들에게 돌아갈 만큼 일(유용한 일이거나 그렇지 않은 일이라도)이 충분하지 않다면 문제가 발생하게 된다.
작업 방식 바꾸기
  • 전체 디버깅 시간을 상당량 줄이지 않고는 프로젝트가 평균 이상으로 능력을 충분히 발휘하도록 할 수 있는 방법은 없다.
  • 높은 성과를 보이는 프로젝트는 디버깅에 훨씬 적은 시간을 소모한다.
  • 높은 성과를 보이는 프로젝트는 설계에 훨씬 많은 시간을 투자한다.
사람들을 좋아하지 않고 제대로 돌봐 주지도 않는다면 어떠한 일이든 간에 그들에게 일을 하도록 만들 수 없다. 사람들을 변화시키기 위해서는 그들의 생각이 무엇에 근거하고, 왜 그런지를 이해(인정)해야 한다.

압력의 효과
  • 스트레스를 받는 사람들은 머리가 빨리 돌아가지 않는다.
  • 초과근무 시간 증가는 생산성 감소 기법이다.
  • 단기간에 가하는 압력과 초과근무는 사람들을 집중하게 만들고 일이 중요하다는 느낌을 심어주기 때문에 유용한 전술이 될 수 있지만, 압력을 장기간에 걸쳐 가하는 것은 언제나 실수하는 것이다.
  • 관리자가 압력을 가하는 이유는 그가 할 일이 없거나 아니면 (압력을 피하는 쪽의) 대안 실행에 엄두가 나지 않기 때문이다.
  • 끔찍한 생각: 압력과 초과근무 시간을 사용하는 실제 이유는 프로젝트가 실패하더라도 모든 사람들이 최선을 다한 것처럼 보이기 위해서일 것이다.
화가 난 관리자
  • 관리에서 화와 모욕은 전염된다. 상급 관리자가 직원들을 학대하면 그 밑에 있는 관리자들도 그와 같은 행동을 따라 한다 (학대 받은 아이들이 학대하는 부모가 되는 것과 비슷하다).
  • 관리 차원에서 모욕을 주는 일은 사람들이 자신의 능력에 좀 더 투자하도록 만드는 자극제 역할을 해야 한다. 그것은 당근과 채찍 두 가지 관리법 중 가장 자주 사용되는 '채찍'인 것이다. 하지만 모욕이 능력을 더 발휘하도록 만든다는 증거가 어디에 있는가?
  • 관리자가 직원들을 자극하기 위해 모욕을 주는 것은 직원이 무능하다기보다는 관리자가 무능하다는 표시다.
애매모호한 명세서
  • 명세서에 나타난 애매모호함은 시스템의 여러 이해당사자들 간에 해결되지 않은 마칠이 있음을 의미한다.
  • 입력과 출력에 관한 완전한 개수를 포함하고 있지 않은 명세서는 출발에서부터 실패한 것이다. 간단히 말해 명세서 작업을 시작하지도 않은 것이다.
  • 아무도 당신에게 명세서가 엉망이라는 것을 말해 주지 않는다. 사람들은 명세서를 탓하기보다 자신을 탓하는 경향이 있다.
마찰 (conflict) 
  • 개발 작업에 여러 이해 집단이 연관되어 있을 때는 언제나 서로 모순되는 관심사가 있기 마련이다.
  • 시스템을 구축하고 설치하는 분야는 특히나 마찰이 일어나기 쉬운 분야다.
  • 대부분의 시스템 개발 조직은 마찰 해결 기술을 가지고 있지 않다.
  • 마찰은 존중되어야 한다. 마찰이 비전문적인 행위를 나타내는 것은 아니다.
  • 모든 사람들의 승리 조건은 존중될 것이라고 미리 선언한다. 그리고 그러한 승리조건이 모든 면에서 명확하게 되도록 보장한다.
  • 협상은 어렵지만 중재는 쉽다.
  • 승리 조건이 상호 배타적이거나 부분적으로 배타적일 때 양자는 마찰을 해결하기 위해 중재 과정을 거치게 된다는 것을 미리 합의해 정한다.
  • 기억하라. 우리는 모두 같은 편이다. 다른 편이 있다면 그것은 문제 그 자체일 뿐이다.
촉매자의 역할
  • 촉매적인 성격이라는 것이 있다. 그런 사람은 팀이 형성되고, 결속되고, 건전하고, 생산적이 되도록 매개함으로써 프로젝트에 기여한다. 촉매자가 (주로 다른 많은 일을 하지만) 아무 일도 하지 않더라도 그들의 역할은 중요하고 가치 있다.
  • 중재는 촉매적인 역할에 있어서 특별한 경우다. 중재는 조금만 투자하면 배울 수 있는 것이다.
  • 시작을 위한 작은 의식인, "제가 중재해도 될까요?"는 마찰 해결에 있어서 중요한 첫걸음이다.
인간의 실수
  • 당신을 괴롭히는 것은 당신이 모르는 것이 아니다. 그것은 안다고 생각했지만 사실은 제대로 알고 있지 못한 것이다.
투입 인력의 수
  • 초기에 인원을 과다하게 투입하면 프로젝트 팀은 중요한 설계 활동을 (모든 사람들에게 할 일을 주기 위해서) 간단하게 해 버리는 경향이 있다.
  • 설계가 완성되기 전에 많은 사람들에게 작업을 나눠주면, 사람들 간의 인터페이스와 작업그룹 간의 인터페이스가 많아진다.
  • 이것은 상호의존성, 회의시간, 재작업, 초조감을 증가시킨다.
  • 이상적인 인력 투입을 위해서는 대부분의 프로젝트에 소규모 핵심 팀을 운영하게 하고, 프로세스 후반에 상당한 수의 사람들을 추가 투입한다. (늦게는 스케줄 상 마지막 6분의 1이 될 때에 투입한다).
  • 놀라운 발견: '공격적인' 스케줄에 매인 프로젝트는 좀 더 타당한 스케줄을 따랏을 때보다 프로젝트를 끝내는 데 더 오래 걸린다.
프로젝트의 사회학
  • 없어도 될 사람이 참석하지 않도록 회의는 소규모로 유지한다. 토론 주제는 반드시 공고해야 하는데, 이는 불참해도 안전하다는 것을 보장해 줄 수 있는 가장 손쉬운 방법이다.
  • 프로젝트에는 의식이 필요하다.
  • 소규모 회의, 무결함 등 프로젝트 목표와 이상에 집중하기 위해 의식을 사용한다.
  • 가학적인 화로부터 사람들을 보호하기 위한 조치를 취한다.
  • 기억할 것: 화 = 두려움. 아래 사람들을 학대하고 화를 내는 행위를 하는 관리자는 거의 대부분 자신들이 두렵기 때문에 그렇게 한다.
  • 관찰한 바: 두려움은 표현하지 않으려는 경향이 있기 때문에 사람들은 더 이상 화를 표출하지 못하는 것이다. 그러므로 만약 모든 사람들이 '화 = 두려움'이라는 것을 안다면, 화를 내는 것은 두려워하고 있다는 명백한 표시가 될 것이다(그렇다고 화를 내는 당사자의 문제가 해결되지는 않지만 나머지 사람들이 감당하기가 훨씬 수월해진다).
병적인 정치(재탕)
  • 아래로부터는 병적 증세를 해결하기 어렵다.
  • 그런 시도로 시간을 낭비하거나 자신의 위치를 위태롭게 하지 말라.
  • 가끔 유일하게 남아 있는 선택은 문제가 스스로 해결될 때까지 기다리거나, 일을 진행시킬 수 있는 때를 기다리는 것 뿐이다.
  • 기적이 일어날 수도 있다 (하지만 그것에 의지해서는 안된다).
비용 삭감
  • 비용 삭감은 실패에 대해 책임이 있는 사람들이 만들어 낸 공식이다.
  • 이것은 '번영하며 서로 돕는다'는 모든 조직의 일반적인 목표와는 반대다.
  • '비용 삭감'이라는 말을 들을 때마다 그 속에 담긴 참 뜻으로 그 말을 대체시킨다. '실패하고 있고 두려워하고 있다'.
근본적인 상식
  • 프로젝트는 목표치와 추정치 모두가 필요하다.
  • 그 둘은 서로 달라야 한다.
모두 옮겨 두고 보니 왜 타이핑 했나 싶다. 책을 보면 더 풍부한 내용을 볼텐데.