Monthly Archives: December 2013

https:// 에서는 HTTP_REFERER 이 일부밖에 기록이 안됩니다.

블로그와 홈페이지에 방문자 로그와 방문 통계용 카운터를 설치해 놓고 로그를 이것저것 살피던 도중에 발견한 사실인데요, https:// 에서 넘어오는 경우 $_SERVER[“HTTP_REFERER”] 에 내용이 일부만 기록이 됩니다. 어떤 검색엔진, 검색어를 사용해서 사이트에 이용자가 유입이 됐는지 확인하려고 넣어놓은 기능인데 정작 구글의 경우에도 https://www.google.com 에서 검색한 결과로 링크를 타고 들어와도 HTTP_REFERER은 ‘https://www.google.com’ 까지만 찍입니다.

반대로 네이버의 경우에는 https를 사용하지 않는지 네이버 검색으로 유입된 경우에는 사용한 검색어 등을 확인할 수 있었습니다.

MongoDB Document 인출하기, db.collection.find() (1)

MongoDB에서 데이터를 인출 질의는 find() 입니다. MySql의 Select에 해당하는 질의 입니다. MongoDB의 질의는 기본적으로 Javascript 함수나 메서드를 호출하는 방법과 유사합니다. MySql과 마찬가지로 현재 사용할 DB를 선택한 상태(use dbname)라는 가정하에 진행하겠습니다. find()의 기본 문법은 아래와 같습니다.

db.collection.find()

collection(MySql의 Table에 해당) 부분에는 document가 저장된 collection명이 들어갑니다. MySql의 쿼리문으로 치환하면, “SELECT * FROM <Table name>”에 해당합니다.  또한 find()는 두 개의 인자를 받아서 조건을 부여할 수 있습니다.

db.collection.find( array(), array() )

find()의 인자는 모두 배열 형식으로 받으며 이는 대다수의 MongoDB 질의문에도 해당합니다. 첫번째 배열에는 MySql의 WHERE 절에 해당하는 조건문을 설정하고, 두번째 배열에는 불러올 Field값(Column명)을 설정합니다. 조건문(논리연산자, 비교연산자 등)은 그 자체로 내용이 거지같이 꽤나 많이 때문에 간단한 연산만 다루도록 하겠습니다. 조건 부여는 다음과 같은 형식으로 이루어 집니다.

db.collection.find( { 'field' : 'value' } )

위 질의를 MySql로 치환하면 “SELECT * FROM <Table name> WHERE field = value”가 됩니다. 여기에 불러올 Field명을 지정하는 두번째 인자는 다음과 같이 부여합니다.

db.collection.find( { 'field' : 'value' }, 
                    { 'name' : 1, 'age' : 1 } );

위 질의를 Mysql로 치환하면 “SELECT name, age FROM <Table name> WHERE field = value”가 됩니다. ‘name’과 ‘age’ 뒤의 1은 MongoDB에서 true 대신 쓰이며 반대로 false의 경우에는 0 이 쓰입니다. 따라서 위의 질의문에서 ‘name’과 ‘age’의 값을 0으로 바꾸면 두 필드를 제외한 전체 document가 반환됩니다.
다시 첫 번째 인자인 where 절로 돌아가서 비교 연산자를 적용해 보도록 하겠습니다. MongoDB의 비교연산자는 $lt, $lte, $gt, $gte, $in, $nin, $ne 이 있습니다. MySql과 달리 기호가 아니라 헷갈립니다만 의미를 정리하면 다음과 같습니다.

연산자 영문 뜻 풀이
$lt less than 작은
$lte less than or equal to 작거나 같은
$gt greater than
$gte greater than or equal to 크거나 같은
$in exist in 존재하는
$nin not exist in 존재하지 않는
$ne not equal to 같지 않은

비교 연산자의 적용은 다음과 같습니다.

db.collection.find( { 'age' : { '$gt' : 10 } )

위 질의를 MySql로 치환하면 “SELECT * FROM <Table name> WHERE age > 10″이 됩니다. 여러 조건을 부여하기 위해서는 콤마로 계속 이어나가면 됩니다.

db.collection.find( { 'age' : { '$gt' : 10 }, 
                      'age' : { '$lt' : 20 }, 
                      'gender' : 'male' } )

MySql 로는 “SELECT * FROM <Table name> WHERE age > 10 AND age < 20 AND gender = ‘male'” 이 됩니다. 참고로 MongoDB에서는 조건을 콤마로 이어나갈 경우 AND 연산으로 간주합니다. 그 외의 논리 연산은 다음에 다루도록 하겠습니다.
한가지 주의하실 사항은 조건문에는 싱글쿼트 ‘ (따옴표)나 더블쿼트 “(쌍따옴표)를 모두 쓰셔도 상관 없습니다만 더블쿼트를 사용하실 경우 연산자인 $앞에 \(역슬래쉬)를 붙여줘야 하기 때문에 가급적이면 싱글쿼트를 사용하는 것을 권장합니다.

MariaDB 마이그레이션 후 mysql client library 에러

MariaDB로 마이그레이션 후에 다음과 같은 에러 메시지가 발생하는 경우가 있습니다.

mysql_connect(): Headers and client library minor version mismatch.

Database의 Client API Library 버전과 Header 버전이 일치하지 않아 발생하는 문제입니다. DB 자체는 정상적으로 굴러가지만 지속적으로 에러메시지를 뱉어냅니다. 자신의 DB API버전을 확인하려면 커맨드 라인이 다음과 같이 입력합니다.

php -i | grep 'Client API'

저같은 경우에는 버전정보가 다음과 같이 출력되었습니다. Client API header version만 다릅니다.

Client API version => 5.3.12-MariaDB
Client API library version => 5.3.12-MariaDB
Client API header version => 5.1.69
Client API version => 5.3.12-MariaDB

해결방법은 php mysql 드라이버를 삭제하고 mysqlnd 드라이버를 설치하면 됩니다.

yum erase php-mysql
yum install php-mysqlnd

드라이버 설치를 마치고 API 버전을 다시 확인하면 mysqldn으로 드라이버가 변경된 것을 확인하실 수 있습니다. 또한 더 이상 에러메세지가 발생하지 않습니다.

MongoDB 인증모드로 접속하기

MongoDB에 인증모드로 접속하는데 방법은 다양합니다.  먼저 리눅스 커멘드 창에서 접속하는 방법부터 보겠습니다.

1. 접속 후 username과 password를 입력

mongo
use admin
db.auth( "<username>", "<password>" );

mongo 를 입력해서 MongoDB 콘솔로 접속한 다음 사용할 DB를 입력한 후(위의 경우 admin) db.auth에 username과 password를 입력하는 방법입니다.  성공하면 심플하게 “1” 이 반환되고 실패하면 인증에 실패했다는 에러메시지가 반환됩니다.

2. 콘솔 접속시 DB명과 username, password를 입력

mongo <dbname> -u <username> -p <password>

콘솔 접속과 동시에 로그인 하는 방법입니다. -u와 -p뒤에 나오는 username과 password는 붙여주셔도 되고 띄어쓰기를 해도 상관없습니다. 성공하면 역시 심플하게 connecting to : 이 뜨면서 로그인 됩니다. 실패하면 로그인에 실패했다는 에러메시지가 반환됩니다.

3. PHP에서 접속하기

PHP 상에서 MySql DB에 접속할 때 username 과 password를 전송하는 것과 마찬가지로 MongoDB에서도 인증모드가 true 일때는 인증을 해주지 않으면 가차없이 에러를 반환합니다.

PHP Mongo Driver가 업데이트 되면서 authenticate() 함수가 삭제되었다고 합니다. authenticate() 함수로도 일단 인증이 작동은 하지만 Codeigniter에서 돌릴경우 Function MongoDB::authenticate() is deprecated 라는 에러를 출력합니다. 새로운 인증방법은 객체를 생성할때 Database Host, username, password를 함께 입력합니다.

<?php
    $mongodb = new Mongo( "mongodb://username:password@localhost:port/dbname" );

하지만 이 소스만으로는 접속 실패(username이나 password 틀림 등)시 fatal error를 뱉어냅니다. 따라서 예외처리를 함께 해주는 것이 좋습니다.

<?php
    try {
        $mongodb = new Mongo( "mongodb://username:password@localhost:port/dbname" );
    }
    catch( mongoConnectionException $e ) {
        die( "Mongo DB Connection Error : ".$e->getMessage() );
    }

PHP에서 백슬래쉬 정규식

문자열에 포함된 개행문자를 제거하기 위해 preg_replace() 함수를 이용해 삽질을 하다가 사소하면서도 중요한 사실을 깨닳았습니다.  백슬래쉬의 정규식은 백슬래쉬 네개 라는 것(…)

뭐, 구체적으로는 문자열에 포함된 메타문자인 \n 을 제거한다고 했을 때 소스는 다음과 같습니다.

$message = "동해물과 백두산이\n마르고 닳도록";
$regex = "/\\\\n/";
$new_message = preg_replace( $regex, "", $message );

CLI에서 Codeigniter 실행하기(cron)

일정 시간마다 특정 php 파일을 서버상에서 자동으로 실행시키는 cron 과 같은 기능을 사용하기 위해서는 CLI에서 php 를 실행시켜야 합니다.  Codeigniter 프레임 워크에서도 간단하게 이 기능을 실행할 수 있습니다.

CLI에서 Codeigniter 실행하기(Codeiginter 한국사용자포럼)

하지만 위 방법을 이용해서 php를 실행했을 때 명령어에 관계 없이 기본 index.php 가 실행되는 경우가 있습니다.  이럴때는 application/config/ 폴더에 config.php 에서 설정을 변경해 주어야 합니다.  $config[‘uri_protocol’] 부분을 찾아서 값을 ‘AUTO’로 변경해 주면 정상적으로 실행됩니다.

$config['uri_protocol'] = 'AUTO';

 

리눅스 콘솔에서 crontab을 실행하였을 때 ‘허가 거부’ 라는 메세지가 출력되는 경우 crontab이 있는 폴더(기본 /etc/ 에 있습니다)에 cron.allow 라는 파일을 작성해서 접근가능한 유저를 지정해 줘야 합니다.  user가 root인 경우 cron.allow 에는 root라고 작성해 주시면 됩니다.

MySql 에서 MariaDB로 갈아탔습니다.

※ 주의 : 기존 DB 데이터를 백업하는 과정을 절대로 생략하시면 안됩니다. 데이터 백업을 하지 않으실 경우 모든 DB 데이터가 삭제 될 수 있습니다.

최근의 대세(…)를 따라 정들었던 MySql을 버리고 MariaDB로 갈아탔습니다.   MariaDB와 MySql의 기능상의 차이점은 좀 더 공부를 해봐야 겠습니다만 일단 가장 좋은 점은 마이그레이션 쉽고 간편하다는 것입니다.

솔직히 말해서 설치 작업만 해주면 할게 없습니다.  콘솔 접속도 mysql을 그대로 사용하면 되니까요.  마이그레이션 작업에 관해서는 아래 블로그를 참조했습니다.  매우 잘 나와 있어서 그대로 따라하시면 됩니다(참고로 서버는 CentOS 입니다)

Upgrade from MySQL to MariaDB on Centos 6 [from : Joe’s Blog]

Repository 파일 작성하실 때 자신의 서버 OS 버전만 주의해 주시면 되겠습니다.  위 블로그에도 Repository-generator 가 링크되어 있으므로 참고 하시기 바랍니다.  자신의 CentOS 버전을 확인하는 방법은 아래와 같습니다.

cat /etc/redhat-release