Dev Blog

스크립트 & 소스코드 공유

실무에서 유용하게 쓰는 스크립트와 코드 조각을 블로그 게시판으로 저장하고 공유합니다.

108건의 글

MySQL에서 중복 데이터 모두 찾기 (GROUP BY + HAVING)

MySQL에서 특정 필드의 중복된 값을 모두 찾아내는 방법을 정리했다. GROUP BY와 count()로 필드값별 건수를 집계하고, HAVING 절에서 count 결과가 n 이상인 항목만 거르는 쿼리 예제를 보여준다. 중복 횟수 2개 이상인 데이터를 확인하는 실제 실행 결과 표도 함께 포함되어 있다.

SELECT 필드명, count(*) FROM 테이블명 GROUP BY 필드명
mysql> SELECT t1, count(*) FROM test GROUP BY t1

중복된 갯수가 n개 이상인 것 찾기
SELECT 필드명, count(*) as 변수명 FROM 테이블명 GROUP BY 필드명 HAVING 변수명>n

mysql> SELECT t1, count(*) as num FROM test GROUP BY t1 HAVING num>1;
t1 num
tulip pink 2
라일라 2

2 rows in set (0.01 sec)

주기적으로 PHP 파일 실행하기 (crontab으로 cron.php 돌리기)

리눅스 crontab을 이용해 PHP 파일을 주기적으로 실행하는 방법이다. crontab -e 명령으로 에디터를 연 뒤, 한 시간에 한 번씩 wget으로 http://도메인/cron.php를 호출하는 "0 * * * * wget -O - -q -t 1 URL" 한 줄을 추가하면 정해진 시간마다 PHP 코드가 자동으로 실행된다. cron.php에는 주기적으로 실행할 코드를 넣어두면 된다.

크론탭에 추가

# crontab -e

한시간에 한번씩 원하는 페이지를 실행시키는 코드

0 * * * * wget -O - -q -t 1 [http://domain.com/cron.php](http://domain.com/cron.php)

위와같이 한 줄을 추가하게되면
순서대로 0분 매시간 매일 매월 매요일 이 될 때마다 (다시말해 1시간에 1번) php코드를 실행시키게 된다.
cron.php에는 1시간에 1회 실행될 코드를 넣어두면 된다.

자바스크립트 배열 내장 함수 정리 (join, reverse, sort, concat, slice, spli…

자바스크립트 배열의 주요 내장 함수를 예제와 함께 정리한 글이다. join과 split으로 배열·문자열 변환, reverse로 순서 뒤집기, sort 정렬, concat 병합, slice로 부분 배열 추출, splice로 원소 삽입·삭제하는 방법을 설명하고, 원본 배열이 변경되는지 여부와 음수 인덱스 처리 등 주의할 점을 코드 예시로 보여준다.

join()

//배열의 모든 원소를 문자열로 변환후 구분자로 이어 붙여서 반환.(구분자 기본값으로는 콤마(,)가 사용됨)
var arr = new Array(1, 2, 3);
var str = arr.join();
str : "1,2,3"

String.split()

//Array.join() 함수와 반대되는 기능을 한다. 구분자를 입력받아 해당 구분자로 문자열을 자른뒤 배열로 반환한다
var str = "1,2,3";
var arr = str.split(",");
arr : ["1", "2", "3"]

reverse()

//배열 안의 원소들의 순서를 뒤집는다. 주의할 점은 뒤집은 결과를 반환하는 방식이 아닌 함수 내부에서 변환이 진행 된다는 점이다
var arr = new Array(1, 2, 3);
arr.reverse();
arr : [3, 2, 1]

sort()

//배열 안의 원소들을 정렬하여 반환한다. reverse() 함수와 마찬가지로 배열 내에서 직접 수행된다.
//별도의 전달 인자 없이 호출할 경우 배열 안의 원소들을 알파벳 순으로 정렬한다.
//배열 안의 원소가 문자열이 아닐 경우 임시로 문자열 변환 작업이 수행된다.
var arr = new Array("banana", "cherry", "apple");
arr.sort();
arr : ["apple", "banana", "cherry"]

concat()

//기본의 배열원소 뒤에 전달 인자들을 추가한 배열을 반환한다. 허나 중복하여 중첩된 배열은, 원소로써 분리되어 나오지 않음을 주의 하자.
var arr = new Array(1, 2, 3);
arr.concat(4, 5) // arr : [1, 2, 3, 4, 5]
arr.concat([4, 5]) // arr : [1, 2, 3, 4, 5]
arr.concat([4, 5], [6, 7]) // arr : [1, 2, 3, 4, 5, 6, 7]
arr.concat([4, [5, [6, 7]]) // arr : [1, 2, 3, 4, 5, 6, 7]]

slice()

//배열의 일부, 혹은 부분배열을 반환한다. 전달인자가 음수일 경우 배열의 마지막 원소에서 상대적인 위치로 배열 원소들을 지정한다.
var arr = new Array(1, 2, 3, 4, 5);
arr.slice(0, 3); // arr : [1, 2, 3]
arr.slice(3); // arr : [4, 5]
arr.slice(1, -1); // arr : [2, 3, 4]
arr.slice(-3, -2); // arr : [3]

splice()

//배열에 원소를 삽입하거나 원소를 제거하려고 할때 사용하는 함수이다. 하지만 본 함수는 slice(), concat() 과는 달리 변경 결과를 반환하는 방식이 아닌 배열 내부에서 수행된다.
// 삭제
var arr = new Array(1, 2, 3, 4, 5, 6, 7, 8);
arr.splice(4); // [5, 6, 7, 8] 반환, arr : [1, 2 ,3 ,4]
arr.splice(1, 2); // [2, 3] 반환, arr : [1, 4]
arr.splice(1, 1); // [4] 반환, arr : [1]

// 삽입
var arr = new Array(1, 2, 3, 4, 5);
a.splice(2, 0, 'a', 'b'); // []반환, arr : [1, 2, 'a', 'b', 3, 4, 5]
a.splice(2, 2, [1, 2], 3); // ['a', 'b']반환, arr : [1, 2, [1, 2], 3, 4, 5]

push(), pop()

//배열을 스택처럼 조작할 수 있다. push() 는 원소의 삽입 pop() 은 원소의 제거를 수행하며, 두 함수 모두 배열의 끝에서 연산을 수행한다. 
//배열 자체에서 연산이 수행되며 pop() 함수의 경우 제거한 원소를 반환하는 특징이 있다.
var arr = new Array()
arr.push(1, 2); // arr : [1, 2]
arr.pop(); // arr : [1], 2 반환
arr.push([4, 5]); // arr : [1, [4, 5]]
arr.pop(); // arr : [1], [4, 5] 반환
arr.pop(); // arr : [], 1반환

unshift(), shift()

//push(), pop() 과는 다르게 배열의 끝이 아닌 맨 앞에서 연산이 이루어진다. unshift() 의 경우 새로운 배열의 길이를, shift() 는 제거한 배열원소를 반환한다.
var arr = new Array();
arr.unshift(1); // arr : [1], 1 반환
arr.unshift(22); // arr : [22, 1], 2 반환
arr.shift(); // arr : [1], 22 반환
arr.unshift(3, [4, 5]); // arr : [3, [4, 5], 1], 3 반환
arr.shift(); // arr : [[4, 5], 1], 3 반환
arr.shift(); // arr : [1], [4, 5] 반환
arr.shift(); // arr : [], 1 반환

검색엔진 크롤링과 인덱싱의 차이 (robots.txt vs meta robots)

검색엔진의 크롤링(문서 수집)과 인덱싱(색인)의 차이를 설명하고, robots.txt 파일로 크롤링을 제어하는 방법과 meta robots 태그로 인덱싱을 제어하는 방법을 자세히 정리했다. 전체 차단·허용, 특정 폴더·페이지·검색엔진별 차단 예시, 크롤러 허용/인덱스 차단 등 조합별 동작 방식과 인덱스 삭제에 가장 효과적인 방법까지 다룬다.

검색엔진의 크롤링과 인덱싱의 차이 (robots.txt 파일과 meta robots 태그의 차이점)
크롤링 제어는 robots.txt
인덱싱 제어는 < meta name="robots" content="noindex">

검색엔진이 검색 키워드에 대한 검색결과를 사용자한테 제공하기 위해서는 크롤러가 끊임없이 온라인 상의 문서를 수집해야하고, 크롤러가 수집한 문서를 인덱서가 잘 정리해서 인덱스 서버에 색인해 둬야 합니다.
많은 분들이 헷갈려 하는 부분인데 크롤러나 인덱서는 서로 하는일이 약간 틀립니다.
말그대로 크롤러는 단순히 사이트와 사이트 사이의 링크를 타고다니며 문서를 수집하는 역할만 하며, 인덱서는 수집된 문서를 검색엔진이 사용자에게 결과물을 좀더 빠르고 쉽게 제공할수 있도록 색인 또는 인덱스하는 역할을 합니다.

마찬가지로 크롤러를 제어하는 방법과 인덱싱을 제어하는 방법이 다릅니다.
크롤링을 제어하려면 사이트의 루트 디렉토리에 robots.txt 파일을 사용해서 제어해야 하고,
인덱싱을 제어하려면 각각의 페이지 내에 < meta name="robots" content="noindex,nofollow"> 같은 메타 로봇 태그를 사용해서 제어해야 합니다.

robots.txt 파일을 사용해서 크롤링을 제어하는 방법

기본적으로 robots.txt 파일은 사이트의 루트 디렉토리에 저장해 둡니다.
예를 들면 브라우저에 http://www.seo-korea.com/robots.txt 를 입력하면 파일을 읽을수 있어야 합니다.
http://www.seo-korea.com/myfolder/robots.txt 는 유효하지 않습니다.

검색엔진의 크롤러로 부터 모든 문서수집을 차단하려면 아래와 같은 내용을 robots.txt에 삽입합니다.
User-agent: *
Disallow: /

반대로 모든 문서를 허용하려면
User-agent: *
Disallow:

특정 폴더만을 차단하려면
User-agent: *
Disallow: /members/
Disallow: /search/
Disallow: /images/

특정 검색엔진 크롤러를 차단하려면 (구글만 차단)
User-agent: Googlebot
Disallow: /

또는 특정 검색엔진 크롤러만 허용하려면 (구글만 허용)
User-agent: Google
Disallow:
User-agent: *
Disallow: /

특정 페이지를 차단하려면
User-agent: *
Disallow: /members/personal_info.html

robots.txt 파일에 사이트맵 명시
User-agent: *
Disallow:
Sitemap: http://www.seo-korea.com/sitemap.xml

meta robots 태그를 사용해서 인덱싱을 제어하는 방법

< meta name="robots" content="..." /> 태그는 인덱싱을 제어하는데 사용되며 각 페이지의 < head>와 사이에 삽입합니다.
사용 가능한 content 로는 index, noindex, follow, nofollow 가 있습니다.
index와 noindex는 페이지의 인덱스 여부를 말해주며 follow, nofollow는 페이지내의 링크를 크롤러가 따라갈수 있느냐 없느냐의 여부를 말해줍니다.
index와 noindex중 하나 그리고 follow와 nofollow중 하나를 섞어서 함께 사용할수 있습니다.

웹 문서에 < meta name="robots"> 태그의 기본값은 index와 follow이며 아래와 같은 형식으로 사용할수 있습니다.
< meta name="robots" content="index,follow" />
< meta name="robots" content="index,nofollow" />
< meta name="robots" content="noindex,follow" />
< meta name="robots" content="noindex,nofollow" />

robots.txt 파일과 meta robots 태그를 혼용해서 사용하는 경우

위의 두가지를 잘 사용하면 검색엔진의 사이트 접근을 효과적으로 차단하거나 허용할수 있고, 검색엔진 결과에 인덱스 되는것 또한 컨트롤 할수 있습니다.
하지만 robots.txt와 meta robots 태그의 역할을 잘못 이해해서 원하지 않는 결과를 초래할수도 있습니다.
모두 공개하기 위해 크롤러와 인덱스를 모두 허용해 놓았다면 별문제 없겠지만 다른 경우의 수에서는 원하지 않는 결과가 나올수 있으니 유의하시기 바랍니다.

크롤러 허용, 인덱스 차단

User-agent: * Disallow: < meta name="robots" content="noindex" />

robots.txt에 크롤러의 접근을 허용했지만 meta robots 태그에 인덱스를 허용하지 않은 예입니다.
크롤러는 문서만 수집할뿐 검색엔진에 문서의 인덱스 여부는 meta robots 태그가 결정합니다.
그러므로 이같은 경우는 크롤러가 방문을해서 수집하기는 하지만 meta robots 태그에서 인덱스를 차단한것을 인지하고 인덱스하지 않으며, 혹시라도 인덱스가 되어있으면 자동 삭제하게 됩니다.
이 방법이 검색결과에서 문서를 삭제하는데 가장 효과적인 방법입니다.

크롤러 차단, 인덱스 허용

User-agent: * Disallow: / < meta name="robots" content="index" />

위와 같은 경우 인덱스는 허용했지만 크롤러를 차단하고 있습니다.
크롤러는 사이트의 robots.txt파일을 먼저 읽기 때문에 일단 크롤러는 컨텐츠를 읽을수 없습니다.
그러므로 인덱스가 허용되었는지 안되었는지 크롤러는 알수 없습니다.
하지만 robots.txt파일에서 크롤러를 차단했음에도 불구하고 페이지가 인덱스되어 검색결과에 나타나는 경우가 종종 있습니다.
이러한 경우는 다른 사이트에서 들어오는 인바운드 링크에 의해 인덱스가 만들어진 경우입니다.
대부분의 검색엔진들이 실제 페이지를 크롤링하지 않고도 링크를 통해서 해당 페이지의 색인을 만들수 있기때문에 가능합니다.
이럴경우 검색결과의 타이틀에는 문서의 타이틀 대신 URL이 나오게 되고 스니펫(검색결과의 문서요약)에는 아무것도 나오지 않게 됩니다.
결국 robots.txt 파일로 크롤링을 차단한다고 해도 그것이 검색결과에 문서가 인덱스 되는것을 차단시키지는 못하며, 인덱스를 허용해놓아도 이를 완벽하게 인덱싱 하지 못합니다.

크롤러 차단, 인덱스 차단

User-agent: * Disallow: / < meta name="robots" content="noindex" />

위의 경우는 크롤러와 인덱스 모두를 차단한 상황으로 일단 크롤러가 차단되었기 때문에 페이지 컨텐츠를 읽지 못합니다.
그러므로 인덱스를 차단하도록 설정을 해놓아도 크롤러는 이를 알수 없습니다.
하지만 [크롤러 차단, 인덱스 허용]의 경우와 마찬가지로 인바운드 링크들로 인해 문서가 인덱스되는 경우가 있습니다.
이렇게 검색결과에 인덱스된 경우 또한 검색결과의 타이틀에는 URL이, 스니펫(검색결과의 문서요약)에는 아무것도 나오지 않게 됩니다.
결국 크롤링과 인덱싱을 모두 차단하도록 설정을 했더라도 크롤링은 차단하되 인덱싱을 막지는 못합니다.

검색엔진에서 인덱스를 없애기 위해 가장 좋은 방법은 크롤러를 허용하고 인덱스를 차단하는 것입니다.
그래야 크롤러가 인덱스를 차단하라는 것을 감지할수 있고 이를 검색결과에 반영하게 됩니다.
그렇기 때문에 크롤링과 인덱싱의 역할, 그리고 robots.txt 파일과 meta robots 태그의 사용방법을 잘 알아야 하며, 인덱스의 차단하는 역할은인덱스의 차단하는 역할은
< meta name="robots" content="noindex"> 가 robots.txt보다 우위에 있다는걸 숙지해야 합니다.

jQuery로 Select(콤보박스) 값 가져오기·설정·옵션 추가/삭제

jQuery를 이용해 Select(콤보박스) 요소를 다루는 방법을 정리한 글이다. change 이벤트 처리, 선택된 option의 텍스트·값·인덱스 가져오기, 원하는 항목을 선택 상태로 설정하는 방법, append와 prepend로 옵션을 추가하고 remove로 특정 옵션을 삭제하는 방법, empty()로 전체 옵션을 비우는 코드를 예제와 함께 담고 있다.

语法解释:

$("#select_id").change(function(){//code...}); //为Select添加事件,当选择其中一项时触发
var checkText=$("#select_id").find("option:selected").text(); //获取Select选择的Text
var checkValue=$("#select_id").val(); //获取Select选择的Value
var checkIndex=$("#select_id ").get(0).selectedIndex; //获取Select选择的索引值
var maxIndex=$("#select_id option:last").attr("index"); //获取Select最大的索引值
//jQuery设置Select选择的Text和Value:

语法解释:

$("#select_id ").get(0).selectedIndex=1; //设置Select索引值为1的项选中
$("#select_id ").val(4); //设置Select的Value值为4的项选中
$("#select_id option[text='jQuery']").attr("selected", true); //设置Select的Text值为jQuery的项选中
/*
jQuery添加/删除Select的Option项:
请选择
点击一次,Select将追加一个Option
点击将在Select第一个位置插入一个Option
点击将删除Select中索引值最大Option(最后一个)

语法解释:

$("#select_id").append("<option value='Value'>Text</option>"); //为Select追加一个Option(下拉项)
$("#select_id").prepend("<option value='0'>请选择</option>"); //为Select插入一个Option(第一个位置)
$("#select_id option:last").remove(); //删除Select中索引值最大Option(最后一个)
$("#select_id option[index='0']").remove(); //删除Select中索引值为0的Option(第一个)
$("#select_id option[value='3']").remove(); //删除Select中Value='3'的Option
$("#select_id option[text='4']").remove(); //删除Select中Text='4'的Option

清楚所有选项:

$("#select_id").empty();


Let's create something great together.

프로젝트 문의 및 견적 요청은 언제든 환영합니다.