콘텐츠로 이동

2016

2016년도 지름 결산

작년에 2015년도 지름 결산 글을 쓴 적이 있습니다. 올해도 지름 결산을 해보려고 합니다.

임의 순서입니다.

  1. [Orion 8 inch Dobsonian Telescope][xt8]

    미국와서 벼르고 벼르던 돕소니안 망원경을 사서 뒷마당에서 성운, 성단을 훑고 있습니다. 생각만큼 어두운 하늘은 아니라 은하는 잘 보이진 않지만, 그래도 충분히 가치를 하는 중입니다.

  2. Costco Industrial Rack

    렌트를 옮기고 개러지에 적재할 선반용으로 구입했습니다. 무거운 무게가 말해 주듯, 아주 튼튼하고 지진에도 버텨낼 것 같은 모습입니다.

  3. Ryobi 18V Drill

  4. Fire Starter (Chimny)

  5. Skywalker 12ft Trampoline

    이사를 한 김에 넓은 뒷마당을 채우려고 구입하였습니다. 아이들이 정말 좋아하고, 다른 가정을 초대했을 때 아이들이 놀면서 시간을 보낼 수 있어서 아주 잘 구입한 것 같아요. 가격은 조금 비싸지만 ($249) 그만큼 가치는 하는 것 같네요.

  6. [Amazon Echo][alexa] + TP-Link Kasa

    보이스로 명령을 내리는 게 얼마나 유용할까 란 의구심으로 기기를 사용했으나, 실제로는 꽤 만족하며 사용중입니다. 일단 아이들이 궁금해 하는 것을 이민자인 제가 잘 모르는게 있는데 검색을 해도 되지만 간단하게 Alexa에게 물어봐도 되고, 기타 소소한 기능들과 IoT 기기를 연동하는 기능이 풍부해서 이것 저것 종종 사용하게 되네요.

  7. [Google Home][google-home]

    2016년 10월 Google I/O에서 구글 홈이 발표되었습니다. 자칭 구글빠라서 일단 아마존 에코와 비교해 보기 위해 주문하였습니다. 아마존 에코와 거의 기능상으로 동일하지만, 아직 IoT 와 연동은 부족합니다. Nest, Phillips Hue, Samsung Smartthings 정도만 지원이 되서 기존에 있던 TP-Link Smart plug를 사용하지 못하네요. 다만, Youtube Red, Google Assistant, Google Cast를 구글홈과 연동해서 쓸 수 있는 점은 큰 장점입니다.

  8. Canon PIXMA MX922 Wireless All-in-One Printer

    생각보다 큰 덩치에 놀라긴 했지만, 인쇄 품질도 좋고, ADF 까지 있어서 자동으로 여러장 스캔이 가능하니 정말 편합니다. Google Cloud Print도 지원하고, Apple Air Print도 지원해서 연결하고 Wifi router에 접속하면 곧장 사용할 수 있습니다. 가정에서 쓸 수 있는 꽤 괜찮은 선택지 인것 같네요.

  9. Venta LW-15

    한국에서 구입했던 벤타는 LW-44 모델이라 아이들 방에 사용하기엔 너무 컸습니다. 습도를 적당히 조절하기 위해 작은 녀석으로 하나 장만했습니다. 자세한 리뷰는 [Venta LW-44][venta] 를 참조하세요.

  10. Volkswagen e-Golf

    기존에 타던 Passat을 처분하고 리스 한 전기차, 폭스바겐 e-Golf입니다. 아주 괜찮은 특가로 나와서, 파삿을 팔고 넘어가도 손해가 없을 정도였거든요. 충전은 회사에서 제공하기에 전기 걱정없이 출퇴근을 편하게 할 수 있습니다. 캘리포니아에서는 전기차에 대해 카풀차선 이용을 허용하기에 출퇴근 시간을 상당히 줄일 수 있습니다. 이게 구매를 결정하게 된 가장 큰 요인이었네요.

  11. Lenovo Yoga 700

    Core M 시리즈 CPU는 별 문제가 아니나, 뭔가 적응이 안되는 키감은 도저히 사용할 수 없을 정도네요. 클릭 느낌이 들었는데 키는 입력이 안됩니다. 바닥을 꾹꾹 눌러주지 않으면 키가 인식이 안되서 오타가 너무 많이 나네요. 결국 다시 코스트코에 환불!

  12. Dell XPS 13 Skylake

    블랙프라이데이에 Ebay에서 저렴하게 작년에 출시된 제품이 올라와서 구매했네요. Kabylake 제품과 크게 달라진게 없어서 구매했습니다. QHD + Touchscreen 에 8GB RAM, 256GB PCIe SSD 라서 사양은 충분합니다. 다만 베젤을 최소한으로 줄이기 위해 카메라가 아래 왼쪽에 박혀있는 건 도저히 용서가 안됩니다. 화상채팅을 할 생각이 있다면 웹캠을 따로 구입하는 걸 추천합니다.

  13. Firepit

    집안에 있는 벽난로를 사용할 수 없어서 밖에서나마 즐기려고 홈디포에서 구입했습니다. 장작 피우고 고구마 구워먹거나 마시멜로 구워먹기 아주 좋아요! 싱글하우스의 또 하나의 장점이네요.

Upgrade to Hakyll 4.8

[Hakyll][] 이 4.8 버전으로 업그레이드 되면서 달라진 점이 하나 있는데, Metadata field가 YAML 형식으로 바뀌었습니다. 이로 인해, 기존의 Data.Map 타입에서 YAML.Object 가 되면서 기존의 Metadata를 이용한 함수를 대부분 고쳐야 했습니다.

예를 들면 match 함수에서 public 인 것만을 추려내서 html을 만드는 데, 이때 쓰이는 함수가 Hakyll 4.7에서는 아래와 같았습니다.

metadataFieldIs :: String -> String -> Metadata -> Bool
metadataFieldIs key value metadata = case M.lookup key metadata of
    Just v  -> value == v
    Nothing -> False

Data.Map 이기에 M.lookup 함수로 찾아서 public인지 아닌지 검사합니다. 하지만, YAML.Object로 변경되었기 때문에, Aeson 라이브러리를 이용하거나 Data.HashMap 을 이용해야 합니다.

다행스럽게도 Hakyll-4.8 에서 비슷한 역할을 하는 함수를 이미 만들어서 제공하고 있습니다 (Jasper 짱!) 바로 lookupString 인데요. Hakyll.Core.Metadata 에 정의되어 있습니다.

그래서 아래와 같이 코드를 간편하게 변경할 수 있었네요.

metadataFieldIs key value metadata =
    case lookupString key metadata of
        Just v  -> value == v
        Nothing -> False

다른 하나는, 이건 YAML에 관련된 이야기 인데, YAML은 on, yes 등의 값을 무조건 Bool로 인식해서 true로 변경하더군요. 그래서 disqus를 표시하는 metadata field가 on 에서 true로 바뀌는 바람에 disqus가 사라져 버려서 찾느라 고생좀 했습니다.

Getting Rid of Ground Bees

지난 주 Lawn Mower로 뒷마당에 무성한 잡초를 깎았습니다. 이 건조한 환경에서도 얼마나 잡초가 잘 자라는지, 이주 만에 엄청 자랐더군요.

잡초를 깎는 데, 마당 한 가운데 꽤 큰 구멍이 보입니다.

마치 다람쥐가 굴을 파놓은 것 같은 모양입니다. '집 근처에 두더쥐나 다람쥐가 있나..' 하고 그냥 지나쳤다가, 잡초를 다 깎은 후 아이들과 놀다가 다시 한번 보았네요.

삽을 들고 구멍을 메울려고 구멍 주위를 파헤치는 순간, 주변에 벌이 몇마리가 나타납니다. '아차!' 싶어서 곧장 두 아이에게 집으로 들어가라고 다그치고 같이 피신을 합니다. 달려오는 길에 벌이 둘째의 다리를 물어버렸네요. 다행히 쏘인 건 아니고 물린 것 같네요.

땅벌을 없애기 위해 이리 저리 찾아보니 몇가지 방법이 있네요.

  1. Home Depot에서 벌 제거용 스프레이를 산다.
  2. 밤에 구멍에 주방세제를 붓고 물을 뿌린다.
  3. 구멍을 Tarp 나 다른 것으로 막아서 굶겨 죽인다.

일단 밤 사이 긴급 조치로 Tarp로 대충 덮어뒀는데, 이게 오히려 악영향을 끼쳐서 벌이 쉴새없이 날아다니게 되어버렸습니다. 결국, 완전 무장을 하고 스프레이로 벌집을 제거하기로 합니다.

Home Depot에 가면 Spectracide 제품 중 벌을 잡는 스프레이를 살 수 있어요. 이게 Foam으로 분사되고 8미터 정도 멀리서도 분사할 수 있어서 꽤 괜찮은 제품입니다. 이걸 사고, 좀 불안한 마음에 방충망과 벽돌도 좀 사기로 합니다.

완전 무장

집에서 바이크 헬멧, 스노우보드 상하의, 글러브로 완벽 무장을 하니 땀이 비오듯 쏟아집니다.

스크린 비닐을 다 뜯고 벽돌도 근처로 옮겨서 만반의 준비를 갖춘 뒤, 잔디깎기 기계가 반쯤 파먹어버린 타프를 걷어내고 스프레이를 분사합니다.

Spectracide

멀리서 길게 죽죽 뻗어나가며 벌집 구멍에 하얗게 막을 형성하네요. 큰 스프레이 통이라 넉넉히 쏴야지.. 하면서 구멍 주변에 뿌리는데 갑자기 압이 약해집니다. -_- Foam으로 나가서 오래 나갈 줄 알았는데, 너무 금방 떨어지네요. 구입할 때 바로 옆 칸에 2개를 한 세트로 팔고 있었는데, 이유가 있었네요.

급하게 대충 구멍 안에 쏘고 급 마무리 합니다. 스크린으로 덮고 벽돌과 페인트 통으로 꾹꾹 눌러서 벌이 못 날아다니게 막아둡니다.

Home Depot에서 사온 호스 정리하는 Reel을 이용해 마당에 널부러진 호스를 감는데, 이미 호스가 휠대로 휘어서 대책없이 꼬이네요. 싼게 비지떡인가 봅니다.

Garden Hose Reel

쭈그려 앉아서 한참을 꼬인 호스를 풀고 있으니, 땀으로 정신이 혼미해지네요. 숨도 막히고, 어쩔 수 없이 대충 감아재끼고, 이따구 싸구려 호스를 판매한 Home Depot에 가서 환불하기로 맘 먹습니다.

아직 완전한 밤이 되질 않아서 밖에서 활동하던 벌이 집에 못 들어가고 방충망 앞에서 맴도네요. 밤에 활동이 아예 없을 때 작업할 걸 그랬나.. 하는 생각도 듭니다. 한방에 다 죽일걸..

Rent a Single House

어느덧 [아파트 갱신 글][renew-apartment] 을 작성한 지 일년이 되어 두번째 갱신 계약서가 날아왔네요. 작년만큼 10% 상승은 아니였지만 금액으로는 거의 비슷한 금액이 올랐습니다. 결국 3천달러를 주고 아파트에 사느냐 아니면 다른 곳을 찾느냐를 결정해야 하는 순간이 되었네요.

지내고 있는 엘란 아파트는 회사와 가깝기도 하고 주변에 미국으로 갓 넘어온 한국 가족이 많이 있기도 하고, 지내기 괜찮았던 것 같습니다. 다만, 가격이 무척 높아진 것, 학교가 형편없이 안좋은 것 (조사해 본 바로는 꽤...)이 꽤 큰 비중을 차지하네요.

아이가 곧 학교를 입학할 나이가 되어서 이참에 옮기기로 결정하고 이리저리 집을 알아보았습니다. 아파트를 제외하고 타운하우스나, 듀플렉스, 싱글하우스를 찾아보니 높아진 렌트비가 실감이 나네요. 적당한 학군을 찾아보니 듀플렉스조차 3천불이 넘네요. 조금 더 눈을 높이면 싱글하우스가 3천불 후반까지 올라가고, 최상의 학군은 5천불도 보통이라 여겨질 정도입니다.

제가 그리 뛰어난 사람은 아니라 눈 높이를 많이 낮춰야 했네요. 3주동안 열심히 쫓아다니고 지원서를 넣고 떨어지고를 반복하다 듀플렉스가 하나 되었습니다. 계약금을 송금하기 전, 지인 집 근처에 저렴한 집 하나가 나왔는데 꽤 괜찮은 가격대로 나왔더라구요. 그래서 바로 전화하고, 찾아가서 사정하고, 적극적인 의사 표시를 한 덕분에 싱글하우스로 집을 구할 수 있었습니다.

이번 렌트를 구하면서 보니, 신용도와 급여가 가장 중요한 것으로 보이지만, 그 기준을 만족하는 지원자가 참 많았습니다. 그 중에서 되려면 무엇보다도 적극적인 의사 표시가 가장 중요한 것 같습니다. 이 집에 꼭 살고싶다는 의사표현으로 편지가 될 수도 있고, 지원서에 Security Deposit을 같이 내는 방법도 있고 몇가지 방법이 있을 수 있어요. 전 매물이 올라오자마자 얼마 안되서 글을 발견하고, 바로 전화를 걸고 thank you email을 보내면서 제 급한 사정을 같이 이야기 했었네요. 그 이메일 덕분에 에이전트가 그 다음날 집을 보여줄 생각이 들었다고 하네요. 그리고 그 날 제가 바로 개인수표로 Security Deposit을 같이 주고, 그날 크레딧 리포트와 급여자료등을 서면으로 같이 들고가서 줘서 일이 일사천리로 진행될 수 있었던 것 같아요.

비록 생각했던 금액의 상한선으로 구하긴 했지만 주변 시세보다 400~500불 저렴하게 잘 구한 것 같네요. 아이들도 뒷마당에서 놀면서 아주 좋아할 것 같습니다.

한 번 싱글하우스를 가면 아파트로 다시 못 돌아간다던데, 이대로 지내다가 집을 살 수 있는 기회가 오면 좋겠습니다. :)

Hakyll Route for Metadata date Field

블로그 URL을 보면 이전과는 좀 달라졌습니다. 예전엔 url이 blog/YYYY-MM-DD-post.html 방식이었다면, 새로운 URL은 blog/YYYY/MM/DD/post.html 형태로 바뀌었습니다.

변경을 한 이유는, 블로그 글이라면 제목과 연관된 URL이 유지되어야 하는데 그 앞에 항상 년,월,일 이 디렉토리 형태도 아니고 같은 묶음으로 다니는게 조금은 이치에 맞지 않는 것 같았기 때문입니다. 그래서 아카이브 형태로 년,월,일 을 디렉토리로 구분하였습니다. 글을 자주 쓰는 게 아니니 년,월,일 보다 2016, 2015 해서 년만 넣어도 충분하겠지만 일단은 이렇게 가는 걸로 하죠. ㅎㅎ

기존에 블로그에 글을 쓸 때에는 blog/ 디렉토리 밑에 URL과 동일했던 마크다운 파일을 두고 글을 썼습니다. 지금이야 글이 꼴랑 20개 남짓이라 문제가 없지만, 나중에,, 아마 한 5년은 걸리겠지만, 나중에 100개 이상이 되었을 때 한 폴더에 모든 글을 다 보관한다는 건 조금은 번거로운 일이 될 것 같아서 방식을 바꾸기로 했습니다.

새로운 방식은, blog/ 밑에 어느 폴더에 두더라도 blog/YYYY/MM/DD/post.html 형태로 바꾸도록 변경했습니다. Hakyll에서는 URL을 결정하는 Rule을 Route라는 이름으로 만들었습니다. 이 Route에 원하는 규칙을 넣으면 그 규칙대로 대상 URL이 결정됩니다.

아래의 코드는 위의 blog/ 를 위해 만든 규칙입니다.

-- | Route based on metadata field 'date' -------------------------------------
dateRoute :: FilePath -> Routes
dateRoute prefix = metadataRoute (f prefix)
  where
    f p md = customRoute $ pullDateToFilePath p md

-- | Add prefix then compose YYYY/MM/DD/post.html format ----------------------
pullDateToFilePath :: FilePath -> Metadata -> Identifier -> FilePath
pullDateToFilePath p m i = p </> (convertDateToFilePath m i)
  where
    convertDateToFilePath md id' = convertLocalTimetoISO (md M.! "date") (M.lookup "slug" md) $ toFilePath id'
    -- convertLocalTimetoISO :: String -> Maybe String -> FilePath -> FilePath
    convertLocalTimetoISO d (Just s) _ = toISO d </> s <.> ".html"
    convertLocalTimetoISO d Nothing fp = toISO d </> chopDayFromFileName fp
    chopDayFromFileName fp' = replaceAll "[0-9]{4}-[0-9]{2}-[0-9]{2}-" (const "") $ takeFileName fp'
    toISO dateString = formatTime defaultTimeLocale "%Y/%m/%d" $ readTimeFromMetadataString dateString

-- TODO: Make more format
readTimeFromMetadataString :: String -> UTCTime
readTimeFromMetadataString dateString = parseTimeOrError False defaultTimeLocale "%B %e, %Y" dateString

일단 post 내의 메타데이터 date 를 이용하기 위해 metadataRoute 가 사용됩니다. 이 metadataRoute 는 함수 인자를 받는데 Metadata -> Route, 즉 Metadata를 입력으로 받고 결과가 Route인 함수를 인자로 받습니다.

Metadata를 이용해 YYYY/MM/DD 형식으로 변경해야 하므로 customRoute를 사용해서 원하는 형태로 바꿔주도록 합니다. customRoutemetadataRoute와 비슷하게 함수 하나를 인자로 받습니다. 이 함수는 Identifier -> FilePath 타입으로 Identifier를 입력으로 받고 최종 URL인 FilePath를 결과로 내는 함수입니다.

f p md = customRoute $ pullDateToFilePath p md

Higher Order Function을 이용해서 pullDateToFilePath 함수를 Identifier -> FilePath 처럼 인식되게 했습니다. 실제 pullDateToFilePath의 타입은 pullDateToFilePath :: FilePath -> Metadata -> Identifier -> FilePath 이죠. 즉, FilePath, Metadata, Identifier를 입력 받아서 FilePath를 리턴하는 함수입니다.

MetadataData.Map 타입이라 원하는 필드, date, slug 를 검색할 수 있습니다. 이를 검색해서 date는 YYYY/MM/DD 형태로 바꿔주도록 하고 slug가 있다면 사용하고 없다면 파일 이름을 사용하도록 합니다.

그래서 slug를 검색할 때는 M.lookup "slug" md 로 해서 Maybe Monad로 결과를 받고 Just 또는 Nothing으로 처리합니다.

    convertDateToFilePath md id' = convertLocalTimetoISO (md M.! "date") (M.lookup "slug" md) $ toFilePath id'
    -- convertLocalTimetoISO :: String -> Maybe String -> FilePath -> FilePath
    convertLocalTimetoISO d (Just s) _ = toISO d </> s <.> ".html"
    convertLocalTimetoISO d Nothing fp = toISO d </> chopDayFromFileName fp

이 방식을, sky/log/ 에도 적용해서 그 부분도 YYYY/MM/DD 형식으로 저장되도록 했습니다.

이번 수정을 하면서 Haskell의 깔끔한 구현 방식이 논리적으로 생각하는 흐름에 맞게 잘 되어있구나, 라는 생각이 다시 한번 들었습니다. 생각의 흐름 그대로 top down이나 bottom up 구현을 해 나갈 수 있어서 큰 무리 없이 수정이 가능했습니다.

영주권

2년하고 한달, 그리고 9일이 걸렸습니다. 2014년 1월 14일 미국땅을 밟고 이 시간이 지나서 영주권이 승인되었네요. 2년이란 시간이 벌써 흘렀는지도 실감이 나지 않을 정도로 빠르게 지나간 것 같네요. 영주권을 받지 못해서 오랫동안 고생하시는 많은 분의 이야기를 인터넷에서 접하고 귀로 전해 들은터라 내심 걱정이 많이 되었습니다. 영주권을 위해서 다른 회사로 이직할 기회도 거절하고 남아있었는데, 결국 시간이 지나니 나오네요.

중간에 문제가 없었다면 한 3개월 더 빨리 나올 수 있었겠지만, 이제 그 모든 게 지나간 일이 되었네요.

다른 사람들은 영주권 나왔을 때 감흥에 젖는다고 하던데, 별다른 느낌이 들지 않았습니다. 카드를 보고 "이게 영주권이구나.." 하는 것 말고는 별로 모르겠네요. 미국을 나갔다가 다시 오면 공항에서 대기줄이 달라서 느낌이 다르려나요?

아무튼, 무탈히 진행되어 다행입니다. 이제 신분 문제도 해결되었으니, 자기계발에 힘을 써서 몸값을 올리는 데 주력해야 겠네요.

그동안 이리 저리 걱정해 주신 모든 분에게 감사 드립니다.

GTD: Omnigroup의 Omnifocus 2

지금까지 일과 기타 해야만 하는 일을 어떻게 관리할 것인지 많이 고민해보고 이것 저것 써 보았습니다.

예전에 잠깐 Microsoft Project를 사용했었는데요. 정말 기가 질릴정도로 다양한 기능에 압도되어 아무것도 하지 못하는 일이 종종 벌어지곤 했습니다. 너무 세세하게 관리를 해야만 흐트러짐없이 정돈이 되기에 오히려 하나 삐긋하면 포기해버리기 일쑤였습니다.

그 전에는 Trac, Redmine 등 온라인 툴을 썼었네요. 다만 이 도구는 Source code repository 와 연동되어야만 강력한 힘을 발휘하기에 특정 프로젝트에 한정되어 쓸 수 밖에 없는 점이 문제였습니다. 마일스톤을 정한다거나 이슈에 대한 추적은 매우 좋은 기능이었다고 생각합니다.

이 Trac의 상용버전 쯤 되는 것이 JIRA인데 호주의 Atlassian 회사에서 만들고 있는 도구입니다. 개인서버에 Starter Edition을 설치해서 사용하곤 했었는데, 일단 Java 기반이라 성능이 느린 제 서버에서는 정말 느렸었고, Microsoft Project 만큼이나 방대한 점, 프로젝트별로만 관리해야 되는 점 등이 1인 사용을 위한 도구로는 부적합했습니다.

Omnifocus 2

작년 12월 중순부터 사용하기 시작한 도구가 있습니다. Omnifocus 2라는 도구인데요. David Allen의 Get Things Done (이하 GTD) 개념을 도입한 소프트웨어 도구입니다. GTD는 다시 말하면 조금 복잡한 Todo list 라 할수 있는데요. 여기에 책임 영역이나 컨텍스트, Due date, Defer 같은 개념을 도입해서, 너무 간단하지는 않지만 MS Project같이 Overkill 은 되지 않는 한도내에서 적절한 지점을 찾은 것 같습니다.

그 전에 사용하던 Wunderlist는 공유되서 하나의 프로젝트를 여러명이서 관리할 수 있는 점은 매우 좋았으나 세부적인 설정이 거의 없다시피 해서 아쉬웠습니다. Omnifocus는 공유는 없지만, 매주 Review를 하는 부분이라던지 Forecast로 앞으로 할 일에 대한 전체 요약을 할수 있다는 것과 Focus 모드로 해야할 부분 하나에 집중하게 한다는 점이 강점입니다.

트라이얼로 사용해 보다가 새해 새 출발 기념으로 구매 후 본격적으로 사용하려고 Android용 3rd party app인 Focus GTD 도 구매했네요. 지금까지 2주간의 경험은 만족스러웠습니다. 구매를 했으니 조금 더 사용해보고 평가를 내려볼게요.

아참, 모두 새해 복 많이 받으세요~