파이썬 3 설치 안하고 docker/django 프로젝트 생성하기


로컬환경에서 pvevn, vevn 설치 없이 장고프로젝트 시작하기!

requirements.txt 생성

Docker `python:${version}` 사용해서 장고가 설정된 기본 requirements.txt 생성하기

$ docker pull python:3.6

$ docker run --rm -v "${PWD}":/tmp -it python:3.6 /bin/bash

$ pip install django

$ pip freeze > requirements.txt

Dockerfile 생성

FROM python:3.6

ENV PYTHONUNBUFFERED 1

RUN mkdir /opt/example

WORKDIR /opt/example

COPY requirements.txt requirements.txt

RUN pip install -r requirements.txt

실행

$ docker build -t ${image_name} .

$ docker run --rm -p 8000:8000 -v "${PWD}":/opt/example -it ${image_name} /bin/bash
  
$ ./manage.py migrate

$ ./manage.py runserver 0:8000

컴퓨터 언어를 영어로 설정해보기

영한 사전과 번역기가 없으면 영어를 읽고 쓰기가 거의 불가능한 제가 사용하는 모든 프로그램의 언어를 영어로 설정하고 느낀 장점과 단점에 대해서 얘기 해보겠습니다.

영어로 설정한 이유

2012년은 장학금으로 맥북을 처음 구매하고 개발을 시작한 해입니다. 요즘에는 많은 사람들이 알고 사용하는 맥북이지만 당시에는 정보가 많이 부족했습니다.

맥용 프로그램은 대부분 영어였고 한영전환/capslock도 없었습니다. 구글에 개발과 사용하는 맥과 프로그램 관련 정보를 한글로 검색하면 티스토리와 일부 네이버 블로그 정도가 나오고 정보도 많지 않았습니다. 물론 구글링을 잘 못한 이유도 있었겠지만 영어로 검색할 경우 이해하는데 시간은 오래 걸렸지만 검색결과의 양은 많았습니다.

개발언어와 프로그래밍 관련 정보는 영어로 된 결과도 쉽게 이해하고 적용 가능하였지만 맥 혹은 프로그램은 달랐습니다. 한글로 설정되어 있는 맥 혹은 프로그램은 어디에 메뉴가 있고 어떻게 그 메뉴로 가야하는지 두번 해석해야하는 문제가 있었습니다. 그래서 맥과 프로그램은 한글이 지원되어도 언어를 영어로 설정하게 되었습니다.

영어로 설정 장점

모든 언어를 영어로 설정하면 큰 장점은 문제 해결을 위해서 검색하면 많은 정보를 얻을 수 있습니다. 영어가 세계 공용어로 사용되기 때문에 많은 문서와 질문, 답변 등이 있습니다. 또한 문제에 대해서 검색시 해결 과정에 어려움이 적습니다.

최근에는 한글로된 문서와 질 좋은 질문, 답변, 글 등이 많지만 아직은 부족하다고 생각합니다. 공식 문서는 오래되어 업데이트 안된 경우도 있고 중간중간 누락된 문서가 있는 경우가 있습니다. 번역된 메뉴의 의미 전달이 잘 안되는 경우가 있고 다른 사람과 커뮤니케이션시 용어를 혼재해서 사용하면 혼돈을 주는 경우가 있습니다.

영어로 설정 단점

저의 경우에는 적응하는데 시간이 오래걸리고 처음 보는 상황 등에 대체하는데 어려웠습니다. 한글로 설명된 경우 쉽게 이해하지만 영어로 설정된 경우 이해하는데 시간이 소요됩니다.

영어가 기본 값이면 일부 서비스 혹은 앱에서 미국, 글로벌로 설정되어 한국 서비스로 수동 설정해야 하거나 특정 기능을 사용, 접근할 수 없는 경우가 있습니다. 글로벌 기능이 애매하게 반영된 한국 서비스 혹은 앱 등에서 특히 많이 발생했던 것 같습니다.

마치며

원서를 해석하며 읽기와 배경지식이 적은 번역가의 번역본을 읽을 것인가에 대해서 다룬 글을 보기 전까지는 무조건 영어로 설정하는 것이 좋다고 생각했었습니다. 번역가가 잘못 번역한 내용보다 자신이 원서를 읽고 잘못 이해하는게 더 클 수도 있다는 내용이였습니다.

절주일기 – 월요일

어제 저녁에 반주를 한 것을 반성하고있습니다. 퇴근할 때 쯤이면 상당히 피곤합니다. 집에 가면 바로 잠들 수 있을 것 같지만 집에 도착하면 졸린 감은 있지만 잠은 오지 않습니다. 누워서 영상조금 보다가 키보드를 잡았습니다. 오늘 하이트진로가 +7.6% 올랐습니다. 가격이 떨어지길 기원하는 안티가 되어버렸습니다.

트위터 이야기

트위터에 부정적인 글을 쓰다가 지우길 여러번 하면서 부정적이고 비판적인 분위기에 물들어 가는 것을 느꼈습니다. 앞에서 못하는 말 뒤에서 하지 말자는 성격이 변하는 것을 경계해야 겠습니다.

대부분의 사람이 그러지 않을 것이고 제가 보는 사람이 그리 많지 않지만 어쩌다 건너 건너 사람의 글들을 볼때면 광기가 느껴질 때가 있습니다. 마음속 응어리들을 익명의 사람들과 공유해서 거대한 먹구름을 만들었다는 느낌을 받습니다. 다수가 공통적으로 느끼는 문제들에 익명의 사람이 조금씩 외곡된 사실과 오류를 교묘하게 섞어 이것 또한 다수가 느끼는 사회적인 문제다! 라고 말하는 느낌을 줍니다. 일부 사람이 문제라고는 하지만 다른 커뮤니티, 그룹도 비슷한 문제가 있을때 트위터는 특유의 소속감으로 뭉치는 느낌도 있습니다. 바꿔야 한다기 보다는 이렇게 생각합니다.

지하철 화장실은 더럽고 냄새나고, 불편하고 휴지가 없을 수도 있고 시끄럽고 많은 문제가 있지만 지하철 화장실 만큼 급하게 볼일 보기 좋은 곳이 없다.

일에서 질문과 답변

저는 답보다 방법을 알려주고 싶습니다. 업무 중 질문을 많이 받을 때 왜 안되는지, 아무것도 안알려주고 안된다는 질문을 많이 합니다. 답이 바로 보일 경우도 있고 질문조차 알 수 없는 경우가 있습니다. 해결하는 방법이나 키워드를 주면 직접 문제를 해결하고 이를 바탕을 다시 질문하거나 다음 순서로 넘어가는 것이 이상적이라고 생각했지만 잘 되지 않습니다. 질문을 받아주는 사수/선임의 경험도 적고 어느 순간부터 답변하는 사람이 되어 이해를 못하는 부분이 많은 것 같습니다. 어떻게 해야하는지 고민이 많습니다.

P.S 오늘 저녁은 한식뷔폐(6000원)에서 먹었는데 쌀밥을 많이 먹어서 그런지 특히 노근노근 했습니다. 절주기간동안 잘 활용해야겠습니다.
ㄴ 보통 술을 먹을때 안주를 적게 먹습니다. 한점에 한잔?

PhantomJS Screen Capture PDF 여러장 프린트

PhantomJS(팬텀제이)에서 PDF로 Screen capture를 하면 단일 페이지로 출력이 됩니다. 하지만 CSS를 이용해 mutli page/다중페이지로 출력할 수 있습니다.

// capture_a4.js
page.paperSize = {
    format: 'A4',
    orientation: 'portrait'
};
page.open('capture_a4.html', function() {
    page.render('capture_a4_output.pdf');
    phantom.exit();
});
<!-- capture_a4.html -->
<style>
    body {
        background-color: rgba(0, 0, 0, .3);
        padding: 0px;
        margin: 0px;
    }
    @media print {
        body {
            // background색 프린트
            -webkit-print-color-adjust: exact;
        }
        .page {
            page-break-after: always;
        }
    }
    #page-1 {
        background: rgba(255, 0, 0, .4);
    }
    #page-2 {
        background-color: rgba(255, 255, 0, .4);
    }
    #page-3 {
        background-color: rgba(0, 0, 255, .4);
    }
</style>

<div id="page-1" class="page">페이지 1</div>
<div id="page-2" class="page">페이지 2</div>
<div id="page-3" class="page">페이지 3</div>

출력물

실패 이야기 – MVVM Pattern in Android

안드로이드를 하면서 새로운 도전중 관심이 생긴 MVVM과 같은 패턴에도 신경을 쓰기 시작했다. 마침 좋은 안드로이드 지원 라이브러리, Plugin이 있어서 적용하였지만 생각보다 별로인 부분이 상당히 있었다.

처음 시작할 때는 AndroidAnnotation을 이용하였고 View Inject에 많은 도움을 받았지만 ANT부분에 상당한 자원이 소모되는지 빌드시간이 너무 길고, 중간중간 빌드를 통해 Activity_.class와 같이 _클래스를 생성해줘야해서 불편했다.`

그다음 선택한 방식은 디자인 패턴을 알아보다가 알게된 Android Data Binding이다. Gradle Plugin을 이용한 백그라운드로 알아서 Bind가능한 클레스를 만들어주고, 최근(??)기술이라 빌드속도에도 문제가 적었다. 또한 View Binding으로 XML에서 로직을 다룰 수 있다는 점에서 맘에 들었다. 하지만 Pure한 뷰가 아니라 유지보수가 힘들고????? 먼가 깔끔하지 않았다.

Binding Adapter를 남용하는 느낌이 들었을때 그냥 맘에 안들게 되었고, 본격적으로 Kotlin을 시작하게되면서 사용하지 않게되었다. Kotlin에 Data Binding라이브러리가 충돌?나면서 안쓰게 되었습니다.

Binding Adapter이지만 남용한 느낌이 물씬드는 코드들이다.

1. TextView

Html Text Setting

@BindingAdapter({"app:html"})
public static void setTextHtml(TextView textHtml, String html) {
    Spannable spannable = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        spannable = (Spannable) Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
    } else {
        spannable = (Spannable) Html.fromHtml(html);
    }
    textHtml.setText(spannable, TextView.BufferType.SPANNABLE);
}
// viewDataBinding.setTextHtml(“underline”);

2. RecyclerView

Set adapter

@BindingAdapter({"app:adapter"})
public static void setAdapter(RecyclerView recyclerView, RecyclerView.Adapter adapter) {
    recyclerView.setAdapter(adapter);
}

Set Layout Manager

@BindingAdapter({"app:layoutManager"})
public static void setLayoutManager(RecyclerView recyclerView, int spanCount) {
    switch (spanCount) {
        case 0 :
            recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
            break;
        default:
            recyclerView.setLayoutManager(new GridLayoutManager(recyclerView.getContext(), spanCount));
    }
}

3. EditText

Two way binding

@BindingAdapter(value = {"app:text"})
  public static void setText(EditText editText, ObservableString observableString) {
      editText.addTextChangedListener(new TextWatcher() {
          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {

          }

          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {
              observableString.set(s.toString());

          }

          @Override
          public void afterTextChanged(Editable s) {

          }
      });

      String newValue = observableString.get();
      if (!editText.getText().toString().equals(newValue)) {
          editText.setText(newValue);
      }
  }

4. ViewPager

Set adapter

@BindingAdapter({"app:adapter"})
public static void setAdapter(ViewPager viewPager, PagerAdapter adapter) {
    viewPager.setAdapter(adapter);
}

Set onPageChangeListener

@BindingAdapter({"app:onPageChange"})
public static void addOnPageChangeListener(ViewPager viewPager, ViewPager.OnPageChangeListener listener) {
    viewPager.addOnPageChangeListener(listener);
}

Node self number example

What is self-number

설명

A self number, Colombian number or Devlali number is an integer that cannot be written as the sum of any other integer n and the individual digits of n. This property is specific to the base used to represent the integers. 20 is a self number (in base 10), because no such combination can be found (all n < 15 give a result < 20; all other n give a result > 20). 21 is not, because it can be written as 15 + 1 + 5 using n = 15. Self Number

Kor 어떤 자연수 n이있을때 d(n)을 n의 각 자릿수 숫자들과 n자신을 더한 숫자라고 정의하다. 예를 들어 d(91)=9+1+91=101 이때, n을 d(n)의 제네레이터(generator)라고 한다. 위의 예에서 91은 101의 제네러이터이다. 어떤 숫자들은 하나 이상의 제네레이터를 가지고 있는데, 101의 제네레이터는 91뿐 아니라 100도 있다. 그런데 반대로, 제네레이터가 없는 숫자를 셀프넘버(self number)라고 한다.

코드

초기화

const MAX_VALUE = 5001; // Rage Array는 (0 ~ MAX_VALUE) - 1 이다 

var numberSet = new Set(Array.from(Array(MAX_VALUE).keys())); // 자바스크립트 : Rage Array만들기.

로직

var _func = function (number) {
  if (number > 0 && number < MAX_VALUE) {
    var _number = (""+number).split("").map(Number).reduce(function (x, y) { return x + y}) + number // generator 구함
    numberSet.delete(_number);
    _func(_number); // array에서 delete할 경우 forEach에 검사되지 않아서 재귀해준다.
  }
};
    
numberSet.forEach(_func); // 돌려주면 끝 - 

Q. 5000까지 Self Number에 합을 구하시요.

A. 1227365

p.s 넥슨 입사문제였다고 한다. javascript 기본 함수들을 몰라서 시간이 조금 소요되었다.

const MAX_VALUE = 5001; // self number max value - 1

var numberSet = new Set(Array.from(Array(MAX_VALUE).keys()));
var result = 0;
// delete self Number in set
var _func = function (number) {
  if (number > 0 && number < MAX_VALUE) {
      var _number = (""+number).split("").map(Number).reduce(function (x, y) { return x + y}) + number
      numberSet.delete(_number);
      _func(_number);
  }
};

numberSet.forEach(_func);
// Self Number sum
numberSet.forEach(function (number) {
  result += number;
});

// Result print
console.log(result);