Don’t “Push” Your Pull Requests의 번역글이다. 코드를 기여하기 전에 그 커뮤니티의 분위기를 아는 것, 커뮤니티와 소통하는 것이 얼마나 중요한가에 대한 이야기다.

Ilya! Thank you for giving me the opportunity to translate this article. 😀


문제에 직면하거나 불편한 부분을 만나게 되면 에디터를 열고 코드를 수정해 문제를 해결하려고 파고들게 된다. 선한 의도로 간단한 패치를 만든다. 패치를 풀 리퀘스트로 보내고서 의자에 편히 기대고 결과를 지켜보게 된다. 자신을 스스로 대견하다고 생각하면서 말이다. 하지만 간단한 패치라고 해도 본 코드에 합쳐지기 전에 전례에 따라 준수해야 하는 몇 가지 원칙들이 있기 마련이다.

그 후에도 가끔 우연하게 불편한 문제를 발견하게 된다. 표면적인 문제로 아주 단순하게 해결할 수 있어서 하루 잠깐 짬을 내 개선을 할 수도 있고, 더 깊이 들어가 본질적인 문제를 살펴봐야 할 수도 있다. 그 결과, 이 문제를 완벽하게 해결한 300줄 이상의 패치, 수정된 여러 파일과 함께 지구를 구한 기분으로 풀 리퀘스트 보내게 된다.

여기에 모든 문제가 있다. 당신은 여기에 투자한 모든 시간과 작업, 노력을 인정받길 원한다. 하지만 메인테이너는 공포에 질려 패치를 들여다보고는 왜 그가 이 패치를 수락할 수 없는지 나열하게 된다. 그는 어디서 시작해야 할지도 몰라서 잘못된 부분만 콕 집어 살펴보게 된다. 당신이 기여한 코드는 어떤 방향으로도 빠르게 진행될 수 없다. 이런 문제는 어느 쪽을 비난할 수도 없는 상황이다.

풀 리퀘스트를 “떠넘기지” 말 것

기여는 항상 환영해야 마땅하지만, 깜짝 놀랄 패치는 결국 짐이 될 뿐이다. 당신은 분명 도움을 주기 위해 한 일이다. 하지만 누군가는 당신보다 더 오랜 기간 동안 그 코드를 유지보수 해왔다. 그러므로 그들을 놀라게 하는 것을 피하고 그들의 방식을 먼저 따르자. 더 최악인 경우는, 협소한 문제를 해결하기 위해 지역적인 변경을 만들어 프로젝트에서의 전체적인 구현을 놓치게 되는 경우가 있다. 미리 세워둔 로드맵 계획 또는 전체적인 구조적 결정 등을 엉망으로 만든다. 좋은 아이디어라도 몇 프로젝트에는 적절하지 못한 구현이 될 수 있다. 심지어 이 과정이 다른 사람의 노력을 무의미하게 만든다는 사실을 알아차리지 못할 수도 있다. 게다가 좋지 않은 타이밍이라면 이런 여러 이유로 인해 사람들이 당신을 등질 수도 있다.

코드 리뷰는 어렵다: 빨리 시작하자

다음부터는 에디터로 뛰어들기 전에 먼저 토론을 시작하고, 내 문제와 해결책에 대한 개요를 만들어 내가 어떤 일을 하려고 하는지 먼저 알리자. 그 목표를 설명하는 것은 한 문단으로 정리되어야 한다. 만약 그 글이 에세이가 되고 있다면, 문제를 더 잘게 쪼개야 한다는 신호거나 문제가 명쾌하게 정의되지 않은 상황이라는 의미다. 그 변경폭이 크다면 리뷰어를 정해 함께 전체적인 디자인을 살펴야 한다. 초기에 도움을 요청하고 손을 빌리면 만들려는 하는 코드를 마술과도 같이 제 시간에 작성해 “합칠(당겨질)” 수 있다.

코드 리뷰는 어렵다. 사실, 코드 리뷰의 효율은 200-400줄 코드를 넘으면 극단적으로 떨어지기 때문에 리뷰 속도는 시간당 300-500줄 미만으로 볼 것을 권장하고 있다. 이 방식을 계속 기억하자. 큰 커밋은 작고 다루기 쉬운 단위로 자른다. 가장 우선되는 규칙으로, 30분 정도 짧은 시간 동안만 리뷰를 한다. 또는 200줄 보다 짧은, (똑똑하진 않더라도) 깔끔하고 좋은 코드를 보는 것이다. 여러 개의 커밋이라도 로드맵을 함께 준다면 각각의 조각들에 대한 피드백을 한번에 받을 수 있을 것이다.

좋은 작업은 “밀어내기”가 아닌 “당기기”를 얻는다

스레드를 읽는 것만큼 귀찮은 일은 없다. 하지만 그보다 더 나쁜 경우는 기여하는 과정 끝에 내 기여가 잘못된 방향으로 흘러갔다는 사실을 받아들여야 할 때다. 기여자는 코드가 수락되지 않으면 상처를 받는다. 메인테이너는 딜레마에 빠진다. 그들은 커뮤니티를 통해 코드가 만들어지고 굴러가길 원하는데 이런 광팬들의 코드를 깊이 살펴보는 과정에서 그들과 대립하게 된다. 거기엔 승자가 없다. 게다가 어느 쪽도 비난할 수 없다.

다음엔 에디터로 뛰어들기 전에 토론을 시작하고, 내 문제와 해결책에 대한 윤곽을 잡아보고, 작업을 제안하자. 그저 어둠 속에서 작업해서 풀 리퀘스트로 “떠넘기지” 말자.


GitHub을 비롯해 이전보다 쉽게 참여할 수 있는 오픈소스 커뮤니티가 많아졌다. 내가 직접 작성한 코드라는 기쁨에 눈이 가려 코드를 꼼꼼히 잘 살펴보지 않고 풀 리퀘스트를 보낸 경험이 있어 이 글을 읽으며 그때의 일이 생각이 났다. 이제 막 오픈소스에 참여하려는 사람들에게 도움이 될 만한 글인 것 같아 번역하게 되었다.

최근 #이삭줍기, #코드줍기라는 이름으로 사소한 개선점을 오픈소스에서 찾아 pull request를 보내고 있는데 각각의 오픈소스마다 가진 문화나 분위기가 달라 배우는 점이 많다. 코드를 읽는 과정은 단순히 코드와 그 구조를 이해하는 것에 그치지 않고 타인을 이해하고 넓은 시야를 갖는 데 도움이 되는 느낌이다. 앞으로도 꾸준히 참여하고 참여한 커뮤니티에서 feel the room 할 수 있도록 노력해야겠다.

코드줍기란

erlang/otp의 위키에서 Writing good commit messages라는 짧은 글을 보고 한국어로 옮겼다. 대부분의 오픈소스는 각각의 Contribute 문서를 통해 어떤 관례를 사용하는지 밝히고 있는 편이지만 대부분 아래의 방식과 크게 다르지 않았다.


좋은 커밋 메시지는 다음 세가지 중요한 목적이 있다:

  • 리뷰 프로세스를 빠르게 만든다.
  • 좋은 릴리즈 노트를 작성하게 돕는다.
  • 미래의 코드 메인테이너를 돕는다. (그 메인테이너가 당신일 수도 있다!) 어떤 코드 변경이 일어났는지, 왜 이 특정한 기능이 추가되었는지 수년 후에 이야기 해도 알 수 있도록 말이다.

커밋 메시지의 구조는 다음과 같다. 이 내용은 git scm에서 자세하게 확인할 수 있다:

(50자 미만의) 변경에 대한 짧은 요약

필요하다면 상세한 설명을 첨가한다. 행 당 72자가 넘지 않도록 유의한다. 맥락에 따라 첫 줄은 이메일의 제목처럼,
나머지는 본문처럼 다뤄지는 경우가 있다. 요약과 본문을 구분하는 빈 행은 본문을 생략하지 않는 이상 필수적이다.
rebase와 같은 도구를 사용하면 혼란을 줄 수 있기 때문이다.

추가적인 문단은 빈 행 다음에 작성한다.

- 개조식 서술 또한 괜찮음

- 블릿(bullet)으로 하이픈(-)이나 별표(*)를 사용하고, 한 칸의 공간을 띄고 각 항목 사이 빈 행을 넣는
  방식이 일반적이나 다양한 관례가 있음.

해야 할 일

  • 요약과 설명을 작성할 때는 자신이 무엇을 했는지를 명령형으로 작성한다. 즉 다른 사람에게 이 일을 지시하듯 작성한다. “고쳤다 fixed”, “추가했다 added”, “변경했다 changed” 대신 “고치다 fix”, “추가하다 add”, “변경하다 change” 식으로 작성한다.
  • 항상 두번째 빈 행을 추가한다.
  • 커밋 메시지에서 줄 바꿈을 한다. (gitk등 커맨드 환경에서 커밋 메시지를 수평 스크롤 없이 쉽게 읽을 수 있는데 도움이 된다.)

하지 말아야 할 일

  • 요약 끝에 마침표를 찍지 않는다. 요약은 제목이다. 제목은 마침표로 끝나지 않는다.

  • 커밋을 요약하는데 어려움을 느낀다면 커밋 안에 여러 로직의 변화 또는 버그 수정이 있기 때문일 것이다. 이럴땐 git add -p 명령어를 사용해 여러 커밋으로 분리하는 것이 낫다.

레퍼런스

커밋 메시지에 대한 좋은 논의를 다음 블로그 포스트에서 확인할 수 있다.

SitePoint에 게시된, Bruno Skvorc의 Starting a New PHP Package The Right Way 포스트를 번역한 글이다. PHP는 autoload를 이용한 composer를 비롯 다양한 모듈화 방법이 논의되어 실제로 많이 활용하고 있다. PHP의 최근 동향을 살펴 볼 수 있는 포스트라 생각해 한국어로 옮겼다. 연재는 총 3회 분이며 이 포스트는 1회에 해당한다.

Bruno and Ophélie at SitePoint! Thanks for giving me the opportunity to translate your great article. 🙂


시각적 인공지능 기계학습 크롤러인 Diffbot을 이야기 할 때, 이 라이브러리를 사용할 수 있는 많은 프로그래밍 언어를 언급했다. 이 많은 언어를 동시에 보고 있으면 거기엔 미끄러져 흠집이 난, 상한 사과도 있기 마련이다. 그 사과 중 하나인 PHP 라이브러리는 이 연재에 기반해 더 나은 라이브러리를 만들고자 한다.

이 튜토리얼은 좋은 패키지를 어떻게 작성할 것인가에 중점을 두고 있으며 코드는 실제적이고 실무적일 것일 것이지만 Diffbot 자체에 지나치게 집중하진 않을 것이다. Diffbot의 API는 충분히 단순하고 Guzzle의 인터페이스는 PHP 라이브러리 없이도 사용하기 간편하다. 양질의 PHP 패키지를 개발하는데 어떻게 사용할 것인가에 대한 접근 방식은 당신의 프로젝트에서 어떻게 활용해야 할지 배울 수 있다. Diffbot이 패키지의 주제로 선택된 이유는 실제적인 예제로서 입증하는 것이지 단순히 다른 “홍길동” 패키지를 만드는 것을 의미하지 않는다.

좋은 패키지 디자인

최근 몇 년 동안, PHP 패키지 디자인을 위한 좋은 표준들이 많이 나왔다. Composer, Packagist, The league 그리고 가장 최근에 The Checklist까지 말이다. 다음 나오는 항목들을 준수한다면 The League를 제외하고는 패키지를 제출할 수 있다. (물론 여기서 작성하는 패키지는 제출하지 않기 바란다. – 우린 단지 서드 파티 API 제공자를 위해 만들었고 또한 아주 제한적인 컨텍스트만 제공하기 때문이다.) 우리가 따를 규칙은 다음과 같다:

  1. 저작권을 포함할 것
  2. 오픈소스여야 할 것
  3. 개발 관련 부분을 배포본과 분리할 것
  4. PSR-4 autoloading 을 사용할 것
  5. Composer 설치를 위해 Packagist에서 호스팅 할 것
  6. 프레임워크에 상관 없이 사용 가능할 것
  7. PSR-2 코딩 표준을 준수할 것
  8. 깊이 있는 주석을 포함할 것
  9. 유의적 버전을 사용할 것
  10. CI와 유닛 테스트를 사용할 것

이 항목들에 대해 더 자세히 알고 싶다면 다음 문서를 참고한다.

시작하기

여기서 Homestead Improved 환경을 다시 사용할 것인데 이는 가장 빠르게 통일된 환경에서 개발할 수 있도록 도와준다. 참고로 다음과 같은 가상 환경을 통해 이 튜토리얼을 진행할 예정이다:

sites:
  - map: test.app
    to: /home/vagrant/Code/diffbot_lib
  - map: test2.app
    to: /home/vagrant/Code/diffbot_test

이렇게 VM을 통해 hacking을 해보자.

바닥부터 시작하기 위해 League Skeleton을 사용한다. League의 규칙이 적용된 템플릿 패키지로 쉽게 시작하는데 도움이 된다. 원래 리포지터리에서 fork한 이 리포지터리는 원래 템플릿보다 개선된 .gitignore가 첨부되어 있고 몇가지 소소한 수정이 포함되어 있다. 만약 원하지 않는다면 원본을 사용하고 차이점은 직접 비교해보기 바란다.

git clone https://github.com/Swader/php_package_skeleton diffbot_lib

이제 composer.json을 다음과 같이 수정할 차례다:

{
  "name": "swader/diffbot_client",
  "description": "A PHP wrapper for using Diffbot's API",
  "keywords": [
    "diffbot", "api", "wrapper", "client"
  ],
  "homepage": "https://github.com/swader/diffbot_client",
  "license": "MIT",
  "authors": [
    {
      "name": "Bruno Skvorc",
      "email": "bruno@skvorc.me",
      "homepage": "http://bitfalls.com",
      "role": "Developer"
    }
  ],
  "require": {
    "php" : ">=5.5.0"
  },
  "require-dev": {
    "phpunit/phpunit" : "4.*"
  },
  "autoload": {
      "psr-4": {
          "Swader\\Diffbot\\": "src"
      }
  },
  "autoload-dev": {
      "psr-4": {
          "Swader\\Diffbot\\Test\\": "tests"
      }
  },
  "extra": {
      "branch-alias": {
          "dev-master": "1.0-dev"
      }
  }
}

우리는 일반적인 메타 데이터를 설정하고 요구 항목을 정의했고 PSR-4 autoloading을 설정했다. 이 과정이 위 목록에서 1-6번 항목에 해당한다. 여기서 Diffbot API를 호출할 수 있도록 돕는 HTTP 클라이언트 라이브러리 Guzzle을 요구 항목에 추가한다.

"require": {
  "php" : ">=5.5.0",
  "guzzlehttp/guzzle": "~5.0"
},

composer install을 실행하면 모든 의존성을 내려 받는다. 테스트를 위해 포함한 PHPUnit도 포함이 되는데 이 모든 것이 동작하는지 확인하기 위해 다음과 같이 src/SkeletonClass.php를 변경할 수 있다:

<?php
namespace Swader\Diffbot;
class SkeletonClass
{
  /**
   * Create a new Skeleton Instance
   */
  public function __consturct()
  {
  }

  /**
   * Friendly welcome
   *
   * @param string $phrase Phrase to return
   * @return string Returns the phrase passed in
   */
  public function echoPhrase($phrase)
  {
    return $phrase;
  }
}

그리고 프로젝트 최상위 경로에 index.php도 다음과 같이 추가한다:

<?php
require_once "vender/autoload.php";
$instance = new \Swader\Diffbot\SkeletonClass();
echo $instance->echoPhrase("It's working");

이제 브라우저로 test.app:8000에 접속해보면 “It’s working” 메시지를 볼 수 있다.

아직 public 디렉토리나 이와 같은 파일을 만들지 않았다고 걱정하지 말자. 패키지를 만들 때에는 중요하지 않다. 라이브러리를 만들 때에는 패키지에만 집중해야 하고 또한 프레임워크나 MVC가 아닌 패키지만 있어야 한다. 그리고 index.php를 잠깐 잠깐 테스트 용도로 사용하겠지만 대부분 PHPUnit을 통해 라이브러리를 개발할 것이다. 여기서는 index.php를 실수로 리포지터리에 보내는 일이 없도록 .gitignoreindex.php를 추가하도록 한다.

PSR-2

현대적인 표준을 따르기 위해 PSR-2를 준수해야 한다. PhpStorm을 사용한다면 엄청 쉬운 일이다. 내장되어 있는 PSR1/PSR2 표준을 선택하거나 CodeSniffer 플러그인을 설치해 PhpStorm 인스팩션으로 활성화시켜 사용할 수도 있다. 아쉽게도 예전 방법을 활용해야 하는데 PHPStorm이 아직 phpcs의 원격 실행을 지원하지 않기 때문이다. (Vagrant VM도 결국 원격 환경이므로. 만약 이 기능을 PHPStorm에 탑재하기 원한다면 여기에서 투표할 수 있다.)

어찌 되었든 CodeSniffer가 평소처럼 프로젝트에 필요하기 때문에 composer를 통해 설치하고 VM의 커맨드라인에서 구동하자:

composer global require "squizlabs/php_codesniffer=*"
phpcs src/
# 코드를 검사해 리포트를 보여준다

계획하기

지금까지 만든 틀로 본격적인 개발을 시작할 수 있다. 이제 필요한 부분을 생각해보자.

시작점

Diffbot API를 어떻게 사용하든지 사용자는 API 클라이언트의 인스턴스를 생성하길 원할 것이다. 이런 경우 미리 만들어진 API를 호출하는 것 이외에는 할 수 있는 것이 없다. 각각의 API를 사용해서 요청을 쿼리 파라미터로 보내려면 폼에서 ?token=xxxxxx와 같이 개발자 토큰이 필요하다. 단일 사용자는 하나의 토큰만 사용할 것이기 때문에 새 API 클라이언트 인스턴스를 생성할 때 토큰을 생성자에 넣어 생성해야 한다. 물론 모든 인스턴스를 생성할 때 활용하기 위해 전역 토큰으로 생성해 사용할 수도 있다. 위에서 이야기 한 두 가지 방법을 다음과 같이 표현 할 수 있다:

$token = xxxx;

// approach 1
$api1 = new Diffbot($token);
$api2 = new Diffbot($token);

// approach 2
Diffbot::setToken($token);
$api1 = new Diffbot();
$api2 = new Diffbot();

전자는 단일 API 클라이언트 인스턴스를 생성할 때 또는 여러 토큰을 사용할 때(예를 들면, 토큰 하나는 Crawlbot에 다른 하나는 일반적인 API를 사용할 때) 도움이 된다. 후자는 자신의 어플리케이션이 여러 API 엔드포인트에서 여러 차례 사용될 때 매번 토큰을 주입하는게 번거로울 때 활용할 수 있다.

위 내용을 생각하며 다음과 같이 첫 클래스를 작성할 수 있다. src/Diffbot.php를 작성한다.

<?php 
namespace Swader\Diffbot;
use Swader\Diffbot\Exceptions\DiffbotException;

/**
 * Class Diffbot
 *
 * The main class for API consumption
 *
 * @package Swader\Diffbot
 */
class Diffbot
{
  /** @var string The API access token */
  private static $token = null;

  /** @var string The instance token, settable once per new instance */
  private $instanceToken;

  /**
   * @param string|null $token The API access token, as obtained on diffbot.com/dev
   * @throws DiffbotException When no token is provided
   */
  public function __consturct($token = null)
  {
    if ($token === null) {
      if (self::$token === null) {
        $msg = 'No token provided, and none is globally set. ';
        $msg .= 'Use Diffbot::setToken, or instantiate the Diffbot class with a $token parameter.';
        throw new DiffbotException($msg);
      }
    } else {
      self::validateToken($token);
      $this->instanceToken = $token;
    }
  }

  /**
   * Sets the token for all future new instances
   * @param $token string The API access token, as obtained on diffbot.com/dev
   * @return void
   */
  public static function setToken($token)
  {
    self::validateToken($token);
    self::$token = $token;
  }

  private static function validateToken($token)
  {
    if (!is_string($token)) {
      throw new \InvalidArgumentException('Token is not a string.');
    }
    if (strlen($token) < 4) {
      throw new \InvalidArgumentException('Token "' . $token . '" is too short, and thus invalid.');
    }
    return true;
  }
}
?>

메소드에서 DiffbotException을 참조한다. src/exceptions/DiffbotException.php를 다음 내용으로 작성한다.

<?php 
namespace Swader\Diffbot\Exceptions;

/**
 * Class DiffbotException
 * @package Swader\Diffbot\Exceptions
 */
class DiffbotException extends \Exception
{

}
?>

Diffbot 클래스에 대해 간단하게 설명하면, token 정적 프로퍼티는 새 인스턴스를 생성하면서 토큰을 넣지 않았을 때 기본값으로 사용한다. 인스턴스를 생성하면서 토큰을 넣으면 instanceToken 프로퍼티로 저장한다.

생성자에서 토큰을 전달 받는지 확인한다. 만약 받지 않았다면, 미리 선언된 기본 토큰이 있는지 확인하고 만약 없다면 DiffbotException 예외를 발생하게 된다. 이 예외를 위해 위 예외 코드를 작성했다. 만약 토큰이 괜찮다면 인스턴스에 토큰이 설정된다. 반면 토큰이 전달 되었다면 instanceToken으로 저장된다. 위 두 경우 모두 validateToken 정적 메소드를 통해 검증 절차를 거치게 된다. 토큰의 길이가 3글자 이상인지 체크하는, 단순한 프라이빗 메소드로 통과하지 못하면 아규먼트 검증 실패 예외를 발생하게 된다.

마지막으로 setToken 정적 메소드로 앞에서 말한 전역 토큰으로 활용한다. 이 역시 토큰 검증 과정을 거친다.

Diffbot 토큰을 보면 API를 호출하는 상황에서 기존에 있던 token을 변경이 가능한데 이렇게 되면 기존에 존재하는 Diffbot 인스턴스는 의도와 다르게 동작할 수 있다. 이런 경우를 대비해 토큰을 인스턴스 생성할 때마다 주입을 하거나 전역적으로 주입하고 Diffbot을 사용하거나 해야 한다. 물론 토큰을 전역적으로 설정하면 인스턴스의 이 설정을 덮어 쓸 수 있다. 물론 전역 토큰도 수정 가능하기 때문에 여러가지 환경에 따라 인스턴스의 토큰이 변경되도록, 이미 존재하는 인스턴스에는 영향을 주진 않을 것이다.

이 모든 내용이 블럭 주석으로 문서화 된 것을 볼 수 있는데 과하게 문서화 할 필요는 없지만 모두가 이해할 수 있도록 간단하게 작성을 해야 한다.

결론

이 파트에서 몇가지 간단한 기능과 환경설정이 들어 있는 스켈레톤 프로젝트로 PHP 패키지 개발을 시작했다. 파트 1에서의 결과는 다음 링크에서 받을 수 있다. 파트 2는 테스트와 실질적인 기능들을 작성하고 기초적인 TDD를 할 예정이다.

반년 만에 블로그 테마를 변경했다. 고해상도 디바이스가 많아져서 그런지 요즘 대부분의 블로그 테마들이 큰 서체 사이즈와 넓은 레이아웃으로 많이 나오고 있다. 반년 정도 사용한 hamingway 테마로 변경했을 때에도 비슷한 테마를 여럿 적용해봤는데 그나마 한국어 컨텐츠가 괜찮은 가독성으로 보여 hamingway 테마를 선택했었다.

이 테마를 오래 사용하다보니 불편한 점도 있었다. 대다수의 테마에서 공통적으로 느껴지는 부분인데 스크롤을 내려가며 컨텐츠를 읽다보면 sidebar가 있던 공간이 계속 공백으로 남아있기 때문에 균형감 없는 레이아웃으로 글을 읽게 된다. 또한 영어로 작성된 컨텐츠는 모든 브라우저에서 단어를 분리해 행 전환이 되는 단어 분리(word-break)가 발생하지 않지만 아직까지 CJK언어권의 단어 분리 옵션은 일부 브라우저만 지원한다.1 이런 상황과 맞물려 좁은 컬럼과 큰 서체의 사용은 한국어 문서의 가독성을 많이 떨어뜨리게 된다.

WordPress haruair theme

이번 테마는 roots.io의 Sage를 기반 테마로 사용해서 레이아웃, 서체, 행간과 자간 등을 변경해서 만들었다. 이 기반 테마는 bootstrap으로 구성되어 있는데 dist 되어있는 minified css를 활용하는 것이 아니라 bower로 전체 코드를 받아와 less를 직접 사용할 수 있는 장점이 있다. 테마의 구조가 직관적인 편이고 gulp를 이용한 빌드 및 watch 설정이 이미 다 되어 있기 때문에 기존에 있던 많은 starter theme과는 다르게 번거로운 작업이 필요하지 않았다.

  • one column으로 강제되어 있지만 2-column으로도 사용 가능
  • 영문은 ubuntu, 국문은 나눔바른고딕 기본으로 사용
  • 기본 서체의 크기를 키우고 행간과 자간을 한국어에 맞게 조절
  • 포스트 제목 아래에 headline을 삽입할 수 있도록 custom field 추가
  • 포스트 하단에 author box 추가
  • 테블릿 이하 해상도에서 서체 크기 조정

Ubuntu는 웹폰트로 추가되어 있는 반면 나눔고딕은 그렇지 않다. 나눔바른고딕은 웹폰트로 사용하기에 아직 무거운 느낌이고 기본 서체를 사용해도 그렇게 못봐주는 느낌은 아니라서 해당 폰트가 설치되어 있을 때만 나오고 그 외에는 애플고딕이나 바른고딕으로 출력된다.

아직 어색한 부분이나 변경해야 하는 부분이 많이 있지만 차차 수정할 생각으로 일단 적용했다. 해당 테마는 GitHub에서 받을 수 있으며 테마를 설치할 때에도 의존성 설치 및 빌드 과정이 요구되어 bower, npm 등을 구동할 수 있어야 한다. 로컬에서 작업한 후 gulp build로 모든 파일을 컴파일해서 올리는 방법도 가능하다. 자세한 설치 방법은 Sage README에서 확인할 수 있다.

  • Firefox는 CJK 언어를 위해 word-break: keep-all 을 지원하며 IE도 비슷한 방식으로 단어 분리를 방지할 수 있다. 
  • haruair.com 블로그 All time views 10만 히트를 달성했다. 사실 10만 히트를 기념한다는 생각을 한번도 해보지 못했었는데 100,000히트 돌파를 읽고나서 통계를 보다가 알게 되었다. 큰 뜻을 품고 만든 블로그가 아니기에 통계 수치에 연연하고 있진 않지만 그래도 소소하게 시작한 블로그에 조회수가 많아지고 있다는 사실에 누군가에게는 도움이 되고 있는 것 같아 기분이 좋다. 그래서 내 블로그에 관한 작은 포스트를 기념 삼아 남긴다.

    Jetpack 통계

    2011년 5월 첫 포스트를 시작으로 이 블로그가 운영되기 시작했다. 워드프레스 통계를 제공하는 플러그인 jetpack은 2012년 11월에 설치했으니 처음부터 설치한 Google Analytics 와는 5,000여 뷰 정도 차이가 난다. 개설 만 4년을 앞두고 10만 뷰에 도달했다. 한국어 컨텐츠가 절대적이기 때문에 한국에서 유입이 높은 편이고 대부분 Google 검색을 통해 들어온다. 국내 포털에서의 유입도 있는 편인데 검색 키워드가 제목과 정확하게 맞는 경우에만 검색이 되는 것 같다. 내 블로그 대부분의 컨텐츠가 광범위한 범위를 포용하는 글보다 특정적인 상황에 촛점이 있는 글이 많아서 그런지 사이트 방문 증가율이 선형으로 증가하고 있다.

    GA 통계

    매년 세우는 목표에 블로그 꾸준하게 포스팅하기가 늘 들어가는데 글을 쓰는 속도가 빠르지 않고 주절주절 쓸 때가 많아 다듬다보면 한 달에 2건 많아야 4건 정도 작성하게 되는 것 같다. 블로그에서 공유하는 이야기보다 더 많은 일들이 일어나고 겪고 있는데 모두 공유하지 못해서 아쉬움이 늘 있다. 그래도 이상한모임 팀블로그를 하게 된 이후, 돌아보는 블로그도 늘었고 그 덕분에 영향을 주고 받아 작성하게 되는 포스트도 많아졌다. 최근에는 이상한글쓰기로 같은 주제 글쓰기를 하고 있는데 “함께 하는 힘”을 무시할 수가 없다는걸 이상한모임을 통해 늘 느끼고 있다.

    가끔 바이럴을 타서 급격하게 뷰가 늘었던 경험도 있지만 아쉽게도 호스팅에서 트래픽 초과 대응이 좋은 편이 아니라서 물 들어올 때 노를 젓지 못했다. 그래도 오랫동안 저렴한 비용에 사용할 수 있어 계속 사용하다가 너무 불편해서 최근에 DigitalOcean으로 이전했다.

    Jetpack 조회 순위

    현재 작성해서 퍼블리싱한 글은 총 166건이다. 예전에 쓴 글을 누가봐도 오글거릴 정도지만 이젠 예전 글을 삭제하는 우를 범하지 않으려고 노력하고 있다. 서비스형 (유사) 블로그를 사용하다보면 작은 사건으로 우발적으로 탈퇴하는 경우가 있는데 몇 번 그런 일을 저지른 탓에 내 역사(물론 흑역사)가 순식간에 없어지고 말았다. 디지털 컨텐츠는 아날로그 시절보다 복제나 관리가 용이하지만 그만큼 쉽게 자료 손실이 발생할 우려가 있어서 아쉽다.

    이 블로그의 주요 컨텐츠는 내가 경험하는 사소한 부분들에 대한 이야기다. 정말 작은 부분의 설정값을 변경한 글도 작성해두니 많은 분들이 보고 도움을 받았다고 고맙다는 피드백을 받는 경우도 많았다. 고맙다는 피드백은 늘 고맙다. 올해에도 더 사소한 이야기를 더 자세하게, 많이 기록하려고 노력하고 있다.

    종종 번역도 했다. 영어/한국어 실력이 그렇게 좋지 않아 매끄럽게 번역하진 못해서 큰 도움이 되진 못해도 구글 번역기보다 자연스럽게 작성할려고 노력을 많이 했다. 누가 와서 이것도 번역이라고 작성했냐 얘기해도 사실 할 말이 없긴 하다. 앞으로도 꾸준히 해보고 싶은 영역인데 번역 자체보다 언어적인 능력을 키우는데 더 우선을 둬야겠다고 생각한다.

    블로그 첫 글 안녕하세요에서 이야기한 것과 같이 삶에서의 배움에 더 적극적으로 참여하는 마음으로, 앞으로도 꾸준히 블로그를 작성하도록 노력해야겠다.

    방문해주신 분들께 감사의 말씀도 전합니다. 🙂


    순위글 다시 보기

    이상한모임 과제로 각자의 작업 환경에 대해 쓰기로 해 작성하는 포스트다. 회사와 집의 환경과 작업 환경에 대해 간단하게 적었다. 과제 덕분에 오랜만에 방청소도 하고 아주 유익한 이상한모임이다.

    사무실

    회사에서 2년 넘게 사용하고 있는 환경이다. 중간에 이사를 갔지만 같은 건물이라 크게 다르지 않다. (사무실 배치는 아주 마음에 들지 않게 변경되서 슬픔.)

    옆에 있는 원숭이는 모자다. mailchimp에서 보내준 물건들인데 스티커도 한움큼, 인형에, 모자에 참 풍성하게 보내줘서 고마웠다. 물을 자주 마시는 편인데 깡통 보틀은 all above human 컨퍼런스에서 받아 잘 쓰고 있고 jiman님이 선물해주신 작은 텀블러는 따뜻한 물을 마실 때 쓰고 있다. 이것저것 메모를 많이 하는 편이라 늘 노트가 있다. 멜번에서 사용하는 교통카드인 myki는 상당히 얇은 편이라 주머니에 넣고 다니면 꺾어질 것 같아서 애플스토어 카드를 같이 넣어서 들고 다닌다.

    오른쪽 위 간트차트는 한참 전에 끝난 프로젝트인데 벽이 허전해서 그냥 붙여뒀다. 기계식 키보드를 사무실에 두고 사용했었는데 요즘 집에서 공부할 때 사용하려고 집으로 들고 왔다. 아이폰은 늘 충전하고 있고 구형 애플 이어폰으로 노래도 듣고 그런다. 바탕화면은 스냅샷, 스프라잇 이미지, 짤방, 합성 등 각종 이미지가 널부러져 있는데 화면에 꽉 차면 그냥 전체 선택해서 지운다.

    집

    이것저것 잡다하게 널부러져 있었는데 다 치우고 찍었다. 여기도 크게 특별하지는 않다. 호주 오면서부터 맥북 에어를 쓰고 있는데 가볍고 대부분의 작업을 무리 없이 소화할 수 있었다. 다만 구입한 이후 계속 투덜투덜 대던 부분이 바로 디스플레이였다. 그냥 일반적으로 사용할 때에는 별 느낌이 들지 않는데 색상을 봐야 하는 작업이 있을 때 문제가 컸다. 처음에는 그냥 기분 탓인 줄 알았는데 맥북 에어 디스플레이가 sRGB 절반 정도도 커버하지 못한다는 얘기를 듣게 되었다. 기분이 아니라 실제로 그랬다는 사실을 알게 된 후 바꿔야겠다는 생각을 계속 하다 아이맥을 구입하게 되었다.

    한국 다녀오기 전까지만 해도 회사 일에 약간 번아웃 된 상태라 집에 오면 코드를 거의 보질 않았었다. Street Photography에 관심이 많아져서 한동안 집에서 사진첩 보고, 사진 편집하고, 다큐멘터리를 찾아보는 등의 일을 많이 했다. 사진도 컴퓨터를 해온 만큼 오랜 기간 했는데 최근엔 조금 심각하게 생각해보고 있다. 한 4~5개월은 디지털과 필름을 병행하다가 이제 완전히 필름으로 넘어와서 대부분의 사진을 필름으로 촬영하고 있다. 현상은 filmneverdie에 맡기고 스캔은 직접 하고 있다. 사진 좌측에 보이는 검은 장비가 필름 스캐너(EPSON V600)이다. BUY FILM 스티커는 Japan Camera Hunter에서 필름케이스 구입할 때 받았다. 오른쪽 물컵 뒤에 있는 외장 하드에 사진을 보관하고 있다. 하드는 늘 불안해서 사진을 어떻게 안전하게 보관할까 늘 고민했는데 필름으로 옮기고 나서는 그런 고민이 없어졌다. 노란 노트 아래에 있는 사진첩은 Martin Parr의 The last resort이다.

    키보드는 레오폴드 FC700RT다. 맥북 에어를 좀 멀찌감치 두고 쓰려고 제작년에 한국 다녀올 때 구입했다. 의도하진 않았지만 윈도우 키보드 레이아웃이라 가상 환경 윈도우를 사용할 때 편하다. 매직패드도 있는데 포토샵 작업할 때 영 불편해서 마우스를 쓰고 있다. 클립보드를 마우스패드처럼 쓰고 있다. 메모하기 쉽고 다 쓰면 새 종이로 교체하기 편리하다. 폰은 늘 충전하고 있다. 완전 충전하고 방전하면 베터리 수명이 줄어든다는 사실을 최근에야 알았다.

    에어는 자기 전에 잠깐 글 쓸 때나 트위터나 슬랙할 때 사용하고 있다. 책상에 앉아서 둘 다 열고 작업해본 적은 한번도 없는 것 같다. 최근엔 들고 나갈 일도 별로 없고 그래서 평소에는 키보드 받침으로 자주 사용되고 있다.

    작업환경

    내가 하는 일이 a little bit of everything이기 때문에 그때그때 환경이 다른 편이다. 그래서 터미널 환경 + Sublime Text를 엄청 많이 사용하는 편이다. (Sublime Text도 호주 시드니 소재 회사가 만들고 있다.) Vim도 쓰지만 복붙도 잘 못해서 마우스 쓰는 라이트 유저다.

    최근에는 C# 코드를 많이 읽고 있어서 Parallels로 windows 8.1, VS2013을 사용하고 있다. Xamarin도 가끔 쓰고 있다. 빠르게 내용 찾고 코드 읽고 할 때는 여전히 Sublime Text를 사용한다. (회사에서는 vmfusion을 사용하고 있지만 Parallels를 추천하는 분들이 많아서 구입했는데 둘을 비교할 때 vmfusion이 훨씬 안정적인 느낌이다. 만약 구입할 예정이라면 vmfusion을 추천.)

    Adobe CC로 Photoshop, Lightroom을 사용한다. Photoshop은 오래 사용해서 다른 프로그램으로 대체를 하질 못하고 있다. 그 탓에 Lightroom도 좀 쓰다가 불편해서 Photoshop을 켜는 경우가 많다.

    문서 작성은 sublime text를 자주 쓰고 최근에는 typed를 사용한다. typed로는 음악만 켜고 다른 작업하는 경우도 많다.


    사실을 나열하는 수준의 글이 되어 버려서 아쉬운 느낌에 하나 더 적어보자면 집이든 회사든 모든 작업 공간에서 동일한 환경을 구축하는건 확실히 중요하다. 마크 주커버그나 스티브 잡스가 사소한 결정에 스트레스 받지 않기 위해 모든 삶의 패턴을 단순화 하는데 신경을 쓴다는 이야기와 비슷한 맥락인데 환경적 변화를 최소화 하는 과정을 통해 환경을 전환하는 시간을 줄이고 더 집중할 수 있는 환경을 만들 수 있는 것 같다.

    최근엔 다양한 가상 환경의 도움을 받아 쉽게 개발 환경을 동일하게 구축할 수 있다고 하는데 더 살펴봐야겠다는 생각이 든다.


    이상한모임에서 진행하는, 다양한 주제로 함께 글을 쓰는 글쓰기 소모임입니다. 함께 하고 싶다면 http://weirdmeetup.herokuapp.com 에서 가입하시고 #weird-writing 채널로 오세요!

    요즘 Microsoft Virtual Academy 를 통해 제공되는 여러 강의를 듣고 있다. 모든 강의가 영어로 제공되어 있어 아쉽긴 하지만 우린 직접 하는 그림(?)을 보고 따라 할 수 있으니까 만약 관심이 있다면 살펴보는 것도 좋겠다.

    C#을 가장 처음 접한 때는 @justinchronicle님이 운영한 .Net MVC Web Frameworks 스터디 였는데 그 경험으로 회사에서도 C#으로 프로젝트를 진행해보는 등 많은 도움이 되었다. 스터디가 프레임워크 위주라서 C# 자체에 대해 너무 피상적으로만 알고 있다는 생각이 들었던 터라 요 얼마간은 제대로 공부해야겠다 마음 먹고 MVA에서 C# 관련 강의를 보고 있다.

    C# 개발을 하면서 Visual Studio를 사용해왔긴 했지만 너무 기본적인 기능만 활용하고 있다는 생각이 들어 MVA에 올라온 강의 중 What’s New In Visual Studio 2013 in JumpStart를 잠깐 보게 되었는데 유용한 기능들이 많아 간단하게 정리했다.

    VS 테마 변경하기

    개발 도구를 사용하다보면 생산성을 높이기 위해서(가독성이나… 기분을 전환하거나ㅎ) 테마를 변경하게 되는 경우가 종종 있다. Visual Studio에서도 Color Theme을 변경할 수 있는 기능이 있다.

    Tools > Options 에서 Environment 섹션을 클릭하면 Color Theme을 선택할 수 있는 옵션이 있다. 기본적으로 제공되는 테마는 Black, White, Blue 세가지인데 Visual Studio를 설치하는 과정에서 선택하게 되어 있기 때문에 직접 변경하게 되는 일은 거의 없다.

    이 외에 새로운 테마를 사용하고 싶다면 Visual Studio Gallery에서 제공하는 Visual Studio 2013 Color Theme Editor를 활용할 수 있다. 해당 확장을 설치하면 기본적으로 추가적인 테마가 제공되며 또 자신의 취향에 맞는 테마를 쉽게 만들어 낼 수 있다.

    다음과 같이 추가된 테마를 확인할 수 있다.

    Color Theme Options

    Solarized (Dark)를 적용했다.

    Theme Changed

    행 번호 표시하기

    이미 많은 분들이 켜서 사용하고 있는 옵션인데 Tools > Options > Text Editor 에서 활성화 하고 싶은 언어의 General 섹션을 클릭하면 Line Numbers 옵션이 있다.

    스크롤바 맵모드 사용하기

    Sublime Text에서 제공되는 것과 같은 스크롤바 맵모드를 활용할 수 있다. Tools > Options > Text Editor 에서 활성화 하고 싶은 언어의 Scroll Bars 섹션을 클릭하면 Behavior에서 스크롤 모드를 변경할 수 있다. 여기서 map 모드로 변경하고 적용하면 맵모드를 확인할 수 있다.

    Scroll Map Mode Options

    활성화 된 스크롤맵에 마우스 커서를 올리면 코드를 바로 확인할 수 있는 Preview Tooltip 도 지원한다.

    주석 켜고 끄기

    해당 코드를 주석으로 바꾸고 싶으면 영역을 선택하고 Ctrl + K, Ctrl + C 로 주석을 달 수 있다. 반대로 주석을 없에고 싶으면 Ctrl + K, Ctrl + U.

    문서 포메팅하기, 들여쓰기 자동 지정하기

    VS는 코드 작성할 때 기본적으로 설정된 코딩 컨벤션에 맞게 잘 동작하지만 가끔 애매하게 제대로 되지 않을 때가 있다. 그럴 때 Format Document를 사용할 수 있다. 단축키는 Ctrl + K, Ctrl + D. 문서 전체가 아닌 선택된 영역만 하고 싶다면 Ctrl + K, Ctrl + F.

    Format Document

    현재 행을 다른 행으로 이동하기

    코드를 작성하다가 코드의 위치를 옮기고 싶다면 복사 붙여넣기를 해도 되지만 간단하게 Alt + 위, 아래 단축키를 사용할 수 있다. 여러 행을 선택하면 한번에 이동도 가능하다.

    Peek Definition

    C#은 여러 클래스가 많은 파일에 산재되어 있어 직접 작성한 코드라도 해당 위치를 찾을 때 불편한 경우가 종종 있다. 이럴 때 Peek Definition을 활용할 수 있다. 현재 작성된 메소드나 인스턴스, 클래스에서 Alt + F12를 누르면 작은 창으로 해당 코드를 바로 열어볼 수 있다.

    Pick Definition

    열린 작은 창 안에서도 해당 단축키로 계속 탐색이 가능하고 그 자리에서 바로 코드를 수정 및 저장하는 것도 가능하다. 창을 닫으려면 ESC를 누르면 된다.

    이전에 복사한 내용 붙여넣기

    내용을 복사해 붙여넣는 도중에 다른 내용을 복사하면 이전에 가지고 있던 내용을 잃어버리게 된다. 만약 그 이전에 있던 내용을 붙여넣고 싶다면 Ctrl + Shift + V 를 반복해서 입력하면 된다.


    Visual Studio는 알아가면 알수록 강력한 기능이 많아 사용하는 재미가 있는 도구인 것 같다. 조만간 나올 VS 2015도 기대되고, 더욱 자유자재로 쓸 수 있도록 부지런히 공부해야겠다.

    마이크로소프트에서 제공하는 IDE인 Visual Studio는 다양한 언어과 강력한 기능을 제공하고 있다. 이 IDE는 상황에 맞게 구입해서 사용할 수 있도록 다양한 버전으로 제공되고 있었는데 예전부터 Visual Studio Express 라는 이름으로 기능이 다소 제한된 무료 버전을 제공하고 있었다. (DreamSpark를 통해서 사용 할 수 있던 버전이 바로 이 버전.)

    가장 최근 Express 버전인 Visual Studio 2013 Express도 각 타겟 플랫폼에 따라 for Web, for Windows, for Windows Desktop로 분류해 제공해왔는데, 2014년 11월, 대부분의 제약 사항이 없어진 Visual Studio 2013 Community가 공개되었다.

    • Express 버전에서 제한 되었던 IDE 확장 기능을 Visual Studio Gallery를 통해 사용할 수 있음
    • 크로스 플랫폼 지원
    • 교육용 및 개인 개발자 상용으로 사용 가능
    • 기업도 PC 250대 이상 또는 연매출 미화 1백만 달러 이상이 아닌 경우 5명까지 사용 가능

    이 버전의 VS는 Visual Studio 2013 Community 안내 페이지에서 받을 수 있다.

    요즘은 생산성 좋은 IDE도 많이 생겨서 선택의 폭이 많이 넓어졌긴 했지만 그래도 VS의 강력하고 안정적인 기능들은 언제 봐도 든든한 기분이 든다. C#, VB 외에도 PHP, JavaScript 등 다양한 언어에 대한 지원도 많아졌고 npm, bower, composer 등을 편리하게 사용할 수 있는 확장도 있어 새로운 개발도구를 찾고 있는 윈도 사용자라면 사용해보는 것도 좋겠다.

    윈도 환경의 개발 커뮤니티도 하루가 다르게 변화하고 있고(MS에서 github에 코드를 공개해놓고 작업한다던가) 게다가 Windows 10와 VS2015 릴리즈가 올해 예정되어 있어 예전에 비해 체감하게 되는 온도가 많이 다른 것 같다. 더 재미있는 도구들이 많이 나왔으면 하는 기대감이 든다.

    워드프레스에서 유지보수를 위해 사이트를 일시적으로 차단할 경우가 있다면 유지보수 모드(Maintenance mode)를 활용할 수 있다.

    사용자로서 워드프레스를 이용하게 될 때에는 이 모드를 보게 되는 일이 거의 없다. 만약 보게 된다면 워드프레스 플러그인, 테마, 코어를 업데이트 하는 도중에 사이트에 접속하게 되는 경우다. 설치 과정을 눈여겨 본 사용자라면 유지보수 모드를 켜고 설치 과정이 진행된 후 완료 되면 다시 유지보수 모드가 해제되는 것을 확인할 수 있다.

    만약 업데이트 중에 페이지를 벗어나게 된다면 유지보수 모드가 해제되지 않아 사이트가 닫힌 상태로 유지된다. 이럴 때에는 직접 유지보수 모드를 직접 해제해야 한다.

    maintenance mode

    워드프레스 웹사이트에서 다음과 같은 화면을 본다면 유지보수 모드가 켜져있는 상태다.

    유지보수 모드 켜고 끄기

    유지보수 모드는 워드프레스 최상위 폴더에 .maintenance라는 이름으로 빈 텍스트 파일을 생성하면 활성화 된다. 유지보수 모드를 끄려면 이 파일을 지우면 된다.

    .Maintenance file

    유지보수 페이지 변경하기

    유지보수 페이지를 좀 더 친절하게 변경하고 싶다면 wp-content/maintenance.php 파일을 만들어 해당 내용을 작성하면 된다. 기본적으로 출력되는 유지보수 페이지는 503 Service Unavailable 를 반환한다는 사실을 참고하자.

    <?php
      $protocol = $_SERVER["SERVER_PROTOCOL"];
      if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
        $protocol = 'HTTP/1.0';
      header( "$protocol 503 Service Unavailable", true, 503 );
      header( 'Content-Type: text/html; charset=utf-8' );
      header( 'Retry-After: 600' );
    ?>
    <!DOCTYPE html>
    <html lang="ko">
    <head>
      <meta charset="utf-8">
      <title>Haruair.com 점검중</title>
    </head>
    <body>
      <h1>현재 웹사이트 점검중입니다. 잠시 후에 다시 접속해주시기 바랍니다.</h1>
    </body>
    </html>
    

    HTML5에서 추가된 Geolocation API는 웹 브라우저에서 사용자 위치를 찾을 수 있도록 도와주는 API다. 이 API를 기반으로 웹앱을 만들거나 웹사이트에서 기능을 구현하면 임의의 경도, 위도로 변경해 테스트를 해야 하는 경우가 있는데 Google Chrome 개발자 도구에서 이 Geolocation 위치를 변경하는 기능을 지원한다.

    개발자 도구에서 스마트폰 모양 아이콘을 클릭해 emulation 모드를 활성화 한 후, 하단 emulation 탭에서 좌측 Sensors 항목을 클릭하면 Emulate geolocation coordinates 항목을 확인할 수 있다.

    emulate geolcation coordinates

    좌표를 입력하면 API에서의 좌표가 변경된 것을 볼 수 있다.

    geolocation result

    웹사이트 설정

    웹페이지 색상을 선택하세요

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