오늘 아침에는 서준이와 치과에 다녀왔다. 늘 그렇듯, 아이와 병원에 가는 것은 힘든 일이다. 예전에도 눈병이 났을 때에, 의사 선생님이 무지막지하게 눈알을 뒤집는데, 피가 주륵주륵 나는 것이 차마 볼 수가 없었다. 그냥 짠하고 눈물이 날 것만 같았다. 오늘은 앞니 두 개가 신경이 죽은 것 같다는 진단을 받았고, 그대로 두면 다음 치아에도 영향을 줄 수 있어 할 수 없이 치료를 하게 되었다. 결정을 하면서도 이게 잘 하는 일인지 쉽게 판단할 수 없었다. 신경치료라니. 신경이 죽으면 이빨이 검게 변한다고. 어쩌면 그냥 두어도 다음 치아가 날 때까지 버틸 수도 있지 않을까. 물어보니 다음 치아는 초등학교 들어갈 때 쯤 난다고 한다. 그렇다면 그 때까지 완벽하게 관리를 해야 하는데, 또 물어보니 양치질만으로 문제가 안 생긴다는 보장이 없다고.. 염증이라는 것이 몸의 전반적인 상태와 관련이 있으니.
일단 엑스레이를 찍었고, 치료할 때에는 마취를 한다. (아이에게 엑스레이와 마취가 어떤 영향이 있을지도 모르는 답답한 부모들이다 ㅠㅠ). 좀 진정을 한 후, 문제의 이빨의 앞면에 구멍을 낸다. 그런 다음 그 구멍을 통해 치아 속의 위부분까지 긁어 올라간다. 나중에 보면 치아가 겉 표면만 남고 안에는 텅 빈 모습이 된다. 그런 다음 내부를 채운다. 채우는 물질이 무엇인지는 잘 모르겠다. 서준이가 아파하면서 움직이니까, 그물 같은 담요로 몸을 덮고 잠궈버린다. 이런...
암튼 힘든 아침이었다. 그래도 수술 시간이 그리 길지 않아 다행이라고 해야 하나. 사실 예전에 왔을 때에도 치료를 해야 한다고 의사선생님이 말씀하셨는데, 좀 과잉진료인 것 같아 하지 않았었다. 오늘은 집사람이 왜 그냥 한다 했을까. 암튼 조금은 애매한 판단이었다고 생각은 드는데, 그래도 하고 나니 말끔한 앞니가 되어서 보기에는 좋긴 하다.
2012-10-29
2012-10-26
2012-10-25
angular form validation 좋은 방법 없나?
제대로 하려면 일관된 방법이 있을 것 같기는 한데, 아직 어떻게 해야 할지 아이디어가 안잡히다보니 일단 이정도로만 처리하자. 더 좋은 방법이 있으면 누가 좀 알려주세요.
브라우저는 required, pattern 과 같은 것으로 기본적인 폼 validation 처리를 할 수 있다.
input이 이 조건이 충족되지 않으면 submit을 하지 않는다.
angular는 여기에 더해서 ng-minlength, ng-maxlength, ng-pattern 과 같은 것들을 제공한다. 그러나 문제는 form submit을 막아주지는 않는다. form submit을 못하게 하려면 어떻게 하나?
action속성을 제거하고 ng-submit을 사용하는 방법이 있다.
하지만 action 속성을 줄 수 없으니 갑갑하다.
또 하나의 방법은 submit 타입의 버튼을 없애고 button이나 anchor로 바꾸는 것을 생각해 볼 수 있다. ng-click handler에서 submit하면 된다. 이러면 action 속성을 줄 수 있다.
보너스로 아래와 같이 메시지로 피드백을 줄 수도 있겠다.
브라우저는 required, pattern 과 같은 것으로 기본적인 폼 validation 처리를 할 수 있다.
input이 이 조건이 충족되지 않으면 submit을 하지 않는다.
angular는 여기에 더해서 ng-minlength, ng-maxlength, ng-pattern 과 같은 것들을 제공한다. 그러나 문제는 form submit을 막아주지는 않는다. form submit을 못하게 하려면 어떻게 하나?
action속성을 제거하고 ng-submit을 사용하는 방법이 있다.
$scope.mainFormSubmit = function() {
if (!$scope.mainForm.$valid) {
$log.log("form is invalid");
} else {
$log.log("form is ok");
// set action and submit using jQuery ?
}
};
하지만 action 속성을 줄 수 없으니 갑갑하다.
또 하나의 방법은 submit 타입의 버튼을 없애고 button이나 anchor로 바꾸는 것을 생각해 볼 수 있다. ng-click handler에서 submit하면 된다. 이러면 action 속성을 줄 수 있다.
보너스로 아래와 같이 메시지로 피드백을 줄 수도 있겠다.
.alert.alert-error(ng-show="!mainForm.$valid") 입력값이 올바르지 않습니다.
2012-10-24
gpt partition
외장하드 하나를 집 컴퓨터에서 포맷을 한 다음 집사람 회사 컴퓨터에 꽂았더니 디스크가 보이지 않더란다. 디스크 관리자에서 gpt partition으로 뜨면서 포맷도 할 수가 없네.
다음 순서로 작업한다.
다음 순서로 작업한다.
- 커맨드라인에서 diskpart 실행
- list disk
- select disk x (x is number)
- clean
2012-10-22
2012-10-12
owncloud를 설치해봤다.
쉽게 설치된다. 패키지를 받아서 (php로 작성되어 있다) /var/www 밑에 풀면 된다.
쉽게 설치된다. 패키지를 받아서 (php로 작성되어 있다) /var/www 밑에 풀면 된다.
- 몇가지 디렉토리의 소유를 www-data:www-data 로 바꾸고.
- .htaccess를 사용하므로 000-default에서 AllowOverride 를 All로 바꾸고
- a2enmod rewrite, a2enmod headers
- service apache2 restart 하면 끝.
전용 클라이언트도 제공하고 좋아 보이더라. finder에서 접속하라고 WEBDAV 연결도 제공한다. 킹왕짱이다. 웹으로 연결하려면 http://server/owncloud 로 연결하면 되고. UI도 깔끔하더라.
그런데 이 새끼 이거.
파일을 올릴 수가 없네. 안되네. webdav로 복사해도 느려 터져서 되는지 안되는지도 모르겠고, 전용 클라이언트가 지정한 폴더에 파일을 넣어도 싱크하겠다는 반응이 없어. 웹브라우저로 올리라고? 그렇게는 못하지.
머... 찾아보면 우회하는 방법도 있겠지만... 내가 그리 한가하지 않은 관계로 오늘은 여기까지.
2012-10-10
2012-09-26
OOM killer 라는게 있다는건 처음 알았네.
http://sylphong.egloos.com/523835
며칠동안 이유없이 tomcat이 죽더니... dmesg로 확인해 볼 것. 혹은 OOM killer 로 더 알아볼 것.
http://sylphong.egloos.com/523835
며칠동안 이유없이 tomcat이 죽더니... dmesg로 확인해 볼 것. 혹은 OOM killer 로 더 알아볼 것.
2012-09-25
Spring MVC Controller 의 REST scaffold
spring roo 가 제공하는 것을 약간 수정하여 나만의 scaffold로...
* roo는 update 경로가 좀 다르고
* list에서 spring data의 Pageable을 사용함.
http://java.dzone.com/articles/restful-standard-resolved 도 참고하자.
* roo는 update 경로가 좀 다르고
* list에서 spring data의 Pageable을 사용함.
http://java.dzone.com/articles/restful-standard-resolved 도 참고하자.
@RequestMapping
public String list(@PageableDefaults(pageNumber = 0, value = Config.PAGE_SIZE) Pageable pageable, Model model) {
}
@RequestMapping(method = RequestMethod.POST)
public String create(@Valid MyObj obj, BindingResult bindingResult, Model model, HttpServletRequest httpServletRequest) {
}
@RequestMapping(params = "form")
public String createForm(Model model) {
}
@RequestMapping(value = "/{obj}", method = RequestMethod.PUT)
public String update(@Valid @ModelAttribute("obj") MyObj obj, BindingResult bindingResult, Model model, HttpServletRequest httpServletRequest) {
}
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public View remove(@PathVariable Long id) {
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ModelAndView show(@PathVariable Long id, Model model) throws Exception {
}
2012-09-22
roo의 service는 aggregate repository 같다. domainTypes에 entity만 지정해주면 그에 해당하는 repository들을 모두 엮어 준다. 그렇다면 하나의 entity가 여러 service에 지정될 수도 있다. 하지만 이건 좋지 않은 것 같다. 서로 역할이 달라야 할 service들이 하나의 entity에 대한 operation들을 중복해서 가지게 되니까. 각 service가 처리하는 entity들은 관련 영역별로 구분하여 모아주는 것이 좋지 않을까. 물론 service라는 것이 지정된 entity만 처리할 수는 없을 것이다. 그럴 때는 domainTypes에 해당 entity를 지정하는 것보다는 그 entity의 repository를 DI 받도록 하자.
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
음... 부팅안되는구나. 미안. ㅋ
$ 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
2012-09-07
jade4j
java에서 jade를 쓰고 싶어서 scalate를 쓰게 되었는데, jade4j로 갈아 타야겠다. 복잡한 페이지는 컴파일하는 시간도 오래 걸리고. 메모리는 왜 일케 많이 잡아 먹는거야. app reload하면 2~400메가씩 점유량이 올라가니 tomcat메모리를 max 2G 줘도 몇번 코드 수정하고 나면 빌빌댄다.
--
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
반면 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를 분리할 필요도 없다.
여기서 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 !
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 !
피드 구독하기:
글 (Atom)