리눅스를 다루게 된다면 마땅한 텍스트 편집기가 존재하지 않는다는 이유라던지, 아니면 emacs가 싫어서 못 써먹겠다던지의 이유로 vim을 에디터로 쓰게 되는 일들이 종종 있다. 아니면 nano보다는 좀 더 강력한 편집기가 필요하거나, vi 말고는 어떠한 텍스트 편집기도 리눅스에서 쓸 수 없다는 착각을 하고 살거나, 여하튼 vim을 쓰기 시작하는 이야기는 다양하지만, 그 끝이 좋은 걸 본 적이 없다.

 

사실, 이 글을 쓰게 된 이유는 간단하다. Vim을 쓰는 최악의 실제 사례를 트위터에서 보고, 설마하고 vim을 쓰는 사람들이 대부분 이렇게 쓰는 거 아닌가 하고 확인을 하다가, 실제로 다들 그렇게 쓴다는 것을 보고 경악을 했기 때문이다. "아니 도대체 왜 그렇게 쓰세요?"라는 질문은 접어두고, 실제로 중학교 때부터 vim을 써오고, (아직도 학부생이지만) 학부 때 주변에 vim을 추천하고 다녔던 과거의 일들이 주마등처럼 스치면서 "도대체 (내가 왜) vim을 이렇게 쓰라고 주변에 알려줬나, 도대체 vim은 뭔 인외마경인가"라는 질문이 갑자기 들어서 꽤 큰 현자타임이 왔었다.

 

vim은 필요에 의해서 만들어진 텍스트 에디터이다. 그리고, 그 필요는 IDE의 등장 이후로는 점점 사라지는 추세가 아닌가 싶다. 터미널 화면이라는 제한적인 상황에서 최소한의 통신과 키스트로크만으로 코딩을 해야했었던 상황과 ed, ex 같은 라인 에디터로 라인을 수정하던 불편함을 해소해야 한다는 상황은 GUI의 등장과 IDE의 등장 이후에는 의미가 없어졌다. vim이 갖고 있는 유일한 장점은 IDE의 기능들과 Ctrl, Alt와 조합 가능한 명령어들로 대체가 되기 시작하였고, 심지어 이 새로운 명령어들은 OS 레벨에서 지원하는 보편적인 명령어 조합들과 호환성이 대부분 보장이 된다. (CCCV처럼)

 

이러한 상황에서 vim이 자랑할 수 있는 것은 유일하다. 터미널 시절의 그 열악한 환경에서 최소한의 시간으로 최대한의 작업을 뽑아내기 위해 만든 각종 명령어 조합들이 그것이다. 이러한 시스템은 vim이라는 에디터의 진입 장벽을 높였을 뿐만 아니라, 일단 진입 이후 대체재를 못 찾게 만드는 주 원인이 된다. 컨트롤 C 컨트롤 V대신 dd나 yy를 사용해서 라인을 카피 뜨고, p를 이용해서 원하는 자리에 넣는 것은 어쨌든 편하고, 거기다가 이 복사 과정에서는 마우스를 쓸 일 조차 없다. 프로그래머가 마우스라는 엄청나게 불편한 화면 포인팅 장비를 쓰지 않고도, 키보드에서 손을 한 번도 안 떼고도, 새끼손가락을 그렇게 고생시키지 않아도, 키 조합을 충분히 외우고 있으면 엄청나게 빠르게 복사 붙여 넣기를 할 수 있는 것이다. 심지어 vim은 내부적으로 스택을 사용해서 이 복사 붙여 넣기 과정을 관리한다. 그러니, 여러 라인을 여러 번 복사하면, 기존 OS처럼 복사한 내용이 사라지지 않고, 스택처럼 쌓여서 프로그래머의 생각대로 막 복붙이 되는 것이다! (실제로 OS에서는 복사 내용이 사라지지는 않고 기록은 하긴 한다. 다만 Ctrl-V는 최신으로 복사한 내용만 붙여 넣기 해줄 뿐이지)

 

하지만 이러한 장점은 너무나도 복잡한 시스템에 의해서 상쇄된다.

 

vim을 초반에 사용하는 패턴들은 대부분 비슷한데, .vimrc의 존재를 모르는 상황에서 인덴트 옵션이나, 신텍스 하이라이팅 옵션은 커녕, set nu나 set rnu 같은 건 키지도 않는 상황에서 엄청나게 불편한 메모장처럼 쓰는 것이 첫 단계이다. 둘째 단계는 그나마 괜찮아지는데, bottom-line command mode나, command mode에서 생산성을 높여주는 몇몇 명령어들을 외우고, 이를 이용해서 vim이 다른 IDE보다 우월한 이유를 찾아내는 것이다. 이럴 때 대부분 vim을 주변에 추천하고 다닌다. 하지만, vim에 대한 이해도는 그렇게 높지 않은 편이고, 실제로 여기서 주저앉아서 아는 기능들만 쓸 것인지, 아니면 불편하면 찾아서 명령어들을 새로 외우면서 더 많은 기능들을 배울지가 갈린다. 셋째 단계부터는 .vimrc를 수정하고 vundle 등의 각종 확장 프로그램 매니저를 깔고 점점 더 나은 터미널 생활을 하는 것이다. 대부분 이 단계에서 멈춰있고, 이 단계만 되어도 충분히 생산성을 보장받는 건 사실이다. 최소 1년에서 길면 3~4년 정도 걸려서 이게 뭔 기능인지 하나하나 테스트하면서 알아내는 게 대부분이지만, 일단 프로그래밍 실력이 상승함과 동시에 터미널에서 작업을 할 일이 많다면 어쩔 수 없이 받아 들어야 하는 숙명 정도로 느끼게 되는 것이다. 그리고 사람들이 잘 모르는 넷째 단계가 있는데, 대부분 플러그인을 만들고 있거나, 컬러스킴을 만들고 있거나 여튼 vim script를 이용하여 뭔가를 만들고 있다. 다섯번째 단계로 가면, 정규표현식이나 매크로 같은 기능들을 이용해서 코드 골프를 치고 있는 경우가 나오는데, 프로그래머가 vim을 쓰는건지 vim이 프로그래머를 쓰는건지 모르는 상황에 다 다르는 것이다.

 

뭐 여튼, 장황한 이야기를 넘어서서, 사실 vim 추천을 극도로 꺼리는 것은 구글링을 해도 그렇게 좋은 vim 자습서와 사용례들이 없기 때문이다. 사실 vim을 접한 지 꽤 되었고, 충분히 프로그래밍도 잘하시는 분이 bottom-line command에 :9999999를 넣어서 마지막 라인으로 이동한다는 이야기를 듣고, 설마 해서 트윗을 올렸다가 대부분 그렇게 쓴다는 이야기를 듣고 상당히 기분이 이상해졌는데, 생각해보니 보통 gg 명령어, hjkl에 숫자를 섞어 쓰거나 대문자로 썼을 경우 vim에서 어떻게 처리하는가에 대한 부분에 대해서 제대로 설명하는 데가 없었다는 것이다. 뭐 유명한 vim 책이나 vim 어드벤쳐 같은 걸 차근차근히 진행을 해 봤다면 알고는 있겠지만, 구글링과 각종 삽질로 배우다 보면 놓치게 되는 부분들이 있는 것은 사실이다. 그리고, 이런 걸 놓치면 솔직히 vim을 권하는 의미가 상당히 없어진다는 것이 문제다.

 

다시 발단부터 되짚어 보면서 vim의 기능들에 대해서 다시 이야기를 하자면...

 

 

그리고 몇몇 대화와 타임라인을 읽다가 {숫자}gg로 라인이동을 하는 게 아닌 :{숫자}로 라인이동을 하는 사례가 의외로 많다는 것을 보고 충격을 받는다.

 

 

이 이후, vim에 대해서 쌍욕을 하기 시작하는데...

 

 

 

 

 

사실 빡침의 이유는 간단하다. 막 주변에 vim 추천하고 다니는데 정작 vim의 장점을 제대로 설명하지 못하는 것, 그리고 vim의 핵심적인 기능을 끝까지 써보지 못하고 끝이 나도록하는 것이 그것이다. (으... 이런 미친 X을 다 봤나! 라는 생각이 드는가? 그렇다 vim은 제대로 쓰지 않으면 의미가 없다 으하하하)

 

Vim의 명령어 조합은 상당히 직관적이다. 사실 직관을 넘어서서 단순하다고 하는 게 낫겠지만, 대부분 command mode에서는 대부분 숫자와 키보드의 키 몇 개의 조합으로 대부분 원하는 기능을 뽑아낼 수 있다. KLDP에서 오래전부터 돌고 있던, 이 이미지부터 시작을 해야 할 것 같다.

 

이 이미지에 겁을 먹을 필요는 없다. 사실 모든 키에는 기능이 하나씩 있다는 것 정도만 알면 된다. 그리고 저기에 있는 키들은 대부분 조합 가능한 형태라는 것이다. 그리고 그 명령어는 현재 커서 위치에 의해서 상대적으로 결정된다.

 

대표적으로 처음 배우는 명령어 중 외울 만한 녀석은 다음과 같다.

 

1. 입력 모드 들어가기 (iosa 나 ioas로 외우면 편하다. IOSA의 경우 iosa의 기능의 반전 느낌이다.)

i : 커서 자리부터 쓰기

o : 다음 라인부터 쓰기

a : 맨 뒤에 붙여쓰기

s : 커서가 가리키는 문자 지우고 새로 쓰기

 

2. 편집 시 사용하는 것

dd : 라인 삭제

yy : 라인 복사

p : 라인 붙여 넣기

u : 되돌리기

U : 되돌린 거 취소

 

3. 커서 이동

gg : 파일 맨 처음 라인으로 이동

G : 파일 맨 마지막 라인으로 이동

h, j, k, l : 좌, 하, 상, 우 이동

e : 단어 끝으로 이동

w : 다음 단어로 이동

{ , } : 다음/이전 빈 줄로 이동 (문단 시작/끝이라는데 그냥 그건 vim이 그렇게 똑똑하다는 증거가 아니다)

 

4. 명령어의 조합

{숫자}gg : 숫자에 해당하는 곳으로 커서 이동

{숫자} + h, j, k, l : 숫자만큼 이동

{숫자}w

{숫자}dd

{숫자}yy

...

de

ye

{숫자}de

...

gg=G

...

 

실제로 vim의 핵심은 명령어의 조합이다.

3de 라던지, 11}, gg=G, 5>>, 3<< 같은 처음 보면 뭐 이딴게 다 있는가라고 느껴지는 것들이 많은데 대부분 이러한 조합에는 대부분 규칙이 있고, 그 규칙만 잘 지키면 상당히 쾌적한 코딩을 할 수 있다. 특히 입력 모드의 경우 다 외워 놓는 게 좋은데, 이건 대부분 강제로 쓰다 보면 외워지게 되는 부분이다. 그리고, 이 명령어들은 .vimrc를 만지지 않아도 대부분 같은 형태로 지원해주고 있으니 이 명령어들을 외우고 다니는 게 핵심이 된다. 그리고, 아마 꾸준한 노력 없이는 hjkl이 아니라 마우스와 키보드 화살표를 사용하게 되는데, 사실 이를 .vimrc에서 막으라는 조언은 듣지 않는 걸 추천한다. 초기 학습 곡선이 엄청나게 높아지는 건 둘째 치고, 숫자 + 명령어 조합에 익숙해지면 어쩔 수 없이 hjkl을 쓰게 된다.

 

이 이후 매크로나 bottom-line 명령어들을 알아가는 과정이 필요한데, 이 부분은 솔직히 이 글을 쓰는 당사자도 모르는 게 많은 편이다. 문자열 치환이나 검색 같은 건 기본적으로 하지만, 그 이후부터는 정규표현식이나 확장 프로그램에 의존을 많이 하게 되는 편이라서 이 부분은 결국 입맛대로 가게 될 수밖에 없다. 하지만 이 정도면 이미 vim이 왜 좋은지에 대해서는 알 수 있겠고, 서버에서 config 파일 수정할 때나 로그 검색할 때 어쩔 수 없이 vim을 쓰게 될 때에 그나마 도움이 될 것이라 생각한다.

 

그래서 하고 싶은 말이 무엇인가? Vim은 인외마경이다. 사실 제대로 배우고 쓸 생각을 하는 초보자가 있다면 일단 익숙한 IDE부터 하나는 있어야 할 것이고, 타이핑의 속도나 텍스트 처리의 속도를 높여주는 용도일 뿐이지, 프로그래밍을 더 잘하게 해주는 도구가 아니라는 것을 일단 인지하고 있어야 한다. 어느 정도 익숙해지면 내 생각의 속도만큼 빠르게 텍스트를 변형시킬 수 있다. 정도로 접근을 해야 할 부분이며, 그 이상의 효과를 기대하는 것은 무리이다.

 

사실 이런 면에서 vim을 사용하도록 장려하는 것이나, vim 좋다는 인식을 주는 것을 반대한다. 모교에서도 1학년 때 vim을 접하고 프로그래밍도 배우기 어려운 상황에서 그지 같은 에디터(그냥 워드프로세서처럼 쓸 수 있는 IDE나 추천할 것이지)랑 씨름하는 것은 어쨌든 도움이 안 되는 게 아닌가 싶고, 대부분 주변 개발자들을 보면 IDE에 vim 익스텐션을 깔지 vim 그 자체를 쓰는 것도 아닐뿐더러, 그렇게 쓰는 사람도 적은 편이다. vim이 좋다고 설파하는 사람들은 특정 언어와 특정 환경에서 사용하는 케이스가 많고, 그런 특정 상황은 대부분 잘 일어나지가 않는다. 특히 수업에서 Python을 vim으로 짜게 하는 경우가 있는데, 것도 2.7 쓰면서 vim 쓰면 좋긴 한가... 그냥 PyCharm 쓰고 Type 관련한 문제 더 빠르게 잡는 게 편할 것이다.

Comments


Bootstrap-Calendar는 그 이름에서 알 수 있듯이, Bootstrap을 이용한 캘린더 모듈(아님 프레임워크, 아직도 이 둘을 구분을 못한다)이다. 몇몇 css 파일과 js 파일을 적절한 위치에 넣고, 캘린더를 호출하면, 그 자리에 뙇하고 캘린더가 나타나기 때문에 웹에서 캘린더를 올려놓고, 일정 공유를 할 필요가 있을 때 상당히 유용한 녀석이다. 하지만, 실제 사용에서는 약간의 문제가 있다. 깃허브에 올라온 도큐멘트와 예세 소스들 중에 하나도 제대로 된 게 없고, bower로 Bootstrap-Calendar를 설치하면 된다고 "나와있음에도 불구하고" bower를 이용하면 제대로 캘린더를 사용할 수가 없다. 기능이 상당히 많은 관계로 소스 코드가 상당히 복잡한데, 약간의 기능 수정이나 경로 변경을 하려고 하면, 거의 모든 캘린더 모듈과 관련된 css와 js파일들을 들쑤셔야하기 때문에 쉽게 문제가 해결 되지도 않는다. 필자도 1~2 시간 동안 bower로 bootstrap, bootstrap-calendar, jQuery, underscore.js 설치하다 경로 관련으로 엄청나게 삽질을 하였고, 현재 실력으로는  해결 할 수 없는 문제들이라는 걸 깨닫고 github 레포지토리를 클론하였다. 하지만 이렇게 클론을 했음에도 불구하고, 캘린더의 몇몇 기능들을 설명하는 소스코드를 참고를 해서는 개발을 할 수 없다. 예제 소스에 오류가 있고 도큐멘테이션이 제대로 되지 않았기 때문인데, sql 쿼리를 던져 일정을 json 객체로 던지는 php 예제 코드가 제대로 작동을 안하는 게 대표적이다. 처음에는 코드가 잘못 된 줄 모른채 mysql이 잘못 붙은 줄 알고 장대한 삽질을 하였는데, 설마하고 .css와 .js 소스코드를 분석하면서 예제가 잘못 됬음을 알게되었다. 단도직입적으로 도큐멘테이션도 예제도 못 믿겠으니 .css 파일과 .js 파일을 하나하나씩 뜯어가면서 작동 로직을 확인하고, 로직에 맞게 코드를 다 짜야한다. 부트스트랩은 분명 아무 생각 없이 도큐멘트와 예제 코드만 보고 웹 개발하라고 있는 녀석인데, 이건 좀 아닌거 같았고, 결국 이 글을 쓰게 되었다.


Github 주소 : https://github.com/Serhioromano/bootstrap-calendar

캘린더 데모 : http://bootstrap-calendar.azurewebsites.net/


설치를 위해 git를 이용하자. 설치를 원하는 폴더로 이동하고, git clone을 이용하여 받으면 된다. bower를 써도 된다고 하지만, 적극적으로 비추한다. ( 윈도 환경에서 쓰겠다고 한다면, github에 가서 download .zip을 이용하여 zip파일로 받고 압축 해제를 하면 된다. 또한 리눅스 터미널을 모른다면, zip 파일을 받자)

 git clone https://github.com/Serhioromano/bootstrap-calendar 

index.html를 열어보면 이쁘장한 캘린더가 나올 것이다. 이제 여기에 일정을 넣는 방법을 찾아야한다. 일단, 녀석은 js 폴더 아래에 있는 app.js를 불러오면서 calendar를 그린다. app.js를 보면 알겠지만, 이것도 예제 코드고 개발자는 귀찮았는지 바로 적용해서 바로 쓸 수 있게 만들어놓지를 않았다.

	var options = {
		events_source: 'events.json.php',
		view: 'month',
		tmpl_path: 'tmpls/',
		tmpl_cache: false,
		day: '2013-03-12',
		onAfterEventsLoad: function(events) {
			if(!events) {
				return;
			}
			var list = $('#eventlist');
			list.html('');

			$.each(events, function(key, val) {
				$(document.createElement('li'))
					.html('' + val.title + '')
					.appendTo(list);
			});
		},
		onAfterViewLoad: function(view) {
			$('.page-header h3').text(this.getTitle());
			$('.btn-group button').removeClass('active');
			$('button[data-calendar-view="' + view + '"]').addClass('active');
		},
		classes: {
			months: {
				general: 'label'
			}
		}
	};

보면 알 수 있지만, day 가 고정되어있다. index.html을 열면 매일 달력 날짜가 2013년 3월 12일에 고정되어있는 것이 그 이유이다.

	var today = new Date();
	var dd = today.getDate();
	var mm = today.getMonth()+1; //January is 0!
	var yyyy = today.getFullYear();

	if(dd<10) {
		dd='0'+dd
	} 

	if(mm<10) {
		mm='0'+mm
	} 
	var todayis = yyyy+'-'+mm+'-'+dd;

이 코드를 app.js에 추가하자. todayis가 오늘의 날짜를 나타내게 하는 코드다. day: '2013-03-12'를 day: todayis로 바꿔주기만 하면, day의 값는 오늘의 날짜를 가리키게 되고, 결과적으로 index.html을 열 때 요번달 달력이 나오게 된다. 이렇게, 날짜 관련 문제를 대부분 해결 할 수 있다. 이제 일정을 넣는 방법을 알아보자.

{
    "success": 1,
    "result": [
        {
            "id": 293,
            "title": "Event 1",
            "url": "http://example.com",
            "class": "event-important",
            "start": 12039485678000, // Milliseconds
            "end": 1234576967000 // Milliseconds
        },
        ...
    ]
}

이것이 맨 처음 나온 json 객체 예제이다. 이 소스는 약간만 수정하면 잘만 작동을 한다. 일단, 여기서 눈 여겨봐야할 점은 success : 1 과 result 값들이다. 뭔 의도인지 몰라도 개발자는 success:1 가 맨 처음에 있어야만, 이후의 json 객체들을 다 읽도록 하였다. result 값은 id, title, url, class, start, end 로 구성이 되어있다. id는 일정 구분을 하는 프라이머리키 (로 추정), title은 일정 제목, url은 일정 title을 클릭했을 때 리다이렉트 되는 주소이다. 이 때, http://를 안 붙이면 "현재 위치한 도메인" + "/" + url 값 으로 리다이렉트 된다. "url" : "250" 이고, 캘린더의 주소가 bengi.kr/index.html 이라면, bengi.kr/250으로 이동을 하는 것이다. class는 calendar.css에 정의된 컬러셋을 불러온다. event-important 는 빨간색으로, event-warning은 주황색으로 캘린더에 점이 찍혀져 나온다. (직접 해보면 이해가 쉽다) 뭐 다른 컬러셋 설정도 있으니, calendar.css를 뜯어볼 것을 추천한다. 또한, 당연하게도 css 파일을 수정해서 컬러셋을 추가할 수도 있다. start와 end는 timestamp로 일정 시작 시간과 일정 마감 시간 받아서 저장하는 부분인데, 이것을 손으로 계산하는 일은 엄청나게 귀찮은 일이라는 건 한 눈에 봐도 알 수 있다. Mysql에 붙여서 이 캘린더를 관리하는 이유가 이것 때문이다. Mysql 에서 timestamp 객체를 생성하고, 날짜와 시간을 지정해주면 밀리초 단위로 자동으로 변환시켜주니, 실제로 복잡한 계산을 할 필요는 없다.

<?php
$db    = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
$start = $_REQUEST['from'] / 1000;
$end   = $_REQUEST['to'] / 1000;
$sql   = sprintf('SELECT * FROM events WHERE `datetime` BETWEEN %s and %s',
    $db--->quote(date('Y-m-d', $start)), $db->quote(date('Y-m-d', $end)));

$out = array();
foreach($db->query($sql) as $row) {
    $out[] = array(
        'id' => $row->id,
        'title' => $row->name,
        'url' => Helper::url($row->id),
        'start' => strtotime($row->datetime) . '000',
        'end' => strtotime($row->datetime_end) .'000'
    );
}

echo json_encode(array('success' => 1, 'result' => $out));
exit;

DB에 캘린더를 연동하는 예제 소스이다. 소스를 보면 알겠지만 ?> 가 존재하지 않는다. 일단 여기부터 낌새를 알아차려야하는데, 앞서 말했듯이 이 소스는 제대로 작동을 안한다. 또한, class 값을 안 긁어오기에 각 일정마다 색을 입히지를 못한다. PDO가 제대로 mysql에 붙지도 않는다. 제대로 mysql을 붙였다고 하더라도 sql 쿼리가 잘못되어 이 달의 모든 일정을 출력하지 못한다. 여러모로 골 때리는 일이 아닐 수 없다. 그래서, mysqli를 이용해서 DB를 붙이고, 코드를 다시 짜는 쪽으로 방향을 잡았다.


일단, app.js에서 어떤 파일을 끌고올지 설정을 하자. 디폴트 설정은 위에서 볼 수 있듯이 event.json.php이다. 그냥 귀찮다면, index.html있는 폴더에 event.json.php 파일을 만들면 된다.

<?php
$my_db = new mysqli("localhost",아이디,비밀번호,테이블이름);
$res =mysqli_query($my_db,"SELECT * FROM Calendar");

$out = array();
while($data = mysqli_fetch_array($res)) {
	$out[] = array(
		'id' => $data['id'],
		'title' => $data['name'],
		'url' => $data['url'],
		'start' => strtotime($data['datetime']).'000',
		'end' => strtotime($data['datetime_end']).'000',
		'class' => $data['class']

);
}
echo json_encode(array('success' => 1, 'result' => $out));
exit;
?>

요로코롬하게 입력을 하면 된다. 보면 알겠지만, Calendar 테이블에, id, name, url, datetime, datetime_end, class를 긁어오는 소스이다. 즉, mysql에 Calendar 테이블에 id, name, url, datetime, datetime_end, class 컬럼이 있어야하는 건 당연한 일 일 것이다. 필자의 경우 이렇게 테이블을 잡았다.



그리고 결과는 이렇다.


'일상생활 > 코딩코딩' 카테고리의 다른 글

Vim 도대체 왜 쓰는가  (13) 2019.05.04
me2day 2.3.3 ipa  (0) 2013.02.12
화면 동영상 캡쳐 프로그램들..  (0) 2007.05.16

Comments


[me2day][iOS_v4.0_and_above][i-funbox.com].ipa


Comments

동영상 캡쳐를 해서 무비 트레일러나, 뮤직비디오를 만드려고하는데 제대로 된것을 찾을 수가 없었습니다.
프리웨어라고해도 시스템과 충돌을 일으키고, 다이렉트 가속 때문에 작동이 안되고...
안습 그 자체 였습니다.
일단 제컴퓨터에서 작동이 되든 안되든 2가지 프리웨어와 1가지 쉐어웨어 프로그램을 소개해보겠습니다.

Comments