콘텐츠로 이동

Log

하드웨어 디자인 코드리뷰

소프트웨어 분야는 하루가 다르게 새로운 기술이 쏟아져 나옵니다. 특히 웹 관련 기술은 최근에 트렌드가 정신없이 계속 바뀌고 있죠. 오죽하면 자바스크립트 기술 변화에 대한 유머까지 등장했겠어요.

이런 발빠른 변화를 쫓아가는 게 정말 벅찰 듯 합니다. 그런데 하드웨어 분야는 기술은 계속 바뀌어 가는데 개발 플로우는 십수년 째 전혀 바뀌지 않고 있어요. 개발 언어인 Verilog HDL 언어도 구닥다리 1995 버전을 쓰는 경우가 태반이고, 실제 칩 디자인에 SystemVerilog 2012를 사용하는 걸 본 적이 없네요. 검증은 대부분 SystemVerilog로 넘어가긴 했지만, 아직 설계는 여전히 Vim으로 한땀 한땀 정성들여 Verilog 포맷으로 코딩합니다. 수백개가 넘는 port를 연결하는 걸 보고 있으면 마치 수공예를 보는 것 같기도 하고, 어셈블리 코딩을 하는 것과 비슷한 느낌을 받기도 합니다.

사실 하드웨어는 한번 버그가 발생하면 수정하는 데 비용이 상당히 많이 들기에 항상 조심스러운 접근을 할 수 밖에 없다는 게 이해가 안되는 것은 아닌데, 그 정도가 심해도 너무 심하다는 생각이 듭니다.

Version Control System

이전 회사에 근무할 때에는 소스 코드 관리를 Clearcase라고 상용 툴을 썼는데, 거의 SVN과 유사한 시스템이었습니다. SVN만 되어도 사실 감사할 따름인데, 이 CC를 그냥 branch도 없고 tag도 없고 그냥 fetch, commit만 하는 수준으로 사용하고 있었어요. 거의 백업을 위해서 쓰는 정도였죠.

게다가 IP 디자인은 Clearcase도 아니고 초창기 파일 기반 버전 관리 도구인 CVS를 사용하고 있었습니다. CVS를 보았던 그때의 충격과 공포는 아직도 생각 나네요.

옮긴 회사는 더 충격적이게도 CVS에 GUI를 입힌 것 같은 도구를 사용합니다. 태그와 브랜치 기능이 있긴 한데 사용하기 까다롭고 한눈에 들어오지 않아서, 주변에서 브랜치를 쓰는 걸 본 적이 없네요. 파일 별로 버전관리가 따로 되다보니 하나의 IP가 여러 프로젝트에 쓰일 경우 점점 서로 뒤엉켜가는 걸 보게 됩니다.

Code Review

상황이 이런 지경인데, RTL (Register Transfer Level) 코드를 기술하고 소스코드 저장소에 업데이트 할 때 멤버라면 아무나 올릴 수 있습니다. 브랜치도 아니고, main에 올릴 수 있게되서, 하나의 잘못된 커밋이 전체 테스트를 fail 하게 되는 경우도 가끔 봅니다.

이런 일련의 경험을 하면서, '왜 하드웨어 디자인은 소프트웨어의 기법을 적용하지 않을까?' 하는 의구심이 계속 듭니다.

소프트웨어는 일찌감치 코드 리뷰에 대해 많은 고민을 해 왔습니다. 심지어 CVS 를 사용할 때에도 maintainer가 patch를 받아서 CVS에 업데이트 하는 것이 일반적이었고, 그래서 코드 리뷰는 자연스럽게 usenet이나 email 을 통해 이뤄지곤 했습니다.

그것조차 비효율 적이라 코드리뷰를 편하게 하기위한 시스템이 등장했지요. [Gerrit][ext:gerrit]은 구글이 코드리뷰를 하고자 Git 기반으로 만들어진 코드리뷰 도구이고, Github의 Pull Request는 email로 주고 받던 패치를 시스템상에서 간편하게 적용할 수있게 만든 도구입니다.

이 두 시스템 모두 main 저장소에 업데이트 할 수 있는 사람은 몇 안되고 나머지 사람은 각자의 branch나 저장소에서 작업 후 메인에 반영하기 위해 코드를 리뷰해야만 합니다. 이로 인해 약간의 지연이 발생하긴 하지만, 결과적으로 깔끔한 코드가 유지될 수 있습니다. 급한 경우엔 Gerrit은 main에도 곧장 업데이트 할 수 있도록 하고 있구요.

그러나 하드웨어는 이런 과정이 거의 없다고 봐도 무방합니다. 저장소에서 이러한 기능을 지원하지도 않을 뿐더러, 코드 리뷰를 한다고 하면 (리뷰하는 일도 거의 드물지만) 회의실에 모여서 소스코드 창을 띄우고 한줄 한줄 보는게 보통입니다. 시간을 가지고 코드를 깊게 볼 기회가 거의 없다고 봐도 되죠.

How to Improve?

일단은 코드리뷰가 가능하도록 저장소와 코드 리뷰 도구를 재정비하는 게 필요한 것 같아요. 지금은 웍스테이션 안에서만 코딩이 가능하다보니, JIRA와도 연동이 되지 않는게 보통입니다. 즉, 이슈와 실제 디자인 수정을 연결할 방법이 거의 없다고 봐도 되죠. (로그도 파일별로 남다보니..)

가장 우선은 Git based 저장소로 바꾸고 gerrit이나 pull-request가 가능한 GitLab이라도 써야 할 것 같아요. Subversion도 나쁘지 않은 선택이나, branch를 빈번하게 사용하고 코드 리뷰 요청을 넣는 flow에서는 조금 비효율적이라 git이나 mercurial이 더 나은 선택인 것 같아요.

여기에 더해서 Continuous Integration 을 이용해 바로 small set regression test를 돌릴 수 있게 설정해 둔다면 더욱 좋겠죠. (라이센스 비용은 좀 나가겠네요) pull request 전에 이 small regression을 통과하고 (아니면 적어도 compile과 elab까지만이라도) 그 후에 merge되는 게 정말 중요한 부분인 것 같습니다.

외부에서 받는 IP 같은 경우는 코드를 수정할 일이 거의 없다보니, IP는 release에 두던지 하고 configuration만 저장소에 두어서 리뷰를 할 수 있게 해야 합니다. 파라미터 세팅을 잘못 해서 빈번하게 실수가 발생하는 것을 봐서 (NIC CDAS scheme이라던지, outstanding capability라던지) 세팅 리뷰는 반드시 필요합니다.

Power Outage

Winter Storm이 온다고 해서 타호에서 3박4일 일정을 다 채우지 않고 전날 저녁에 길을 나섰습니다. 타호 가는 길에 눈으로 인해 4시간 반 걸릴 거리를 7시간을 넘겨 겨우 도착해서 가는 길도 그렇게 고생하고 싶지 않았습니다. 오늘 보니 눈이 많이 와서 아내 지인은 타호에서 새크라멘토로 오는 I-80 고속도로에서 네시간이 넘도록 갇혀 있었다고 하니, 오늘 출발 했으면 고생을 했겠다는 생각이 듭니다.

온 지 하루도 되지 않아 오늘 집 근처 일대가 모두 정전이 되었습니다. 아침부터 비바람을 맞으며 레몬나무를 다듬는데, 바람이 심상찮게 느껴졌었는데 결국은 오후 늦게 정전이 되어버리네요. 바람이 거세서 어디 전봇대 하나가 넘어지기라도 했나봅니다.

덕분에 캠핑용 랜턴을 꺼내 거실에 켜 두고 헤드 플래시와 스마트폰 플래시로 겨우겨우 버텨야 했습니다. 전기가 없어서 히터도 돌지 않고, 워터리스 가스 보일러라 뜨거운 물도 나오지 않은데 다행히 가스레인지는 동작을 해서 어찌 저찌 저녁은 겨우 해 먹었네요.

그래도 타호에서 일찍 오길 잘했습니다. 일찍 온 덕분에 집안 온도도 미리 68도로 끌어올려 둘 수 있었네요. 오늘 왔다면 차가운 집에서 히터도 틀지 못하고 추위에 벌벌 떨 뻔 했습니다.

얼마 전 지인 집이 정전되었을 때 다시 전기가 들어오는데 하루 반나절이 걸렸다는데, 이번에는 정전 된 지역이 워낙에 커서 더 오래 걸릴 수도 있겠다는 생각이 듭니다.

여긴 한국과 다르게 정전이 빈번한 듯 합니다. 매번 폭풍우가 온다고 하면 여기에 오래 계셨던 지인들은 정전을 걱정했었습니다. 한번 정전되면 복구도 꽤 오래 걸리는 것 같아요. 한국 같이 수 시간 내에 복구되는 일은 드물고 보통은 하루, 길게는 일주일이 넘도록 복구가 안되는 경우도 있다고 하네요. 느린 걸 전제로 사회체계가 굴러갑니다.

Half Moon Bay 게잡이

이곳 캘리포니아에 와서 새로 경험한 것이 정말 많습니다. 그 중에서, 겨울철이 되면 보게 되는 '게'가 그 중 한 종류일 것 같네요. 한국에서는 꽃게, 가끔씩 매우 비싼 베링해 근처에서 잡힌 킹크랩을 보는게 전부인데요. 이곳 캘리포니아에서는 가장 유명한 게를 꼽으라면 던저니스 크랩(Dungeness Crab)일 겁니다.

Dungeness Crag

정말 큰 크기에 깜짝 놀라고 살이 킹 크랩만큼 많이 들어있어서 또 한번 놀란 게 입니다. 지역이 다르니 먹거리도 다르구나.. 라는 생각을 들게 한 녀석이죠. 이쪽 북캘리에서부터 알래스카까지 퍼져있는 종 인데 겨울철 인기 음식입니다.

매번 사서 먹다가, 한번 직접 잡아볼 생각으로 지인에게 장비를 빌려서 다녀왔습니다.

면허 (License) & 규칙

캘리포니아에서는 한국과 다르게 아무 곳에서나 게를 잡거나 낚시를 하면 깜짝 놀랄만한 벌금을 물게 됩니다. 가장 큰 벌금은 '전복잡기' 인데요, 면허없이 잡으면 문제고, 면허가 있어도 정해진 수량 (2개)이상 잡으면 벌금이 10,000 달러가 넘을 정도로 큽니다.

게잡이나 낚시도 면허가 필요합니다. 그러나 면허가 없이 낚을 수 있는 곳이 있는데, 바로 공공 부두입니다.

Pacifica 공공부두: 출처 Fishermenneverlie

이곳에서는 정해진 규칙 안에 자유롭게 낚시와 게잡이가 가능합니다. 제가 사는 곳에서는 게잡이로 위 사진에 보이는 퍼시피카 부두로 가는게 보통인데, 저기는 전문적인 기술이 없으면 쉽지 않다고 해서 초보자에게 인기가 있는 하프 문 베이로 가보았습니다. 게잡이는 하프문 베이가 남쪽으로 잡을 수 있는 한계선이고, 그보다 아래에 있는 산타크루즈 피어나 Seaside 피어는 일반 낚시하러 갈 수 있습니다.

게잡이는 크기에 제한이 있는데, 던저니스 크랩은 등껍질 크기가 5.75인치 이상이 되어야 하고, 그 외의 게는 4인치 이상이 되어야 합니다. 또한 상업용도로 게잡이를 할 때에는 암컷은 놔주어야 하며, 일반인이 게잡을 때는 성별에 상관없이 잡을 수 있습니다. 다만 관례상 암컷은 풀어주는 게 보통입니다.

하프 문 베이 피어

Pillar Point Harbor

물이 찰 때 게를 잡아야 잘 잡힌다고 해서 일찍 서두른다고 했는데 하프문 베이 피어(위의 사진에서 보이는 필라 포인트 항구가 하프 문 베이 피어입니다)에 도착하니 9시 30분이 되어버렸네요. 서둘러 빌려온 낚시대 두개와 통발에 준비해 온 닭고기를 썰어 넣고 던졌습니다.

5~10분마다 한번 씩 들어올려보면서 게가 잡혔나 보는데, 작은 게들만 올라와서 바로 바로 풀어주었습니다. 던질때 마다 미끼로 준비해 간 닭고기가 싸그리 사라지는 걸 보니 게인지 아닌지 모르겠지만 바다속에 먹는 녀석이 매우 많나봅니다. 그런데 잡혀주질 않네요. ^^

12시까지 낑낑대면서 5인치 가량 되는 던저니스 크랩을 잡아서 아쉬워 해 보고, 작은 녀석들은 바로 바로 풀어주고 했지만, 운이 좋게 5인치쯤 되는 Red Rock Crab과 6인치쯤 되는 Red Rock Crab 두 마리를 잡을 수 있었습니다. 큰 게가 올라오자 아이들이 무척이나 즐거워 하네요. 이리 보고 저리보며 신기해 합니다.

근처에서 점심을 먹고 (다시는 Fish & Chips는 주문하지 않을겁니다) 다시 와서 한시간 가량을 더 낚으니 6인치쯤 되는 Red Rock Crab을 한마리 더 잡았네요.

3시간 반 정도 낚은 끝에 던저니스 크랩을 낚지도 못하고, 레드 락 크랩만 세마리 잡았습니다. 그래도 아이들도 게잡는 걸 지루해 하지 않았고, 날씨 좋은 날 바깥 구경도 하고, 집에 와서 잡은 게를 쪄서 먹으니 재밌는 경험이네요.

다음엔 좀 제대로 된 낚시대로 일반 물고기를 잡아볼까 생각 중입니다. 어릴 적 아버지와 함께 낚시를 종종 갔던 기억이 나네요. :)

미국에 넘어온 3년

오늘 2017년 1월 14일은 제가 미국에 넘어온 지 만 3년이 되는 날입니다. 달랑 캐리어 하나 들고 가족은 한국에 잠시 두고 장거리 비행을 한 후 초췌한 모습으로 입국 심사관을 대했던 게 기억에 나네요. 친한 형의 도움을 받아 그날 바로 중고 자동차를 구입하고 익숙하지 않은 차를 몰며, 익숙하지 않은 교통체계에 실수를 연발하며 어두운 밤길을 운전해 오던 것도 기억이 납니다. 그날 San Ramon에 멈춰서 인앤아웃에서 햄버거를 먹었던 것도 기억이 나고요.

3년이 지나고 나니, 어느새 아이들은 부쩍 커서 큰 아이는 킨더를 가고, 작은 아이는 자기 주장이 생겨서 미운 네.살이 되고, 단칸방 하숙에서 아파트를 거쳐 월세지만 단독주택에 지내게 되었네요. 영주권도 무사히 받아서 신분 걱정을 하지 않고 지내게 되었고요. 직장도 비록 회사 자체가 위태위태하지만, 직장 내에서 적당히 인정받고 열심히 일할 수 있게 되었습니다. 아이들과 아내는 아직은 완전히는 아니지만 꽤 많이 미국생활에 적응해 가고 있네요. 짧지 않은 시간이지만 그래도 정말 빠르게 지나간 것 같습니다.

3년동안 있었던 많은 일들이 추억으로 느껴질 만큼 아련하면서도 눈을 감으면 떠오를 만큼 선명하네요. 지나온 3년이 우리 가족에게 적응의 시간이어서 힘든 때도 있었지만, 그래도 나름 좋은 일이 가득했었던것 같습니다. 그래서, 앞으로 얼마나 길게 미국에 거주하게 될 지 모르겠지만, 앞으로의 시간도 좋은 일만 가득할 것 같다는 생각이 드네요.

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개월 더 빨리 나올 수 있었겠지만, 이제 그 모든 게 지나간 일이 되었네요.

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

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

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