Script / CSS

G1sUtil.js

G1sBlogger.js

G1sNavigationList.js

G1sCode

Posts List


2017년 6월 10일 토요일

[Javascript] 초성검색을 구현해보자 - with Hangul.js

이번 프로젝트에서 제 파트는 아니지만 초성검색을 Javascript로 구현해야 하는 요건이 있어서 구글링을 한 결과,
힌트를 주는 블로그는 몇개 있으나 구현되어 있는 소스가 없어 한번 만들어 보았습니다.

마침 Github에 공유 된 Hangul.js 라는 훌륭한 라이브러리가 있어 해당 라이브러리를 사용하였습니다.
Hangul.jsMIT 라이센스를 따르고 있네요.
MIT 라이센스는 가장 제약이 적은 라이센스로 저작권 표시 의무만을 가지고 있습니다.
라이센스 링크는 https://github.com/e-/Hangul.js/blob/master/LICENSE 입니다.


우선 Hangul.js는 한글을 분해/조립하는 disassemble, assemble 함수를 기본으로 동작하는 라이브러리로 search 함수를 제공하고 있습니다.
이 search 함수에 대해서 살펴보면...
우선 라이브러리의 REDME 에는 아래와 같이 설명하고 있습니다.

Hangul.search(a:string, b:string)는 문자열 a가 문자열 b를 포함하는지 검사합니다. 이때 포함관계는 '두벌식 키보드 기준으로 a문자열을 입력할 때 누르는 키들의 배열이 b문자열을 입력할 때 누르는 키들의 배열을 포함한다'로 정의합니다. 반환값이 0보다 크거나 같다면 포함합니다.
https://github.com/e-/Hangul.js#hangulsearch

즉, 검색어 'ㄷ'로 검색을 하였을 경우,
'닭'과 같이 초성의 결과를 검색이 가능하지만, '갇' 과 같이 값이 종성에 있을 경우에도 검색이 됩니다.

또한 초성이 두개이상인 검색어 'ㄷㄱ'에 대해,
초성 검색을 통해 '달걀'을 검색 할 수 없으며, 오히려 '갇가'와 같은 의도치 않은 결과가 검색 될 수 있습니다.

이에따라 해당 함수를 수정해 초성검색이 가능하도록 만들어 보았습니다.

제가 만들고자 하는 초성검색 기능은 다음과 같습니다.

  • 검색어가 초성으로만 이루어져 있을 경우 초성검색을 한다.
  • 검색어가 초성으로만 이루어져 있지 않을 경우 기존 Hangul.search 기능을 사용한다.
  • 초성검색은 문자의 초성만 추출한 후 검색어의 초성과 indexOf를 통해 판단한다.

간단하게 정리가 되네요.

위 조건을 만족하기 위해서 필요한 로직은 세가지로, 아래와 같습니다.
- 문자열이 초성으로만 이루어져있는지 판단한다. -> Hangul.isConsonant 이용
- 한글 검색 - Hangul.search
- 문자열의 초성만 추출 - Hangul.disassemble 이용

기존 Hangul.js로 모두 해결이 가능하군요.
자세히 설명하기에는 너무 길어 질 것 같구요.
수정한 Hangul.js 소스는 아래 링크를 참고하시기 바랍니다.

수정 소스 : https://github.com/g1s/Hangul.js/blob/master/hangul.js
수정 내역 : https://github.com/g1s/Hangul.js/commit/e1db92721a1e4cc98c4ef15337c2f8a9c29ebced

이를 사용하는 샘플소스는 다음과 같습니다.


샘플열기

2017년 6월 3일 토요일

[자전거따라] 시화방조제를 달려 삼도여행. 대부도라이딩


영산강을 다녀온지도 한달이 지났습니다.
작년말부터 확실히 자전거를 타는 횟수가 줄고있네요.
이번에도 즉흥적으로 자전거여행을 떠납니다.
목적지는 오이도역에서부터 시화방조제를 넘어 대부도, 선재도, 영흥도까지.
확실히 체력이 줄은것이 느껴지네요.



어젯밤 즉흥적으로 정한 여행답게 준비가 부실합니다.
늦잠에 부랴부랴 준비해서 1시간30여분에 걸쳐 지하철을 타고 오이도역에 도착하니 어느덧 시간은 12시가 넘어가네요.


바로 시화방조제까지 이동합니다.
네이버 지도의 길안내를 따라가니 도시를 흐르는 하천을 따라 자전거길이 있네요.
신호등이 많은 도로로 달리지 않아도 되어 편하긴 하지만 길상태가 썩좋지는 않습니다.


드디어 시화방조제 자전거길에 진입.
지도상으로는 방조제 좌우측으로 자전거길이 있는것으로 나오지만
우측길은 현재 통행이 금지되어있네요.


직선으로 뻥뚫린 곧은 길.
하지만 길상태가 썩 좋은 편은 아닌데다
바다 한가운데를 달리는 만큼 바닷바람이 장난이 아니네요.
아무리 달려도 속도가 나지 않습니다.


좌측으로는 통행이 금지되어 차량 하나 없는 도로도 있네요.
잘닦인 도로에 차도 하나 없는 도로를 보니 내려가서 달리고 싶군요. ㅎㅎ

힘들게 바람을 뚫고 바다가운데를 달리길 한참.
멀리 전망대가 보이기 시작합니다.


조력발전소와 전망대 등이 있는 휴게소가 하나 있네요.


휴게소를 지나 멀리 보이기 시작하는 풍력발전기를 향해 달리면 드디어 대부도 도착합니다.
바다를 빠져나와 섬으로 들어가니 바람이 좀 줄어듭니다.

확인해보니 시화방조제를 달리는데 시속이 10km/h 밖에 안나왔네요.
직선으로 뻥 뚫린 자전거길이라 시원하게 달릴 수 있을 줄 알았더니 바닷바람에 힘만 빠져버렸네요.


대부도에 들어가자마자 우측으로 바로 해수욕장이 하나있네요.
방조제를 넘느라 떨어진 체력도 채울겸 잠시 바다를 구경하며 쉬어갑니다.
이제 6월초인데 벌써부터 텐트와 사람들로 해변이 가득찼네요.


그러고보니 어느덧 점심시간이 한참 넘었네요.
마침 바로 해수욕장옆 식당들중에 하나를 골라 들어갑니다.


바다가 바로 옆으로보이는 창가에 자리를 잡고 음식을 기다리며 바다구경을 합니다.


음식이 나오는데 꽤많은 시간이 걸리네요.
그러는 사이 어느덧 넓은 식당안엔 하나둘 손님이 들어차기 시작합니다.

덕분에 충분히 쉬며 바닷구경을 하고 있는사이
드디어 주문한 음식이 나오기 시작합니다.


동동주에 해물파전. 회덮밥. 조개탕은 서비스입니다.
바다를 끼고 바닷바람을 맞으며 마시는 동동주의 맛이 끝내줍니다.

식사를 하는 사이에 어느덧 바닷물이 서서히 빠지기 시작합니다.
갯벌에 나와 즐기는 사람들과 갈매기에게 먺이를 주며 노는 사람들의 모습도 보이네요.


배를 채웠으니 이제 다시 출발해야 할 때입니다.
자전거에 올라 도로를 따라 다음 목적시 선재도로 향합니다.
지나는 길에 대부도를 지키고 있는 히어로들과도 만났네요. ㅎㅎ


아일랜드 CC 앞에서 잠깐 휴식.
지도를 보니 여기만 돌아서 내려가면 선재도를 건너는 다리가 나오네요.


다리를 건너 선재도로.


선재도로 들어가자마자 바로 좌측으로 하나의 섬이 보이네요.
썰물때만 바닷길이 열린다는 목섬입니다.
갯벌위를 운행하는 트랙터 버스도 보이네요.


이제 다시 마지막 목적지 영흥도로 향합니다.
선재도에는 도로 우측으로 자전거길이 잘 닦여 있네요.


영흥대교를 지나 영흥도에 도착.
영흥도 초입에서 안으로 조금만 들어가면 버스터미널을 만날수 있습니다.
잠시 화장실도 이용할겸 쉬면서 보니 오이도역까지 운행하는 버스들이 다니네요.


영흥도에 왔다고 그냥 갈 수는 없으니 가까운 곳에 있는 십리포해수욕장으로 향합니다.
차가 많진 않지만 그만큼 관리가 안되어 갈라지고 깨진 도로를 달려 해수욕장에 도착합니다.
여기도 역시 긴 백사장위로 텐트들이 가득 자리를 차지하고 있네요.
어느덧 바닷물이 다시 차오르고 있네요.


마지막 목적지인 만큼 잠시 구경이나 할겸 해변을 거닐다보니 마주한 나무 데크 산책로.
바다를 따라 산책로를 잘 만들어 놓았네요.


이제 돌아가야 할 시간이네요.


그대로 왔던길을 따라 돌아오는 길..
어느덧 7시가 넘어 석양이 지기 시작합니다.
마침 대부도를 들어오자마자 만났던 방아머리해수욕장에 도착해 석양을 감상합니다.




바다로 지는 낙조는 정말 오랜만이네요.
석양이 지는 하늘은 언제봐도 아름답지만 그 중에서도 바닷가에서 보는것만한게 없죠.

이제다시 바다위를 달려 돌아가는 것만 남았네요.
돌아오는 길에는 대부도로 향하면서 봤던 아래쪽의 통행이 제한된 도로위를 달립니다.
앞에서 부는 바람도 없고, 차도 없고, 잘닦인 도로위를 순풍을 맞으며 순식간에 육지에 도착합니다.


돌아오는 길은 친구와의 저녁약속때문에 오이도역이 아닌 안산까지....
추가로 달리니 전체 92km를 달렸네요. ㅎ

2017년 5월 28일 일요일

[Theme2017] 테마 적용하기

Master/Detail 2017 테마에 대한 4번째 글입니다.
이번에는 제가 만든 테마를 적용하는 방법에 대해 포스팅을 하도록 하겠습니다.

우선 블로거 관리자 메뉴에서 테마로 가서 현재 테마를 백업받으시기 바랍니다.




이제 본격적으로 테마를 적용해 보겠습니다.

1. Master/Detail 2017 테마 적용

얼마전 블로그 소스들을 Github에 업로드 하였는데요.
아래 경로에서 xml 파일을 다운받겠습니다.

https://github.com/g1s/blog.g1s.kr/blob/master/G1sBlog/Theme/MasterDetail2017/MasterDetail2017.xml

위 링크를 타고 이동해서 Raw 버튼를 우 클릭 후 다른이름으로 저장합니다.


다음 다시 블로거 관리메뉴 테마에서 다운로드한 xml 파일을 업로드 해주시면 됩니다.


업로드를 하시면 우선 기본적인것은 적용이 되었을 텐데요.
여기서 저와 같이 적용할지 아니면 각자 원하는 위젯들을 적용하실지는 여러분의 선택사항입니다.
우선 저는 제 위젯들을 하나씩 설치해 나가겠습니다.

2. 기본 js 세팅

레이아웃으로 가서 상단 Hidden 영역에 2개의 기본 스크립트 위젯들을 세팅하겠습니다.
Script / CSS 는 필요한 것이 있다면 설정을 해 나가는 곳으로...
필요없다면 지워주셔도 됩니다.


해당 위젯들을 열어보시면 내용이 모두 비어 있을 텐데요.
이를 채워줘야 합니다.
역시 Github로 이동합니다.

G1sUtil.js : https://github.com/g1s/blog.g1s.kr/blob/master/G1sBlog/common/js/G1sUtil.js
G1sBlogger.js : https://github.com/g1s/blog.g1s.kr/blob/master/G1sBlog/common/js/G1sBlogger.js

이번에는 소스를 다운받으실 필요까지는 없고, 소스를 복사하시기만 하면 됩니다.


전체 소스를 선택 후 복사합니다.
그리고 다시 블로거 레이아웃의 G1sUtil.js 편집을 연 후 스크립트 태그를 만든 후 그 안에 복사한 js 소스를 넣어줍니다.

<script>
<-- 붙여넣기
</script>


저장 한 후 G1sBlogger.js 도 동일하게 붙여넣습니다.

3. 카테고리 메뉴 적용

다음은 카테고리 메뉴를 적용 할 건데요.
블로거의 링크목록 가젯을 이용하여 링크를 구성하고, 
G1sNavigationList 위젯을 이용하여 해당 링크를 배치할 겁니다.


우선 링크목록 가젯을 세팅합니다.


사이트 이름과 URL을 설정해 주시면 되는데요.
사이트 이름과 정렬에 주의해 주세요.

메뉴는 2Depth 메뉴로 구성이 됩니다.

1Depth 메뉴, 즉 기본적으로 노출되는 메뉴는 일반적인 이름을 쓰시면 되고
2Depth 메뉴는 제일 앞에 언더바('_')를 하나 추가해 주시기 바랍니다.

1Depth 메뉴가 상위메뉴가 되고 그 밑에 있는 2Depth 메뉴는 하위 메뉴가 됩니다.

다음으로 G1sNavigationList 위젯을 세팅하겠습니다.
아래 Github 링크로 이동해 주세요.


이번에는 별다른 작업없이 소스 전체를 복사해 가젯에 붙여넣으시면 됩니다.


좌측의 카테고리가 우측처럼 정렬되었습니다.
1Depth 메뉴에 마우스를 올리거나, 우측 + 버튼을 누를경우 2Depth 메뉴가 열리게 됩니다.

4. Google OAuth 적용

구글 로그인 여부를 확인하고 로그인 안된 방문자에게 로그인 버튼을 노출하기 위해 구글 OAuth를 적용하였습니다.
하지만 이번 페이지에 적용하는 법을 모두 쓰기에는 글이 길어질 것 같네요.
우선 간단하게 소개하고, 자세한 것은 별도 포스팅으로 포스팅 하도록 하겠습니다.


역시 아래 Github 소스를 복사하여 붙여넣습니다.



소스중에 위와같이 Google Oauth ClientKey를 발급 후 <head> 적용 필요. 라는 글이 있을 텐데요.
네 다음 구글 개발 콘솔에서 Google Oauth ClientKey를 발급받아야 합니다.


키를 발급받은 후에는 

블로거 관리메뉴 > 테마 > html 편집으로 이동해서
<head> 태그부분에 주석되어있는 google-signin-clientk_id 메타태그의 주석을 푼 후
[YOUR_SECURE_KEY::Google OAuth ClientKey] 부분을 발급받은 Client Key를 넣어주시면 됩니다.


5. Feature 이미지 적용

다음은 블로그의 주요 포스트를 이미지 위주로 보여주는 Feature 이미지입니다.
정확히는 특정 태그를 보여주도록 되어 있습니다.


역시나 Github에서 소스를 복사해서 붙여넣으면 됩니다.

https://github.com/g1s/blog.g1s.kr/blob/master/G1sBlog/widget/feeds/G1sFeature.html

소스를 붙여넣고 가장 하단에 보시면 아래와 같이 특정 태그의 Feed를 가져오도록 되어있는데요. 태그만 원하시는 태그로 변경해주시면 됩니다.


다음과 같이 지정한 태그의 이미지 포스트 3개가 노출됩니다.


6. G1sMainPost 적용

주요 소식도 Feature와 마찬가지로 지정한 태그의 포스트를 가져와서 인기소식의 UI 형태로 만드는 것입니다.


역시 Github에서 소스를 복사 후 태그만 바꿔주시기 바랍니다.

https://github.com/g1s/blog.g1s.kr/blob/master/G1sBlog/widget/feeds/G1sMainPost.html


다음과 같이 주요소식과 동일한 형태로 포스트를 가져와 그려줍니다.
위젯 타이틀은 적당히 괜찮은 것으로 바꿔주시면 됩니다.
저는 '주요소식' 이라는 타이틀을 적용하였습니다.


7. G1sPostList 적용

이 위젯은 2012년에 만들어서 아직까지 잘 쓰고 있는 위젯입니다.
자세한 내용은 아래의 포스팅을 참고하셔도 좋을 것 같네요.

http://blog.g1s.kr/2012/02/blogger-label-posts-list.html



위 링크의 포스팅에 있는 소스를 사용하셔도 되며,
현재 제가 사용하고 있는것은 거기에 추가로 수정이 된 버전으로
아래 Github에 최신 소스가 있습니다.

https://github.com/g1s/blog.g1s.kr/blob/master/G1sBlog/widget/feeds/G1sPostList.html


역시나 복사/붙여넣기만 해주시면 됩니다.
이 소스가 만들어진지 오래되다 보니 그전에는 별문제 없겠지.. 라고 생각했던 부분에서 약간의 문제가 있어서 언젠가 개선된 버전을 만들려고 생각중인데요.

포스트가 30페이지 즉 150개 이상 일경우 그 이상의 포스트를 보여주지 못한다는 겁니다.
언제 그렇게 포스팅을 하려나 했는데 어느덧 포스트가 150개를 훌쩍 뛰어넘었네요.

혹시라도 개선을 하게 된다면 이곳에도 업데이트 하겠습니다.



여기까지....
따로 언급하지 않은 부분인 CCL이나 광고영역은 각자 원하시는데로 적용을 하시면 됩니다.
물론 다른 위젯들도 더 추가하거나 원하시는데로 수정을 하시면 될 테구요.

아, 참고로 CCL은 아래 경로로 가시면 CCL 적용을 위한 소스를 발급받으실 수 있습니다.