지난 21일 Weird Developer Melbourne 밋업이 있었다. 3회차인 이번 밋업은 라이트닝 토크 형식으로 진행되었고 그 중 한 꼭지를 맡아 C# 초보가 C# 패키지를 만드는 방법 주제로 발표를 했다.

C# 스터디에 참여한 이후에 윈도 환경에서 작업할 일이 있으면 C#으로 코드를 작성해서 사용하기 시작했다. 하지만 업무에서 사용하는 기능은 한정적인데다 의도적으로 관심을 갖고 꾸준히 해야 실력이 느는데 코드는 커져가고, 배운 밑천은 짧고, 유연하고도 강력한 코드를 만들고 싶다는 생각을 계속 하고 있었지만 실천에 옮기질 못하고 있었다.

얼마 전 저스틴님과 함께 바베큐를 하면서 이 얘기를 했었는데 “고민하지 않고 뭐든 만드는 것이 더 중요하다”는 조언을 해주셨다. 말씀을 듣고 그냥 하면 되는걸 또 너무 망설이기만 했구나 생각이 들어서 실천에 옮겼다. 특별하게 기술적으로 뛰어난 라이브러리를 만들거나 한 것은 아니지만 생각만 하고 앉아있다가 행동으로 옮기는 일을 시작한 계기와 경험이 좋아서 발표로 준비하게 되었다.

발표 자료는 다음과 같다.

발표는 다음 같은 내용이 포함되었다.

  • MonoDevelop에서 간단한 예제 코드 시연
  • 라이브러리 작성하면서 배운 것
  • GitHub
  • Nuget 패키지
  • AppVeyor 설정

라이트닝 토크라서 이 주제가 괜찮지 않을까 생각했지만 다른 분들은 더 심도있는 주제를 많이 다뤄서 쉬어가는 코너 정도 느낌이 되었던 것 같다. 시간을 짧게 한다고 좀 더 설명할 부분을 그냥 넘어가거나 보여줄 페이지를 다 보여주지 못했던 점도 아쉽다.

발표 이후로도 계속 시간을 내서 라이브러리도 다듬고 C# 공부도 부지런히 해야겠다는 생각을 했다. (아직도 갈 길이 멀다!) 학습에서 유익했던 자료와 보고 있는/볼 예정인 자료를 참고로 남긴다.

  • [C# Fundamentals for Absolute Beginners

]6 MVA 강의로 C# 기초와 VS 사용 방법을 배울 수 있음. 최근 리뉴얼 한듯.

In Weird Developer Melbourne! Thanks @justinchronicles

Interfaces separated from the class implementation in separate projects?를 짧게 번역했다. 이 포스트는 cc-by-sa를 따른다.


인터페이스는 클래스 구현과 별도의 프로젝트로 분리해야 하나요?

Tomas Walek의 질문

현재 중간 규모의 프로젝트를 개발자 3명이서 6개월 넘게 진행하고 있다. 구체적인 구현에서 인터페이스를 분리하자는 결론에 이르렀다. 가장 먼저 인터페이스를 별도의 파일로 보관하기로 했다.

추가적으로 데이터를 더 분리하기 위해서 인터페이스 .CS 파일과 헬프 클래스 .CS 파일(이 인터페이스를 사용하는 퍼블릭 클래스나 enum 등)을 담은 프로젝트(CSPROJ)를 만들었다. 그리고 팩토리 패턴이나 구체적인 인터페이스 구현, 다른 “워커” 클래스 등을 별도의 프로젝트(CSPROJ)로 만들었다.

어떤 클래스든 인터페이스를 구현하는 개체를 생성하려면 그 자체만으로 구현하지 않고 인터페이스와 퍼블릭 클래스를 포함하는 첫 번째 프로젝트로 분리한 다음에 해당 프로젝트를 포함하는 방식으로 작성했다.

이 해결책은 큰 단점이 있다. 어셈블리 수가 2배로 늘게 된다는 점인데 모든 “일반” 프로젝트가 하나의 인터페이스 프로젝트와 하나의 구현 프로젝트를 포함하게 되기 때문이다.

당신의 추천은 무엇인가? 각각 프로젝트 자체에 인터페이스를 보관하는 것보다 인터페이스 만을 위한 별도의 프로젝트 하나를 갖는 것이 좋은 생각인가?


Wim Coenen의 답변

  1. **독자적 인터페이스 (Standalone interfaces)**는 프로젝트 나머지와 소통할 필요 없이 사용할 수 있도록 제공하는 목적에서 작성한다. 이런 인터페이스는 단일 항목으로 “인터페이스 어셈블리(interface assembly)”에 넣게 되고 프로젝트 내 모든 어셈블리가 참조할 것이다. ILogger, IFileSystem, IServiceLocator가 전형적인 예시다.
  2. **클래스 결합 인터페이스 (Class coupled interfaces)**는 오직 프로젝트 내의 클래스와 사용하는 맥락에서만 이해가 되는 경우다. 이 인터페이스는 의존성을 갖는 클래스와 동일한 어셈블리에 포함한다.

예를 들어보자. 도메인 모델이 Banana 클래스를 갖고 있다고 가정한다. 바나나를 IBananaRepository 인터페이스를 통해서 얻을 수 있다면 이 인터페이스는 바나나와 밀접하게 결합된 상황이다. 이 경우에는 바나나에 대해 알지 못하고서는 이 인터페이스를 구현을 한다거나 이 인터페이스를 사용하는 일이 불가능하다. 그러므로 이 인터페이스는 바나나 어셈블리와 함께 위치하는 것이 논리적이다.

앞 예제는 기술적인 결합이지만 논리적으로 결합하는 경우도 있다. 예를 들면, IFecesThrowingTarget 인터페이스는 Monkey 클래스에 기술적인 연결 고리로 선언되어 있지 않더라도 Monkey 클래스와 함께 사용하는 경우에만 유의미할 수 있다.

내 답변은 개념에 의존적이지 않으며 클래스가 약간 결합하는 정도는 괜찮다고 생각한다. 모든 구현을 인터페이스 뒤에 숨기는 일을 실수일 것이다. 의존성을 주입하거나 팩토리를 통해 인스턴스를 생성하지 않고 그냥 클래스를 “new 키워드로 생성”하는 것도 괜찮을 수도 있다.

tmux는 입력하는 내용을 현재 열린 모든 pane에 전달하는 기능을 제공한다. 여러 위치에 있는 내용에 대해서 동일한 작업을 수행해야 하는 경우에 유용하게 사용할 수 있다. 이전부터 기능이 있다는 점은 알고 있었는데 딱히 사용할 일이 없다가 최근 장애 대응 중에 유용하게 사용해서 기록 해둔다.

tmux 창에서 pane을 열고 다음과 같이 입력한다. on이나 off를 지정하지 않으면 현재 설정과 반대로 토글한다.

<Ctrl-B>, :
setw synchronize-panes on

설정을 켠 다음에 입력하면 현재 창에 열린 모든 pane에 동시에 입력되는 것을 확인할 수 있다.

자주 사용한다면 단축키로 저장해둘 수 있다. .tmux.conf에 다음처럼 설정을 추가한다.

bind-key y set-window-option synchronize-panes

이제 <Ctrl-B>, y로 간편하게 사용할 수 있다.

2016-07-13 추가:

Vue.js 포럼에 한국어 사용자 카테고리가 추가되었고 해당 포럼에서 문서 한국어화를 진행한다고 한다. 이 문서 외 Vue.js에 관심이 있다면 해당 포럼을 확인해보자.


Vue.js 문서를 살펴보던 중에 Comparison with Other Frameworks 내용이 괜찮아서 짧게 번역했다. Vue.js의 문서답게 기승전vue.js 이긴 하지만 각각의 프레임워크가 어떤 특징이 있고 어떤 주요 이슈가 있는지 잘 정리되었다.


다른 프레임워크와 vue.js 비교

Angular

모두에게 적용될 만한 항목은 아니지만 Angular 대신에 Vue를 선택해야 할 이유가 몇 가지 있다.

  • Vue.js는 API나 디자인 측면에서 Angular에 비해 훨씬 단순하다. 대부분의 내용을 빠르게 배울 수 있어서 생산성이 좋다.
  • Vue.js는 더 유연하면서도 덜 의견지향적인 해결책을 제시한다. 이 특징은 모든 개발의 흐름을 Angular 방식에 맞춰 개발하는 접근 방식과 다르게 자신 스스로가 원하는 애플리케이션 구조를 사용할 수 있다. 이 라이브러리는 인터페이스 레이어(interface layer)에 해당하기 때문에 풍성한 SPA 기능 대신에 각 페이지에서 사용할 수 있는 가벼운 기능을 제공한다. 이러한 접근 방식은 다른 라이브러리와 조합해서 사용하는데 넉넉한 공간을 제공한다. 물론 구조적 결정에 대한 책임도 생긴다. 예를 들면 Vue.js 코어에서는 기본적으로 라우팅이나 ajax 기능이 포함되지 않는다. 그리고 애플리케이션을 만드는 대부분의 경우에 외부 모듈 번들러를 사용한다고 가정하고 있다. 이런 특징을 가장 중요한 차이로 볼 수 있다.
  • Angular는 각 스코프(scope) 사이에서 양방향 바인딩(two-way binding)을 사용한다. Vue도 명시적 양방향 바인딩을 지원하긴 하지만, 기본 설정은 컴포넌트(component) 간, 부모에서 자식으로 단방향 바인딩(one-way)으로 구성되어 있다. 대형 앱에서는 단방향 바인딩을 사용하면 데이터의 흐름을 만들기 더 쉽기 때문이다.
  • Vue.js는 디렉티브와 컴포넌트를 명확하게 분리한다. 디렉티브는 DOM 조작을 캡슐화한 기능이고 컴포넌트는 뷰 자신과 데이터 로직을 포함한 독립 단위를 뜻한다. Angular에서는 이 둘의 차이가 상당히 혼란스럽다.
  • Vue.js는 변경 확인(dirty checking)을 수행하지 않기 때문에 좋은 성능을 제공하고 매우 매우 쉽게 최적화 할 수 있다. Angular는 감시자(watcher)가 늘어날 때마다 느려진다. 매번 스코프가 변경될 때마다 모든 감시자가 평가를 다시 수행하기 때문이다. 게다가 이 평가 흐름(digest cycle)에서 감시자가 다른 갱신을 수행하게 되면 모든 데이터가 “안정화(stabilize)” 될 때까지 반복하게 된다. Angular 사용자는 이런 상황을 해결하기 위해서 종종 난해한 기법을 사용하기도 하고 어떤 상황에서는 너무 많은 감시자가 있다보니 아예 간단하게 최적화 할 방법이 존재하지 않을 때도 있다. Vue.js를 사용한다면 이런 상황으로 고통 받을 필요가 없다. 비동기 큐 형태의 옵저버 시스템을 구현해서 의존성을 투명하게 관리하기 때문이다. 의존 관계가 명시적으로 기록되지 않았다면 모든 변경에 대해 독립적으로 이벤트를 호출한다. 앞으로 필요하게 될 최적화에 대한 힌트를 준다면 v-for 목록의 track-by 파라미터를 확인해보자.

Angular 1의 문제를 해결하기 위해서 Angular2 와 Vue가 접근한 방식이 다소 비슷하다는 점은 흥미로운 사실이다.

React

React와 Vue.js는 반응형 & 조합 가능한 뷰 컴포넌트를 제공한다는 점에서 유사점을 공유한다. 물론 많은 차이점도 존재한다.

먼저 내부 구현이 근본적으로 다르다. 리액트의 렌더링은 가상 DOM에 의해 이뤄진다. 가상 DOM은 메모리에서 실제 DOM이 어떤 형태로 존재하는지 저장하는 방식이다. 상태가 변경되면 React는 가상 DOM 전체를 다시 생성한 다음에 DOM을 비교하고 변경된 정보를 실제 DOM에 반영한다.

가상 DOM 접근은 뷰가 어떤 상황에서든 값에 따라 동일하게 동작하는 함수적 접근 방식을 제공하고 있으며 정말 좋은 방법이라 할 수 있다. 전체 앱을 매 차례 다시 생성한다면 관찰자를 만들 필요도 없고 뷰는 항상 데이터와 동기화 되어 있다는 점을 명확하게 보증하기 때문이다. 게다가 이 접근 방식은 동형(isomorphic) 자바스크립트 애플리케이션에 대한 가능성도 열었다.

Vue.js는 실제 DOM을 템플릿으로 사용하고 데이터를 실제 노드에 참조해서 사용하고 있다. 즉, Vue.js의 환경은 DOM에서 표현하는 방식으로만 사용 가능하다는 제약이 있다. React가 가상 DOM을 사용해서 다른 것에 비해 빠르다고 생각할 수 있지만 이 일반적인 오해와는 반대로 직접 갱신(hot update)에 있어서는 Vue.js가 React에 비해 손수 최적화하지 않고도 훨씬 빠르게 동작한다. React를 사용하는 경우에는 shouldComponentUpdate을 모든 위치에 구현해야 하며 불변 데이터 구조를 사용해야 다시 렌더링하게 되는 경우에 완벽한 최적화를 수행할 수 있다.

API 단위에서 React(또는 JSX)의 문제는 함수를 렌더링하는데 종종 많은 로직이 동반되는 경우가 많고 결과적으로 인터페이스의 시각적인 표현보다는 그 자체로 작은 프로그램 조각이 되고 만다. 개발자 일부에게는 이런 특징이 이익으로 느껴지겠지만 나처럼 디자이너/개발자를 겸하는 사람에게는 템플릿을 만들어서 디자인과 CSS를 더 시각적으로 생각하는 방식이 훨씬 쉽게 느껴진다. JavaScript 로직이 섞인 JSX는 디자인에 코드를 적용하기 전까지 확인이 쉽지 않은 방식이다. Vue.js는 대조적으로 경량의 데이터 바인딩을 비용으로 지불하는 대신에 시각적으로 확인 가능한 템플릿을 제공하고 로직은 디렉티브와 필터를 사용해서 캡슐화 하는 방식을 사용한다.

React의 다른 문제는 DOM 갱신이 전적으로 가상 DOM에서 이뤄지기 때문에 DOM을 직접 제어하고 싶은 경우에 다소 까다롭다. (이론적으로 가능하긴 하지만 라이브러리의 방식에 반해서 작업 해야한다.) 애플리케이션에서 DOM 조작에 부차적인 제어가 필요한 경우에는 이런 제한적인 특성으로 인해 짜증나는 작업이 되고 만다. 특히 요구사항이 시간적 흐름에 따라 변화하는 애니메이션이 그렇다. 반면 이런 문제에서 Vue.js는 더 유연하기 때문에 큰 문제가 되질 않는다. FWA/Awwwards에서 수상한 사이트 다수가 Vue.js로 만들어진 이유가 거기에 있다.

아래는 몇 가지 살펴볼 만한 내용이다.

  • React 팀은 React를 모든 플랫폼 UI 개발에서 사용하려고 하는 야망을 갖고 있는 반면에 Vue는 웹을 위한 실용적인 해결책을 제공하는데 촛점을 두고 있다.
  • React는 함수적인 환경을 제공하고 있어서 함수형 프로그래밍 패턴과 아주 잘 맞는다. 이런 특징은 초보자나 주니어 개발자에게 큰 학습 장벽이 된다. Vue는 훨씬 간단하게 바로 사용할 수 있어서 더 효율적이다.
  • 대형 애플리케이션을 개발하는 경우에 React 커뮤니티에서는 상태 관리를 위한 해결책으로 Flux, Redux와 같은 혁신이 있었다. Vue 자체는 이런 문제를 크게 괘념치 않는데 (React 코어도 동일하다.) 비슷한 아키텍쳐라면 상태 관리 패턴은 쉽게 이식할 수 있는 개념이다. Vue 자체에서 사용할 수 있는 상태 관리 솔루션으로 Vuex가 있고, Redux를 Vue와 사용하는 것도 가능하다.
  • React 개발의 트랜드는 CSS까지 모든 것을 JavaScript에 집어넣는 분위기다. JS에 CSS를 넣는 많은 해결책이 존재하지만 각각 크고 작은 문제를 갖고 있다. 가장 중요한 문제는 표준 CSS 저작 경험을 벗어나고 있는데다 기존 CSS 커뮤니티가 일궈 놓은 작업을 이상하게 만드는데 지렛대 역할을 하고 있다. Vue의 단일 파일 컴포넌트는 컴포넌트 단위로 캡슐화된 CSS를 작성할 수 있고 선택에 따라서 전처리기를 선택하는 것도 가능하다.

Ember

Ember는 모든 기능을 제공하는 프레임워크로 아주 의견지향적으로 디자인되었다. 이 프레임워크는 많은 양의 컨벤션을 제공한다. 제공하는 모든 문법에 충분히 익숙해지면 아주 생산적으로 활용할 수 있다. 하지만 학습 곡선이 높은 데다 유연함이 고통을 준다. 의견지향적 프레임워크와 느슨한 의존성으로 묶인 여러 라이브러리 중 어느 것을 선택하느냐에 따라 얻거나 잃을 수 있는 부분이다. 후자를 선택하면 더 자유롭긴 하지만 구조적 결정을 내려야 하는 상황에 놓인다.

Vue.js 코어와 Ember의 템플릿, 개체 모델 레이어를 비교하는 것이 더 나을 것이다.

  • Vue는 눈에 거슬리지 않는 반응성을 일반 JavaScript 개체를 통해 제공하며 모든 프로퍼티가 자동으로 연산된다. Ember에서는 모든 Ember 개체로 감싸야 하며 연산 프로퍼티를 사용하려면 수동으로 의존성을 선언해야 한다.
  • Vue의 템플릿 문법은 JavaScript 표현식 전체를 사용할 수 있는 반면에 Handlebar 표현식과 헬퍼 문법은 다소 제한적이다.
  • 성능에 있어서 Ember가 2.0에서 Glimmer 엔진으로 변경했는데도 여전히 Vue가 빠르다. Vue는 자동으로 일괄 갱신을 수행하는 반면 Ember는 성능에 민감한 상황에서 실행 순환을 수동으로 관리해야 할 필요가 있다.

Polymer

Polymer는 Google이 지원하는 또 다른 프로젝트다. 사실 Vue.js도 이 라이브러리에서 영감을 받고 만들었다. Vue.js의 컴포넌트는 Polymer의 커스텀 엘리먼트와 느슨하게 비교되는데 이 두 기능은 아주 비슷한 개발 스타일을 제공한다. 가장 큰 차이점은 Polymer가 최신 웹컴포넌트 기능 위에서 개발되었고 기능이 제공되지 않는 브라우저에서 사용하기 위해서는 폴리필이 필수적으로 필요하다. (폴리필이라서 성능도 떨어진다.) 이 특징과 대조적으로 Vue.js는 IE9까지 어떤 기술 의존 없이도 잘 동작한다.

또한 polymer 1.0 팀은 성능을 챙기기 위해서 데이터 바인딩을 매우 제한적으로 가능하게 만들었다. 예를 들면, Polymer 템플릿의 표현식은 불린 부정(boolean negation)과 단일 메소드 호출만 지원한다. 또한 연산 프로퍼티의 구현이 아주 경직되어 있다.

마지막으로 프로덕션에 배포할 때는 Polymer 엘리먼트를 Polymer에 특화된 도구인 vulcanizer를 사용해서 번들링 해야한다. 이와 대조적으로 Vue 컴포넌트는 단일 파일로 Webpack 생태계가 제공하는 모든 기능을 사용할 수 있다. 이 특징 덕분에 Vue 컴포넌트에 ES6도 쉽게 적용할 수 있고 CSS 전처리기도 필요하다면 바로 사용할 수 있다.

Riot

Riot 2.0은 유사한 컴포넌트 기반 개발 모델을 제공한다. (Riot에서는 “tag”라고 부른다.) 이 모델은 작고 아름답게 디자인된 API를 제공한다. 내 생각에는 Riot과 Vue는 디자인 철학을 많이 공유하고 있다. Vue는 Riot에 비해 조금 무겁지만 Riot에 비해 중요한 잇점을 제공한다.

  • 참 조건부 렌더링 (Riot 렌더링은 브랜치에 있다면 모든 내용을 렌더링하고 단순히 보여주고 숨기는 기능만 수행한다.)
  • 더 강력한 라우터 (Riot의 라우팅 API는 지나치게 단순하다.)
  • 더 성숙한 도구 지원 (webpack + vue-loader를 확인한다.)
  • 트렌지션 효과 시스템 지원 (Riot에는 없다.)
  • 더 나은 성능 (Riot은 사실 가상 DOM보다 변경 확인(dirty checking)을 사용하고 있어서 Angular와 동일한 성능 이슈가 발생한다.)

최근에 화웨이 P9 Plus를 구입해서 오랜만에 안드로이드 환경을 사용하기 시작했다. 롬을 변경하거나 하지 않고 기본 EMUI를 사용하고 있는데 기본 한국어 폰트가 너무 안이뻐서 폰트를 변경하게 되었다. 혹시나 싶어 기록삼아 포스팅을 남기게 되었다.

그냥 ttf 넣는다고 바로 변경되지 않아서 한참 검색했는데 이전 버전은 간단하게 가능한 반면 4 버전 이상에서는 쉽게 되질 않아 결국 편법으로 변경했다. 폰트를 변경하는 앱이 있나 찾아보니 있긴 한데 평이 전부 더이상 되지 않는다는 얘기라서 설치해보지 않았다.

  • 먼저 Themes > Fonts 에서 무료 폰트를 아무거나 받는다.
    • 이 과정에서 화웨이 ID가 필요한데 폰에서 가입이 진행이 안되길래 화웨이 웹페이지에서 가입했다. (찾아보면 가입 주소가 상당히 다양하다.)
  • 새 폰트를 받으면 HWThemes/HWFonts 디렉토리가 생기고 새 폰트가 ttf 파일로 들어있다.
  • 사용하려고 하는 폰트를 위에서 받은 폰트 이름과 동일하게 변경해서 넣는다. (otf나 ttc 파일의 경우에도 이름만 ttf로 설정해서 넣어도 문제 없다.)
  • Themes > Fonts 에서 해당 폰트로 설정한다.
    • 미리보기는 그냥 이미지라서 무료 폰트 모양이지만 폰트는 변경한 ttf로 적용된다.

분명 메타데이터를 같이 넣는 방법이 있을 것 같은데 인터넷서 찾은 방법으로는 적용이 되질 않았다. 폰트와 xml 메타 데이터를 생성해서 <fontname>.hwt 폴더나 zip으로 압축해서 해당 이름으로 변경해서 넣으면 된다고 하는데 버전 차이인지 인식이 안된다. 서체는 Noto Sans Demi-Light가 가장 깔끔했다.

이전까지는 lubuntu에 있던 xterm을 비트맵이 정겨워서 그냥 사용했는데 특수 기호를 표시하는데 불편함이 있어서 터미널을 변경하며 손 본 기록을 남긴다. 지금 사용하는 환경은 별 특별한 내용 없이 기본 lubuntu 설치 상태다.

gnome-terminal 설치

다른 터미널 다 살펴봤는데 우분투 기본 터미널인 gnome-terminal 쓰기로 했다. lubuntu에서 제공하는 lxterminal은 별로 안이쁘다.

$ sudo apt-get install gnome-terminal

시작할 때 터미널 기본 시작

전체화면을 위한 플래그 셋, 그리고 시작 후에 터미널에서 tmux를 실행하도록 작성했다. 동일한 내용으로 /usr/local/binterminal 스크립트를 추가했다.

#!/bin/bash
gnome-terminal --window --hide-menubar --full-screen -e tmux

시작 -> 기본 설정 -> Default Applications for LXSession 들어가서 autostart에 terminal을 추가했다.

기본 IM와 연동되도록 플러그인 설치 fcitx.vim

Lubuntu에는 Fcitx-IM가 기본 IME다. Vim에서 모드를 전환하는 경우에 영문 자판이 아니면 매번 한영전환을 해야 하는 번거로움이 있는데 이 fcitx.vim 플러그인이 그 해결책이다. 이 플러그인은 Vim에서 모드를 전환하면 영문으로 전환하고 다시 끼워 넣기 모드로 돌아올 때, 이전 언어로 자판을 변경한다.

fcitx.vim 받아서 ~/.vim/plugin에 해제하면 끝난다.


그 외 터미널 시작 시에 메시지를 넣었는데 별 내용 없이 .zshrcecho로 넣었다. 분실 연락처 정도 넣었다. 아직 Vim을 사용해야 해서 아직 neovim으로 넘어가지 않았는데 얼른 하는 일 마무리하고 넘어가고 싶다. 이상하게 nvm이 터미널 시작을 느리게 만들어서 일단 주석 처리 해뒀다. 조만간 다시 확인해봐야겠다.

오랜만에 깔끔한 폰트로 터미널을 사용하니 또 새롭다. 바쁜 일을 좀 정리한 후에는 환경을 좀 더 꾸며보고 싶다.

지금까지 git을 숱하게 사용했지만 한글 파일명은 문제가 생긴다는 사실을 이제야 알았다.

다음처럼 core.quotepath를 끄면 commit, status 등에서 한글 출력이 정상으로 돌아온다. 이 설정은 일반적이지 않은 문자를 탈출문자로 처리하는 기능을 수행한다. 그래서 한글 앞에 탈출 문자를 붙인 탓에 이런 문제가 발생했다.

git config --global core.quotepath false

관련 링크

근래 화웨이나 DJI와 같이 대단한 제품을 만드는 중국 기업이 눈에 띈다. 멋진 제품으로 승부하는 이런 회사는 갑작스레 출현했다기 보다는 든든한 중국 제조업의 질적 성장으로 외연이 넓어지면서 자연스럽게 들어나게 된 것은 아닌가 생각한다. 여전히 중국산 제품 중에는 말도 많고 탈도 많은 제품이 많을지 몰라도 더이상 저렴하고 질 낮은 제품과 동의어라고 쉽게 이야기하기 어려워졌다. 게다가 중국 브랜드가 새겨진 중국 키보드 하나 구입한 경험이 이 생각을 더 단단하게 만들었다. 이 글은 Ajazz Geek AK33 기계식 키보드를 구입하고 느낀 점을 정리한 글이다.

이 키보드는 사무실에서 사용하려고 구입했다. 알리 익스프레스에서 45.74달러(한화 52,000원 정도) 정도로 저렴하게 판매하길래 구입했다. 더 저렴한 기계식 키보드도 많이 있었지만 게이밍 키보드라는 점을 강조하고 싶었는지 각인이 다 이상해서 그나마 깔끔하고 무난한 이 키보드를 골랐다. 흰색과 검정 두 색상과 청축과 흑축 중 하나를 선택할 수 있다.

일단 사용하고 있는 키보드가 있기 때문에 급하게 부를 필요가 없어 무료 배송으로 받았다. 1달 여 시간이 지나서 키보드를 받았다. 상자에는 키보드와 중국어로 된 품질보증서로 추정되는 용지가 들어 있다. Zorro 스위치를 사용했고 82키 레이아웃에 LED가 내장되어 있다. 여태 알리에서 구입한 물건 중에 패키지가 가장 깔끔하고 튼튼해서 마음에 들었다.

Ajazz Geek AK33

키보드 기판이 노출되지 않도록 하는 부분을 하우징(housing)이라고 하는데 이 키보드는 하우징이 일반 키보드와 조금 다른 형태로 구현되었다. 사진으로 봤을 때는 키가 쉽게 뽑힐 것 같은 모습이었는데 생각보다 잘 결합이 되어 있고 키를 뽑지 않는 이상 청소하기 어려웠던 이전 키보드와 달리 쉽게 먼지를 털어낼 수 있는 점도 장점이다.

Ajazz Geek AK33 LED를 켠 모습

숫자 자판이 없는 텐키리스인데다 미니 키보드 레이아웃이라서 메타키가 우측에 세로로 나열되어 있다. 처음에는 방향키 레이아웃이 마음에 드는 형태가 아니라서 구입 전에도 망설였지만 방향키 크기가 다른 키에 비해서 충분히 커서 잘못 눌리지 않아 엄청 만족스럽다. 그래도 잘못 누르면 귀찮고 맥에서 자주 사용하는 메타키도 아니라서 비활성화했다.

  • 리니어 방식이라서 눌리는 느낌이 갈축, 멤브레인 키보드와도 다르다. 키가 반발력이 있어서 입력하고 나면 손가락을 밀어 올리는데 흑축 키보드를 사용하고 나서 다른 키보드를 사용하면 키를 누르고 나서 손가락을 의도적으로 들어 올리는 기분이 든다. 특히 이 키보드 쓰고 나서 애플 키보드를 사용하면… 이상해.
  • 키를 꾹꾹 눌르면 확실히 스위치 밀어 올리는 힘이 강하다. 나는 살살 입력하는 편이라서 크게 손이 아프거나 하지 않았다.
  • 갈축 키보드 소리에 익숙해서 그런지 시끄러운 느낌은 전혀 들지 않는다. 그래도 일반 멤브레인이랑 비교하면 소리가 많이 다르다.
  • LED는 끌 수 있다. 맥북 에어 키보드 조명처럼 은은할 줄 알았는데 무슨 파티 조명 같다. 둠칫둠칫. 금요일에 켜놓고 일해야지.
  • 오른쪽 시프트 키를 많이 사용한다면 방향키랑 가깝고 키가 작아서 좀 불편할 수 있다.
  • 폭이 넓은 키 중에 보강 스위치? 같은게 달린 키가 있는데 키감이 아무래도 좀 다르다. 특히 엔터 키가 좀 이질감이 있다.

Ajazz Geek AK33 흑축 스위치

레오폴드 FC700RT 갈축을 구입해서 집에서 사용하고 있는데 스위치 매커니즘이 달라 직접적인 비교는 어렵겠지만 레오폴드와 함께 봐도 별로 뒤떨어진다는 느낌이 들지 않는다. 더군다나 시중 기계식 키보드보다 1/3 가격 정도에 구입할 수 있다는 점이 큰 매력이다. 저렴한 가격의 입문용 기계식 키보드를 찾고 있다면 이 키보드로 시작해도 좋을 것이다.

맥에서 몇가지 키를 수정해서 사용하고 있다. 이 설정은 Karabiner를 사용했다. 이 키보드는 알리익스프레스에서 구입할 수 있고 내가 구입한 링크는 요기다.

작업을 하다 보면 작은 코드 스니핏을 공유해야 하는 경우가 있다. 간단하게 텍스트 파일을 작성해서 메일이나 메신저를 통해서 공유할 수도 있고 GitHub의 gist 서비스를 이용해서 공유할 수 있다. 이 gist에 코드를 올리는 작업을 브라우저 없이 터미널에서도 가능하다. 서비스 이름과 동일하게 명령도 gist다.

OS X에서는 Homebrew로 바로 설치할 수 있으며 루비로 작성한 도구라서 gem으로도 설치 가능하다. apt-get에도 올라와 있는데 우분투에서 설치하고 나서 제대로 동작하지 않아 gem으로 설치했다.

$ brew install gist # OS X에서 homebrew를 사용하는 경우
$ gem install gist # gem이 설치되어 있는 경우

설치를 한 다음, gist 명령을 입력하면 프롬프트가 출력되서 바로 코드를 작성할 수 있다.

$ gist
(type a gist. <ctrl-c> to cancel, <ctrl-d> when done)
// 코드를 바로 입력. cat과 같이 동작함.
console.log("Hello World");
// <ctrl-d>를 입력해 저장.
# https://gist.github.com/bc7c51a5d5bef0465c67b38c39f29b7e
$

아직 로그인을 하지 않았기 때문에 입력한 내용이 익명 계정으로 등록된다. 로그인은 --login 플래그를 사용해서 할 수 있다.

$ gist --login
Obtaining OAuth2 access_token from github.
Github username: haruair
Github password:
Success! https://github.com/settings/applications
$

간단하게 이미 작성한 파일을 올리는 것도 가능하다.

$ gist hello.js
$ gist index.js index.jade style.css # 여러 파일을 올릴 때

파일명은 -f 또는 --filename으로 지정 가능하다. 파일명을 지정한 경우에는 STDIN으로 올리려는 파일을 지정할 수 있다. 그리고 업로드한 주소를 바로 사용할 수 있도록 복사하는 -c, --copy 플래그도 존재한다.

다음 명령에서는 hello.js 파일을 index.js로 gist에 업로드하고 그 주소를 바로 복사한다.

$ gist -c -f index.js < hello.js
# https://gist.github.com/69872a365b9b073eb94ac14e87eb469e

이외에도 기존에 올린 코드를 수정하거나 private 모드로 올리기, embed 코드를 반환하는 등 다양한 플래그가 있다. 이 도구에서 제공하는 모든 기능은 --help로 확인할 수 있다. ruby로 작성되어 있어서 만약 ruby로 개발한다면 코드에서 사용할 수 있는 라이브러리 형태로도 제공한다. 엔터프라이즈 사용자를 위한 설정도 존재하는데 상세한 내용은 defunkt/gist 문서에서 확인하자.

터미널에서 작업을 하다보면 메모리 사용량이나 스토리지 사용량을 확인하기 위해 free -m 또는 df -h를 사용해본 경험이 있을 것이다. 명령을 입력하고 엔터를 누르는 순간에 명령을 처리하고 그 결과를 반환하기 때문에 지속적으로 변하는 결과를 살펴보기엔 불편하게 느껴질지도 모른다. 그런 상황에서 사용할 수 있는 명령이 바로 watch다. 이 명령으로 간격을 두고 반복적으로 결과를 확인하고 싶은 명령을 손쉽게 사용할 수 있다.

대부분의 리눅스 환경에는 이미 설치되어 있을 것이다. OS X의 경우에는 homebrew로 설치할 수 있다.

$ brew install watch

간단하게 사용해보자. date를 입력하면 현재 시각을 확인할 수 있다. watch date를 입력하면 매 2초 간격으로 date의 결과를 화면에 표시한다.

$ date
Thu 14 Apr 2016 22:02:59 AEST
$ watch date
Every 2.0s: date        Thu Apr 14 22:03:26 2016
Thu 14 Apr 2016 22:03:26 AEST

화면에서 빠져나오기 위해서 Ctrl + C를 입력한다. 기본적으로 2초의 주기로 설정되어 있는데 2초가 조금 길다면 -n, --interval을 이용해서 그 주기를 조정할 수 있다. -d, --differences를 추가하면 어느 문자가 변하고 있는지 강조된다. 스토리지의 용량을 확인하는 df 명령과 함께 사용하면 다음과 같다.

$ watch -d -n 0.5 df -h
Every 0.5s: df -h           Thu Apr 14 22:03:26 2016
Filesystem      Size   Used  Avail Capacity   iused      ifree %iused  Mounted on
/dev/disk1     931Gi  643Gi  287Gi    70% 168658707   75329829   69%   /
devfs          186Ki  186Ki    0Bi   100%       644          0  100%   /dev
map -hosts       0Bi    0Bi    0Bi   100%         0          0  100%   /net
map auto_home    0Bi    0Bi    0Bi   100%         0          0  100%   /home
/dev/disk2s1   1.8Ti  900Gi  963Gi    49%      2253 1009481363    0%   /Volumes/My Passport

만약 두 가지 이상의 명령을 동시에 모니터링하고 싶다면 간단하게 ;로 구분해서 호출할 수 있다. 다음은 현재 디렉토리를 확인하는 ls와 앞에서 본 df를 같이 사용하는 예시다.

$ watch -n 0.5 "ls -al ; df -h"
Every 0.5s: ls -al ; df -h          Thu Apr 14 22:03:26 2016
total 152
drwxr-xr-x@ 10 edward  staff    340 14 Apr 22:15 .
drwxr-xr-x@ 24 edward  staff    816 30 Mar 18:32 ..
-rw-r--r--@  1 edward  staff   2639 29 Mar 02:13 cowsay.md
-rw-r--r--@  1 edward  staff   2163  8 Apr 23:22 figlet.md
-rw-r--r--@  1 edward  staff   2541 14 Apr 21:43 gist.md
-rw-r--r--@  1 edward  staff    179  8 Apr 23:44 slurm.md
-rw-r--r--@  1 edward  staff  48201  8 Apr 23:26 slurm.png
-rw-r--r--@  1 edward  staff   1390  8 Apr 08:31 todo.md
-rw-r--r--@  1 edward  staff   2559 14 Apr 22:15 watch.md
-rw-r--r--@  1 edward  staff   2260  3 Apr 00:02 zsh-bash.md
Filesystem      Size   Used  Avail Capacity   iused      ifree %iused  Mounted on
/dev/disk1     931Gi  643Gi  287Gi    70% 168659745   75328791   69%   /
devfs          186Ki  186Ki    0Bi   100%       644          0  100%   /dev
map -hosts       0Bi    0Bi    0Bi   100%         0          0  100%   /net
map auto_home    0Bi    0Bi    0Bi   100%         0          0  100%   /home
/dev/disk2s1   1.8Ti  900Gi  963Gi    49%      2253 1009481363    0%   /Volumes/My Passport

명령을 쌍따옴표로 감싸서 실행했다. ;는 명령행에서 특별한 의미를 갖는 문자이기 때문에 watch 내에서만 실행하도록 전달하기 위해 쌍따옴표를 사용했다. 따옴표 없이 사용하려 한다면 \;와 같이 역슬래시로 탈출문자 처리를 하면 쌍따옴표 없이 동일한 결과를 모니터링 할 수 있다.

이처럼 watch는 아주 간단한 용도로 사용할 수 있는 모니터링 도구다. 즉 메모리나 프로세스를 모니터링 할 때는 htop과 같이 각 필요에 따라서 더 정밀하고 자세한 정보를 제공하는 도구가 많으니 자주 사용한다면 꼭 관련 모니터링 도구를 살펴보자.

색상을 바꿔요

눈에 편한 색상을 골라보세요 :)

Darkreader 플러그인으로 선택한 색상이 제대로 표시되지 않을 수 있습니다.