설정에 shortcut 이 다 나와 있지 않아, 매우 불편했었다;;;

특히나, 에디터 탭간 이동을 몰라서 무척 난감했었는데...

ALT+R / ALT+Q  을 아래에서 발견했다~ :)

https://shortcutworld.com/SAP-Web-IDE/win/SAP-Web-IDE_Shortcuts

블로그 이미지

ohnewdev

배워서 남주자

,


###  Closuser

출처 : 단일페이지 웹 어플리케이션 (위키북스)


Closure 역시나 내용이 쉽지 않으나, 설명이 참 좋다. 


<script>
var makePrison = function (prisoner) {
return function () {
return prisoner;
}
};

var joshPrison = makePrison('Josh Powerll');
var mikePrison = makePrison('Mike Mikowski');

//클로저
// 클로저란 변수가 생성된 실행 컨텍스트 외부에서도 변수에 접근할 수
// 있게끔 변수를 유지함으로써 가비지 컬렉터가 변수를 메모리에서
// 제거할 수 없게끔 하는 절차다.
console.log(joshPrison());
console.log(mikePrison());

var prison = {
names: 'Mike Mikowski and Josh Powell',
who: function () {
return console.log( this.names );
}
};
prison.who();
</script>

위에서의 this 는 prison 이며, closure 처리됨.


이런 경우에 Closure 처리를 함으로서 원하는 바를 얻을 수 있다. 

Ajax 호출에 대한 응답은 최초 비동기 호출이 발생했던 실행 컨텍스트 밖에서 발생하게 된다. 

( 참고 : context 의미 )

<script>
var prison = {
names: 'Mike Mikowski and Josh Powell',
who: function () {
var that = this;
$.ajax({
success: function () {
//console.log ( this.names); // 여기서 this 는 ajax 호출을 가리킴

//success함수 호출될 때에 that 변수를 참조할 수 있음
// that 객체가 closure 처리되어
console.log ( that.names);
}
});
}
};
prison.who();



</script>


### 실행 컨텍스트란 ( p.62 )

함수가 호출될 때마다 새로운 실행 컨텍스트(executioin context)가 생긴다.

실행 컨텍스트는 함수가 실행되는 동안 일어나는 모든 내용으로 구성된다. 실행 컨텍스트는 함수 선언과는 다르다. 함수 선언이 함수가 실행될 때 어떤 동작을 하는지 설명하는 데 반해, 실행 컨텍스트는 함수 실행 그 자체다.

... 중략...

실행 컨텍스트에 속한 변수 및 함수는 실행 컨텍스트 객체에 저장된다.

자바스크립트 엔진이 실행 컨텍스트를 통해 2단계를 거치면서 변수를 선언하고 초기화한다. 

1차 : 인자와 함수가 선언되고 대입

2차 : 자바스크립트를 실행하고 지역 변수의 값을 정의함






'프로그래밍 > javascript' 카테고리의 다른 글

[ECMAScrpt6] Arrow 함수  (0) 2018.04.03
[javascript] 계산기 만들기  (0) 2017.05.16
블로그 이미지

ohnewdev

배워서 남주자

,

[ 참고서적 : ECMAScrip6 - 김보영 님 저. ]

(param) => { 코드 };
param => { 코드 };
() => { 코드 };
( param1, param2, , , , paramN) => { 코드 };
param => ( {key: value} );
(param1, param2, ...rest) => { 코드 };
( param1, param2 = 123, , ,  paramN) => {코드 };
( [one, two] = [1, 2] _ => one + two;
({key : sum} = {key : 10 + 20 }) => { 코드 };
let fn = (param) => { 코드 };

화살표 함수는 functnion(param) { 코드 } 를 축약한 것으로 (param) => {코드} 형태로 작성합니다.






'프로그래밍 > javascript' 카테고리의 다른 글

Closure  (0) 2018.07.04
[javascript] 계산기 만들기  (0) 2017.05.16
블로그 이미지

ohnewdev

배워서 남주자

,
### Vim 환경설정을 해보자.
매번 서버받고 설정하려고 하니... 귀찮다. 더더 쉬운 방법을 찾게 되겠지만..
일단 vim 설치는 아래와 같이 하면 되겠다.

git clone --depth=1 https://github.com/amix/vimrc.git ~/.vim_runtime
sh ~/.vim_runtime/install_awesome_vimrc.sh

참고 :
https://github.com/amix/vimrc


=========================================================
아래는 이전 작성글 ... 매번하니 귀찮아 졌다 :(

### vim 환경설정을 해보자.
먼저, 코딩을 할 수 있는 환경을 만들어야 하는데,
vim 을 잘 써보리라 했지만, 이제 막 써보는 경우라 사용법이 어렵다.
윈도우 환경에서 이클립스만 써왔는데, 관연 IDE 를 대체할 수 있을지;;
그래도 모바일환경(갤럭시탭s2, termux) 에서 사용하는 것이라 아쉬운데로
사용해보려고 한다.

[참고]
https://bluesh55.github.io/2016/10/09/vim-ide/
굉장히 잘 정리해 주셔서 그간 플러그인 설치에서 많이 헤매었으나, 처음으로 플러그인을 적용시켜봤다. 그동안 왜케 헤매었었는지...

$ vim ~/.vimrc
로 파일을 열면, 아래와 같이 설정을 해보았다.

아래와 같이 이쁘게 UI 도 바뀌었다.

'프로그래밍 > Python' 카테고리의 다른 글

나도 클라우드에 개발환경을 가져보자(#1)  (0) 2018.02.28
블로그 이미지

ohnewdev

배워서 남주자

,

나도 클라우드에 개발환경을 가져보자(#1)

리눅스랑 친해보고 싶어서 매일매일 아래 과정을 1번부터 계속 해보고 있습니다 :)

내용 중에 틀린 부분이 있을 수 있고, 시간상 이해없이 넘어간 부분도 있습니다.

0. 클라우드 서비스에 가입하자

vps 를 제공받을 수 있는 클라우드 서비스에 가입한다. 
나는 conoha 에서 서비스를 받고 있는데, 테스트 서버 사양으로 한달에 690엔입니다.
네트웍 트래픽은 무제한이다!! 
1시간에 1엔정도 인데… 아직 돌릴만한 서비스도 없고 
쓸때만 쓰고, 그외는 삭제시켜버린다. 
몇 번이고 만들었다, 삭제하는 것을 반복해볼 수 있어서 좋다.

아래 링크를 통해 들어가면, 일본어가 떠서 정신없다.

  • 한국어로 바꿔주고 회원가입한다.
  • 안심이 되는 것은 포인트를 충전해서 쓸 수 있다는 것이다.
  • AWS 달리 나와같은 초짜가 의도치않게 과금폭탄 고지서를 만날일이 없다는 것에 대담해질 수 있다.

ConoHa 에 가입시에 아래 링크로 가입하면, 사용에 따른 쿠폰이 지급된다.

ConoHa를 지인분께 소개하시고 선물 쿠폰을 받으세요. 
지인분께서 2,000엔 상당의 ConoHa 서비스를 이용하시면, 소개자 분께 각각 2,000엔씩 선물 쿠폰을 드립니다.

https://www.conoha.jp/referral/?token=30kMggaB1XdoYEnxbFfpOPOursdQuUAW7Iwlg6ZUgbeYIgYdx8s-13P 
위 링크를 누르시면, 기본언어인 일본어로 나와서 정신없다. 
한국어로 바꿔주고 회원가입한다. 
나는 신용카드로 1000엔 정도의 포인트를 충전하여 포인트로 사용료 지불하는 식으로 하고 있다.


1. conoha 에서 서버 추가하기

기본적으로 제일 싼놈으로 설정되어 있는데,

  • cpu 1core
  • SSD 20GB
  • memory 512mb
  • 630엔/월
  • Os Ubuntu 16.04(64bit) 
    를 선택한다. 
    1시간에 1엔하는 착한 녀석이다.

    root 패스워드는 필수 입력 사항이다. (대소문자, 특수문자가 필수로 알고 있다) 
    추가하기 누르면 끝!!

    약 20초 정도 지나면, 고정 서버접속가능한 ip를 받을 수 있다.


2. ssh를 통해 접속을 한다.

저 같은 경우는 개인적인 사정으로 모바일환경에서 개발을 합니다.ㅠ

  • 갤럭시탭s2 에서 Termux 라는 앱을 설치하고 블루투스 키보드를 이용한다.
  • Termux 가 리눅스환경을 제공하긴 하지만, 쓰다가 보니, 제한도 많고, 다르다. 
    flask(파이썬 웹서버) 를 통해 로컬서버를 띄우고 간단히 만져볼 정도는 된다.

  • conoha 에서 서버를 추가하고 받은 고정ip(xxx.xx.xxx.xx)를 이용해서 아래와 같이 입력한다.

$ ssh root@xxx.xx.xxx.xx
  • 이어서 conoha 에서 서버추가시 설정했던 패스워드를 입력하면, 접속이 된다.

3. 우분투 사용자 계정 생성

매번 root로 사용하면 찝찝하니… 리눅스와 친해질겸 매일 하는 과정에 포함시킨다.

root@xxx.xx.xxx.xx:~# adduser dev1

: 비밀번호 입력하라고 나온다.

root@xxx.xx.xxx.xx:~# usermod -G sudo dev1

: dev1 에 sudo 권한 부여하기위해 sudo라는 그룹의 권한을 추가해 준 것임. 
(참고 : http://kanziw.com/133 )

root@xxx.xx.xxx.xx:~# su dev1

: su는 switch user 이다. 맞나?

dev1@xxx.xx.xxx.xx:~$

: #에서 $로 프롬프트가 바뀌었다. root 계정에서 그외 계정으로 바뀌면 바뀌는 걸로 알고 있다.


4. python 버젼 확인

$ python --version

을 해보면, 2.7.12 가 기본으로 설치되어 있는 것을 확인했다.


5. pip 설치

pip 이것저것 편리하게 python 관련 프로그램을 설치해 주는 편리한 도구이다.

$ sudo apt-get install python-pip
$ pip --version

: 현재 python 버젼이 2 이므로 pip는 python2 버젼 기준으로 되어 있다.


6. virtualenv 설치

virtualenv 는 프로그램을 설치할 때, 시스템에 등록이 되는데, 여러 버젼이 설치되면 
개발환경이 꼬이게 된다. 그래서, 개발환경 ID를 정해놓고, 그 ID로 이름지어진 공간에만 
프로그램 환경변수 등이 등록되어 개발환경이 ID별로 달리 적용할 수 있도록 해주는 
편리한 프로그램 이다. 
이것을 설치해서 python2, python3 을 구분해서 사용하겠다.

$ sudo pip install virtualenv
$ mkdir dev_space
$ cd dev_space
$ mkdir proj1
$ pwd
/home/dev1/dev_space/proj1
$ virtualenv .venv_py2
: venv_py2 로 구분할 개발환경 이름를 정했다.
이름을 .venv_py2로 해줬다. 필수는 아니지만, .을 붙여줌으로서 일반폴더와 구분이된다.
$ . .venv_py2/bin/activate
(.venv_py2) $

: 활성화 시킨다. 
앞에 (.venv_py2) 라고 “이 개발환경은 .venv_py2 라는 환경이야” 라고 설명이 나와있다.

(.venv_py2) $ sudo apt-get install python-dev \
build-essential libssl-dev libffi-dev \
libxml2-dev libxslt1-dev zlib1g-dev
: 줄줄이 설치 된다.
다시 환경을 빠져나가서 python3 환경을 만들어보자
(venv_py2) $ deactivate
$
: 나만의 개발환경에서 빠져나왔다.
다시 들어가려면, venv_py2 상위폴더에서
$ . venv_py2/bin/activate

: 를 실행해주면, 다시 venv_py2 라고 이름 붙이 개발환경으로 셋팅된다.

연습 겸 python3 버젼으로 설정해보자.

$ virtualenv venv_py3
$ . venv_py3/bin/activate
(venv_py3) $ sudo apt-get install python3 python-dev python3-dev \
build-essential libssl-dev libffi-dev \
libxml2-dev libxslt1-dev zlib1g-dev \
$ sudo apt-get install python3-pip
$ python3 --version
$ pip3 --version

: 이렇게 설치로 py2, py3를 구분하는게 맞는지는 나중에 알아보고 일단 계속 진행하겠다.


7. Hello world 찍어보자

$ vim hello.py
: vim 편집기를 이용해서 print(“hello world”)
vim 사용법은 각자…
$ python hello.py

로 실행시켜 본다.


8. 달랑 한 줄이지만 github 에 올려보자.

$ cd ~/dev_space/proj1
$ git init
$ vim hello.py

i 키를 누르면, 입력모드 
esc 키를 누르면, 커맨드 모드 
esc 키를 누르고 :wq 라고 입력하면 저장 된다.

$ python hello.py
$ git status

: 를 해보니, .venv_py2 폴더가 보인다. 예외처리 하자.

$ vim .gitignore
.*/
.*

이렇게 입력하고, 저장하고 다시

$ git status

하면 내용이 안보인다.

$ git add hello.py
$ git commit -m "first commit"

라고 하면, 내가 누군지 알려달라고 git config 를 통해 설정하라고 메세지가 나온다.

$ git config --global user.email "ohnewdev@gmail.com"
$ git config --global user.name "ohnew"
$ git remote add mytwisted https://github.com/ohnewdev/learnTwisted.git
$ git remote -v
$ git pull mytwisted master
$ git status
$ git commit -m "ok commit"
$ git push mytwisted master

: 잘반영된다.

다음 to do… 
eclipse che, vim 로 코딩환경 개선하기... 


'프로그래밍 > Python' 카테고리의 다른 글

나도 클라우드에 개발환경을 가져보자(#2)  (0) 2018.03.08
블로그 이미지

ohnewdev

배워서 남주자

,

개인적인 학습목적으로 작성한 포스트 입니다.

SAP FIORI

SAP의 Front-end 프레임웍 입니다. 
사용자경험 기반의 UI로 새롭게 단장하고 폰, 테블릿, PC에서도 같이 보여집니다. 
SAP UI5 에 기반한 기반한 UX 입니다.

[SAP 기존 UI vs Fiori UI 비교 동영상] 
https://www.youtube.com/watch?v=_morrLqAZTQ

참고 : Fiori 소개 
https://blogs.sap.com/2016/09/17/understanding-sap-fiori/

[정리할 개념 및 용어]

1. SAPUI5

  • SAP가 구축한 HTML5 툴킷의 이름입니다. 
    (즉, 웹화면 부분을 개발할 수 있는 개발도구 입니다.)
  • Web 개발이 Server-client 방식으로 개발되는데, 웹클라이언트 개발의 
    javascript, CSS, HTML5 를 기반으로 만든 UI 라이브러리입니다.
  • Javascript Framework 으로 IE, Chrome, Firefox 등 메인 브라우저를 지원합니다.
  • 튜토리얼 ( https://sapui5.hana.ondemand.com/ )

2. FIORI

  • SAP 에서 SAPUI5로 만든 Front-end Framework 입니다. 
    (즉, SAPUI5를 이용하여 시스템의 화면부를 구성할 수 있도록 개발환경을 제공합니다.)
  • 모바일, 테블릿, PC 에서도 동일하게 작동하도록 설계되어있습니다.

3. Odata

  • 웹상에서 손쉽게 데이터를 조회하거나 수정할 수 있도록 주고 받는 웹프로토콜(규약) 입니다.
  • Fiori 에서 사용되며, Fiori 화면을 SAPUI5 로 만들어낸다고 하면, 그 내부적으로 데이터를 
    던지고 받는 구조적인 역할을 합니다.

4. Front-end Server

UI add-Ons(Fiori App Repogitory) + SAP NetWeaver Gateway

로 구성됩니다. 

  • Fiori App Repogitory : Fiori 프로그램의 구성된 공간
  • SAP NetWeaver Gateway : ABAP Back-end Server 와 Fiori 간의 Odata 전달

5. SAP UI5 Concept

1) Model-view-Controller(MVC)
  • Client 단에도 MVC 구조를 이루고 있음.
  • View : 화면 레이아웃 구성
  • Model : 데이터를 채워주는 부분. 뷰에 어떤 데이터를 보낼지 담는 그릇 역할
  • Controller : View 에 버튼이 눌러졌을 때 Model 에 어떤 데이터를 넣어줄건지, 어떤 행동을 할 것인지를 정의하고 있는 부분.
2) Data Binding
  • 서버에서 뿌려지는 것 뿐 아니라 화면에서 사용자가 변경한 부분까지 묶이도록 코딩으로 정의 하는 작업.
[코드 예]
// 샘플로 oData 를 만듬.
var oData = { recipient : { name : "world"} };
//위에서 만든 oData 를 model 로 구성함.
var oModel = new JSONModel(oData);
this.getView().setModel(oModel);
// model 에는 데이터가 실려있고, 이 model 을
// View 쪽에 연결(데이터 바인딩)
// 이렇게 데이터가 바인딩 되면....
// 화면에 데이터를 변경하면 연결된 데이터들도 함께
// 변경된다. 즉, 화면값과 연결된 model 내부의
// 값도 변경된다.
// 예를들어 화면의 world 값을 ABC 로 바꾸면,
// model이라는 그릇내의 world 값이 ABC로 바뀝니다.
// 이것을 다시 ABAP Back-end로 전달하면, 되겠지요.

그럼, Fiori는 뭘로 개발하나? (개발도구)

1) web IDE

  • 웹사이트 들어가서 개발함.
  • 하나클라우드에 들어가서 개발함.

2) web ide personal edition

  • 로컬에 띄워놓고 개발하는 것임.

3) Eclipse 플러그인

  • 웹화면 개발하는 것과 거의 유사.

  • SAP 에서는 클라우드 플랫폼에서 개발하도록 권하긴 합니다. 
    가입을 하면 트라이얼 환경에서 개발을 해볼 수 있습니다. 
    가짜 서버도 띄워보고 할 수 도 있습니다.

  • 개발도구 링크 : https://tools.hana.ondemand.com/#sapui5


블로그 이미지

ohnewdev

배워서 남주자

,
책 : JAVA 언어로 배우는 리팩토링 입문
히로시 유키 저
박건태 역

1. 정의

: 외부에서 본 프로그램의 동작은 변하지 않고 프로그램 내부의 구조를 개선하는 것입니다. 
리팩토링을 할때는 전후에 테스트를 실시합니다. 
- 리팩토링하기 전에 테스트를 합니다. 
- 리팩토링을 합니다. 
- 리팩토링한 후 다시 한번 테스트를 합니다.

2. 목적

  • 버그를 찾아내기 쉽게 한다.
  • 기능을 추가하기 쉽게 한다.
  • 리뷰하는 것이 쉬워진다.

3. 리팩토링의 한계

  • 프로그램이 아직 동작하지 않는 경우
  • 시간이 얼마 남지 않았을 경우(마감일에 가까워 졌을 때)

4. 코드의 악취

: 리팩토링이 필요한 부분

  • 코드가 여기저기 겹쳐 있다.
  • 메소드가 너무 길다.
  • 클래스의 파일이나 메소드가 너무 많다.
  • 메소드에 전달하는 인수의 수가 너무 많다.
  • 사양변경이 발생한 경우 수정할 곳이 여기저기 흩어져 있다.
  • 어떤 클래스를 수정하면 다른 클래스도 수정하지 않으면 안 된다.
  • 언제나 다른 클래스의 속성을 건드리고 있다.
  • 정리해서 다룰 수 밖에 없는 여러 개의 데이터가 하나의 클래스에 정리되어 있지 않다.
  • 클래스를 만드맂 않고 int같은 기본 데이터형만을 사용한다.
  • switch 문이나 if문을 사용하여 동작을 분할하고 있다.
  • 서브클래스를 만들면 클래스 계층에 따로 서브클래스를 만들어야 한다.
  • 클래스가 별로 하는 일이 없다.
  • 일시적으로 사용할 필드가 있다.
  • 메소드가 호출하는 연쇄가 너무 많다.
  • 위양(권리를 위임하고)자신이 하는 일은 없는 클래스가 있다.
  • {부적절한 관계} 필요 없는 쌍방향 링크가 걸려 있거나 is-a 관계가 아니면서 상속을 사용한다.
  • {클래스의 인터페이스 불일치} API 가 부적절하다.
  • 기존의 클래스라이브러리가 사용하기 힘들다.
  • {데이터클래스} 필드와 getter메소드와 setter 메소드만 가지고 있는 클래스가 있다.
  • {상속거부} 상속하고 있는 메소드면서 그것을 호출하면 문제가 발생한다.
  • {코멘트} 코드의 부족을 보충하기 위해 상세한 코멘트가 있다.

  • [요약]

    • 겹쳐있다.
    • 너무길다
    • 너무 많다
    • 이름이 어울리지 않는다
    • 너무 공개했다
    • 객체지향적이지 않다.

    리펙토링은 Step by step!!!


책 : JAVA 언어로 배우는 리팩토링 입문
히로시 유키 저
박건태 역


블로그 이미지

ohnewdev

배워서 남주자

,


그간 대강 두리뭉실 써왔던 javascript를 다시 보고 있다. 재입문이 아니라 처음 배우는 느낌이다.

함수 선언 VS. 표현식

함수에는 두 가지 리터럴 형태가 있는데, 다른지는 몰랐었다.

[함수 선언-function declaration]

function add(num1, num2){
return num1 + num2;
}

[함수 표현식-function expression]

var add = function (num1, num2){
return num1 + num2;
}

함수 선언식을 사용하면 코드가 실행 될 때 컨텍스트(선언된 함수를 포함하고 있는 함수 스코프 또는 전역 스코프) 상단에 끌어올려진다고 한다. 즉, 함수를 호출하는 코드가 함수를 선언한 코드보다 앞에 있어도 에러가 발생하지 않는다는 뜻이다.(hoisting)

var result = add(5,5);
function add(num1, num2){
return num1 + num2;
}

함수 호이스팅(hoisting)은 함 수 이름을 먼저 처리하기 때문에 일어나는 현상으로 함수 선언에만 적용된다. 
같은 자리에 함수 표현식으로 작성하면 에러가 난다.

[인용-객체지향자바스크립트의 원리]

정규식

숫자키 버튼 및 텍스트박스 직접 입력 등의 입력값에 대한 검증을 하기 위해 정규식 사용. 
참조 : 정규식

strict mode

개발과정에서 발생될 수 있는 오류에 대해 더 엄격하게 두기.

참조 : Strict mode


계산기 프로그램 OOP 로 만들기

객체지향 언어 특징을 다시 정리하면


'프로그래밍 > javascript' 카테고리의 다른 글

Closure  (0) 2018.07.04
[ECMAScrpt6] Arrow 함수  (0) 2018.04.03
블로그 이미지

ohnewdev

배워서 남주자

,

[postgresql] UPSERT

  1. SQL- upsert 만드는 법 
    기존 오라클에서 사용하던 merge 구문효과를 postgresql 에서 사용하기 위해 UPSERT 문을 만들어 사용한다.

    1)

    INSERT INTO spider_count (spider, tally) VALUES ('Googlebot', 1);

    2)

    UPDATE spider_count SET tally=tally+1 WHERE date='today' AND spider='Googlebot';

    이와 같은 2개의 구문이 있다고 할 때,변환 방법은 다음 처럼 한다. upsert 라는 변수로 가정하고,

     $insert = "INSERT INTO spider_count (spider, tally) SELECT 'Googlebot', 1";

    $upsert = "UPDATE spider_count SET tally=tally+1 WHERE date='today' AND spider='Googlebot'";
  2. 위 2개의 변수를 아래 모양에 맞춰 넣는다.

    WITH upsert AS ($update RETURNING *) $insert WHERE NOT EXISTS (SELECT * FROM upsert);
    WITH upsert AS ( (UPDATE spider_count SET tally=tally+1 WHERE date='today' AND spider='Googlebot') RETURNING *) INSERT INTO spider_count(spider, tally) SELECT 'Goolgebot', 1 WHERE NOT EXISTS( SELECT * FROM upsert)


'프로그래밍 > SQL' 카테고리의 다른 글

[SQL] rownum, limit(top), order by 순서지정  (0) 2017.04.11
블로그 이미지

ohnewdev

배워서 남주자

,

Java Pair 자료구조

C++ 에는 Pair 자료구조가 있는데, 자바에는 없다. 
직접 만들어서 써야 하는 건가? 
찾아보다가 맘에 드는 소스를 보관해본다.

    class Pair<L,R> {
final L left;
final R right;

public Pair(L left, R right) {
this.left = left;
this.right = right;
}

static <L,R> Pair<L,R> of(L left, R right){
return new Pair<L,R>(left, right);
}
}

list.add(Pair.of(x,y)); // my preference 
list.add(pairOf(x,y)); // use with import static x.y.Pair.pairOf

참고 : @simbo1905 http://stackoverflow.com/questions/521171/a-java-collection-of-value-pairs-tuples


'프로그래밍 > JAVA' 카테고리의 다른 글

Web-Scraping(XML)  (0) 2017.04.06
블로그 이미지

ohnewdev

배워서 남주자

,