태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

WEB|DB|CODE (34)



두개의 테이블을 Join 할 때 기준이 되는(코드) 테이블을 기준으로 join 하는 테이블(데이터)에 데이터가 없을 경우 inner join을 사용하면 기준이 되는 테이블의 행이 표시되지 않는다. 이 때 데이터가 없을 경우 0으로 표시하고 싶다면 outer join을 사용해야 한다.

예를 들어 특정 문자열이나 에러코드, 감사로그 코드의 일별 통계를 뽑을 때 한건도 없는 경우 일반적인 Inner Join을 하게 되면 건수가 0인 날짜는 출력되지 않는다. 이럴 때 해당 일자에 0건으로 출력되도록 하는 경우에 outer join을 사용할 수 있다.

다음의 두 테이블에서 예를 들어 설명하면...


table name : t_student 
no      name
 01      홍길동
 02      김철수
 03      이영희 


table name : t_score
code  subject grade 
 01      math      A
 01      social    A
 02      math      C
 03      social    B
 03      english  A

위의 테이블에서 아래의 결과처럼 각 이름별로 등급이 'A' 인 갯수를 구하고 A가 없는 학생의 경우 0 으로 출력하고자 한다면 어떻게 해야할까?



SELECT A.no, A.name, count(B.grade)
from t_student as A left join t_score as B on A.no = B.no
where B.grade = 'A' group by A.no;


로 하면 될 듯 하지만 안된다. -.-  0으로 출력되기를 원했던 학생들은 하나도 출력되지 않는다.
아~ 좌절했다... 시간이란... 알고 있다고 생각했던 것도 모두 지워버리는 매우 특별한 능력을 갖고 있다. 하지만 인간의 뇌는 잊었던 것을 다시 공부하면 훨씬 빠르게 되살릴 수 있는 능력 또한 갖고 있다.


Join,inner join, outer join




이런 저련 자료를 찾다보니 outer join 할 때 데이터가 있는 테이블에 WHERE 절로 조건을 주면 안되고 sub query를 써서 FROM 절에서 걸러내고 걸러낸 데이터셋에 outer join을 걸어야 한다는 이야기가 있었다.

즉... 위의 SQL은 아래와 같이 바뀌어야 한다는 이야기다.

SELECT  A.no, A.name, count(B.grade) 
FROM t_student as A LEFT OUTER JOIN (
SELECT no, COUNT(grade) AS grade 
 FROM t_score 
WHERE grade = 'A' 
GROUP BY no) as B on (A.no = B.no)
GROUP BY A.name



  • taeho Tae-Ho 2015.01.13 14:47 신고

    내가 작성해 놓은 포스트를 내가 다시 검색해서 찾았을 때의 느낌은 참....묘하다..ㅋㅋ



MySQL을 관리하기 위해 가장 많이 사용되는 관리도구는 바로 phpMyAdmin 이다. 웹 기반이고 단순한 DB의 생성과 관리 뿐만 아니라 백업과 복구기능도 지원되는 다재다능한 관리도구다.


그런데 MySQL 5.7을 설치하고 예전처럼 최신버전의 phpMyAdmin을 설치하는데 계정을 만드는 과정이 새로 보였다. 그래서 기존 처럼 MySQL의 DBA계정인 root를 버릇처럼 입력했더니 phpMyAdmin 웹 접속 시 다음과 같은 에러가 발생했다.


MySql 5.7 + phpmyadmin 접속 오류MySql 5.7 + phpmyadmin 접속 오류


쉘 상태에서 mysql 커맨드라인에서는 잘 접속이 되는데 phpMyAdmin에서는 root 계정으로 접속이 안되었다. 순간 phpMyAdmin에서 접속 시 root 계정으로의 접속을 차단했나 싶었다.


그래서 계정을 하나 더 만들고 해당 계정에게 DBA와 같은 권한을 부여해 봤다.


먼저 계정을 생성한다.


phpmyadmin 계정 생성phpmyadmin 계정 생성


phpmyadmin 이라는 계정을 만들고 뒤에는 비밀번호를 함께 부여한다. 당연히 비밀번호 규칙에 맞게 입력해야 한다.


다음엔 접근권한을 부여한다.


phpmyadmin에게 권한 부여phpmyadmin에게 권한 부여


그냥 모든 권한 (*.*)을 부여한다. 이렇게 해줘야 DB생성, 테이블생성, 권한부여, DB삭제 등의 작업을 할 수 있다.





시놀로지 NAS는 정말 요물과도 같은 존재다. NAS와 단순 웹서버는 물론 DNS, 프린터 서버, FTP서버, 토렌트 머신을 뚝딱~뚝딱~ 구성할 수 있고 보다 전문적으로 mysql 또는 mariadb를 설치하고 그 위에 워드프레스도 쉽게 설치할 수 있다. 물론 메일서버, 위키 등도 몇번의 클릭만으로 설치할 수 있는 애플리케이션 마켓(?)도 있다. 어제 하루만에 mariadb와 아피치, php, phpmysql을 모두 업그레이드하고 최신 워드프레스를 다운받아 수동으로 설치한 뒤 DSM에서 무료 SSL 인증서도 발급 받아 설치하고 워드프레스에 SSL까지 적용했다.

물론 시놀로지 NAS에 워드프레스 설치와 SSL 적용은 처음 해보는 작업이었다. 그럼에도 큰 어려움과 오류 없이 모든 작업이 부드럽게 진행되었고 지금까지 안정적으로 동작하고 있다.

Synology NAS... 정말 유용한 물건이다.

하지만 그 과정에서 내가 잘못 설정한 것인지는 모르겠으나 워드프레스의 SSL 적용을 위한 플러그인을 설치하는 과정에서 권한과 관련된 오류가 발생해 그 문제의 해결 방법을 정리해본다.

먼저 시놀로지 NAS의 웹서버에 설치된 워드프레스에서 사용할 SSL 인증서는 DSM에 웹으로 접속한 뒤 "제어판" - "보안" 메뉴로 진입한 뒤 "인증서" 탭에서 "추가" 버튼을 눌러 "Let's Encrypt"의 SSL 인증서를 발급 받으면 된다. 다만 무료 SSL 인증서 이기에 유효기간은 3개월 밖에 되지 않는다. 즉, 3개월 마다 재발급 받아 적용해줘야 한다.

발급받은 Let's Encrypt Auth"의 SSL 인증서.

발급받아 Synology NAS에 설치한 무료 SSL 인증서... 유효기간이 3개월이다.

그리고 시놀로지에 워드프레스를 설치한 뒤 워드프레스 접속 시 적용할 SSL 리다이렉션 플러그인을 설치한다. 내가 설치한 SSL 플러그인은 Really Simple SSL 이다.

이미 설치되어 있는 플러그인 이기에 상태가 "Activate" 이지만 이 플러그인이 설치되어 있지 않을 때는 Activate 버튼이 설치 버튼이 된다. 이 플러그인을 설치할 때는 워드프레스가 설치된 웹서버에 외부에서 FTP 접속이 가능해야 한다. 그리고 설치 중 워드프레스가 설치된 하위 디렉토리로 이동해 wp-content의 plugins 디렉토리 하위에 플러그인 설치 디렉토리를 만들고 설치하게 된다. (이 과정은 FTP 접속 ID와 비밀번호를 입력하면 자동으로 진행된다.)

그런데 워드프레스를 시놀로지 DSM에서 제공하는 버전이 아닌 최신버전을 수동으로 설치해서 그런지 Really Simple SSL 플러그인 설치 시 FTP 접속까지는 성공하는 듯 한데 이후 다음과 같은 에러가 발생했다.

FTP 접속 후 wp-content의 plugins 디렉토리 하위에 really-simple-ssl 디렉토리를 생성하다 에러가 발생하는 것이다.

이 경우 어떻게 해야 하는지 구글링을 통해 확인하니 권한문제라는 이야기가 많다. 하지만 wp-content 디렉토리와 그 하위 디렉토리의 접근권한을 777로 주어도 동일한 문제가 발생했다. 아마도 이 문제는 단순한 퍼미션의 문제라기 보다는 보안과 관련된 특별한 보안 기능이 적용되어 퍼미션이 777이라도 plugins 디렉토리에 새로운 디렉토리의 설치가 차단되는 듯 했다. 

아마도 웹서버의 제로데이 취약점 공격 등을 차단하기 위함 때문일텐데... 결과만 설명하면 워드프레스가 설치되는 디렉토리와 하위 디렉토리를 웹서버 프로세스의 소유자ID 및 그룹으로 맞춰야 하는 것으로 보인다. (사실 이러면 웹 취약점에 의한 디렉토리나 파일의 생성을 막을 수 없다. -.-)

즉... 아래와 같이 웹서버 대몬...여기서의 경우 웹서버 대몬인 httpd22 프로세스의 소유자를 확인해야 한다. 아래 화면의 경우 소유자의 계정이 http다. (부모가 1번인 httpd22 제외)

그리고 /etc/passwd 파일을 보면 http 계정이 존재한다.

/etc/group 파일에도 http 그룹이 있고 http 계정과 그룹ID가 1023으로 동일한 것을 확인하였다.

그렇다면 wp-content 를 포함한 하위의 파일들과 디렉토리의 소유자를 http로 바꾸고 권한을 755로 설정한다. 소유자 및 그룹과 퍼미션을 바꾸기 위해서는 다음의 명령을 이용한다.

chown -R http:http ./wp-content

chmod -R 755 ./wp-content

두 명령으로 변경하면 아래 처럼 소유자와 그룹 그리고 파일 퍼미션이 모두 변경된다.

화면 하단에 보면 really-simple-ssl 이라는 디렉토리가 생성되어 있는데 이 화면은 설치에 성공한 뒤 캡쳐해서 그렇다~.

이후 really simple ssl 플러그인의 설정화면에서 ssl인증서가 인식되는지 확인하고 관련 설정을 마치면 워드프레스 접속 시 브라우저의 주소창 앞에 안전한 SSL이 적용되었음을 보여주는 자물쇠 표시가 보일 것이다.



  • 에스델 ♥ 2019.03.27 10:32 신고

    무료 SSL인증서는 3개월마다
    재발급받아 적용해줘야하는군요.^^
    좋은 하루 보내세요!

    • taeho Tae-Ho 2019.03.27 16:15 신고

      네.. 개인 사용자용 인증서와 달리 서버에 설치하는 서버 인증서도 연단위로 돈을 내야 하는데 가격이 꽤 비싸거든요~~ ^^
      이 서버 인증서를 웹서버에 설치하면 서버에 웹브라우저로 접속하는 사용자에게 이 서버를 운영하는 주체가 누구인지 알려주고 공인인증기관이 그 운영주체가 맞음을 검증해주는 역할을 합니다. 당연히 웹브라우저와 서버간의 통신이 암호화되는 것도 보장해주고요~



C언어를 공부해본 사람이라면 누구나 알만한 프로그램이자 처음으로 작성해보는 프로그램이 있죠.

바로 Hello, World 혹은 Hello, C 라는 문자열을 출력하는 프로그램입니다. 이 프로그램이 얼마나 유명하냐면 프로그래밍 언어별로 이 문자열을 출력하는 소스를 컬렉션한 웹사이트가 있을 정도입니다. (보러가기)

그 중에서 오늘 이 포스트에서 작성할 언어는 바로 C언어 입니다. 그리고 C 언어 중에서도 Text 화면(콘솔)에서 동작하는 C언어와 Windows와 같은 GUI 화면에서 동작하는 C언어 소스를 비교해 보려 합니다.

먼저 사용자환경이 콘솔 즉  CLI (Command Line Interface) 환경인 C 언어 입니다. CLI를 지원하는 운영체제에서 C언어로 코딩한다면 소스코드는 100% 동일합니다. 

콘솔(DOS) Hello,C 소스콘솔(DOS) Hello,C 소스

위의 프로그램 소스는 주석과 공백라인을 제외하고 6 줄 뿐 입니다.은  너무도 유명해 더 설명이 필요 없을 정도 입니다. C 언어를 처음 배우는 사람은 누구나 이 프로그램을 작성하고 컴파일하고 실행해봅니다.

이 소스코드는 윈도의 콘솔프로그램(DOS 창에서 실행되는 프로그램)과 리눅스, 그리고 HPUX, Solaris, AIX 등은 물론 다른 운영체제에서도 컴파일하여 실행프로그램을 만들 수 있습니다. 아래 창은 위의 소스코드를 컴파일하면 생성되는 exe 파일을 실행시킨 화면입니다. 컴파일 시 생성될 실행파일명으로 hello-console-c.exe를 지정하였습니다.

위의 프로그램은 Visual Studio 라는 마이크로소프트에서 제공하는 개발환경에서 코딩하고 컴파일 했습니다. 즉 컴파일러가 Visual Studio의 C 컴파일러입니다. Visual Studio는 당연히 Windows 운영체제에서 실행되는 프로그램을 개발할 때 사용하는 통합개발환경입니다. 그리고 Windows와 Visual Studio는 위 화면처럼 명령프롬프트라는 콘솔환경(DOS 환경이라고도 함)에서 실행되는 GUI가 없는 프로그램도 개발하고 사용할 수 있도록 지원합니다. 하지만 최근에는 GUI가 없는 Console 프로그램은 일반사용자들은 거의 사용할 일이 없기 때문에 사실 앞의 "Hello, C"를 출력하는 C 프로그래밍언어는 단지 C언어의 문법과 여러 프로그래밍 개념을 배울 때만 사용합니다. 

만약 C언어의 문법과 구조체, 함수, 포인터 등등 여러 프로그래밍 개념들을 공부했다면 다음으로 이해해야하는 것은 Windows 프로그래밍의 특징입니다. (Windows 운영체제를 주로 사용한다는 가정하에...) 

전 C#, C++(MFC, ATL), Visual Basic 등의 언어로 프로그래밍 공부를 하기 전에 꼭 Visual C++ API를 사용해서 기본적인 Windows 프로그램의 밑바닥 구조를 이해하라고 이야기해주고 싶습니다. 

아래는 Windows GUI를 갖는 가장 간단한 ... 즉 Windows 창에 "Hello, Win3 2"를 출력하는 프로그램 소스입니다. 앞의 콘솔(도스창)모드에서 동작하는 프로그램 소스코도와 비교해보세요.

윈도 Hello,C 소스윈도 Hello,C 소스

무척 복잡해보이죠? 네..복잡합니다. -.-

그럼 컴파일한 뒤 실행된 화면을 봅니다.

무척 썰렁하긴 하지만 윈도 창이 있고 타이틀바도 있고 최소화 버튼, 최대화 버튼, 종료 버튼이 있는 윈도 프로그램입니다. 

콘솔C 소스는 크게 이해하는데 문제가 없습니다. C를 공부하기 시작한 스타터도 쉽게 이해할 수 있죠. 하지만 윈도C 소스코드를 처음보는 사람이라면 거의 멘붕에 가까운 느낌을 받을 수 있습니다. "Hello, Win32" 문자열 하나를 화면에 표시하는데 뭐이리 복잡한 소스코드가 필요한가 생각이 들기 때문이죠.

하지만 이 윈도C 소스를 이해하는 것은 Windows 운영체제가 프로그램을 실행시키고 관리해주는 메카니즘을 이해하는데 큰 도움이 됩니다. 사실 인터넷을 검색해보면 다이얼로그 윈도에 "Hello, C"나 "Hello, Window"를 표시하는 프로그램 소스는 있지만 위 소스코드처럼 메인윈도에 표시해주는 소스는 찾기 힘듭니다.

이런 윈도C 소스코드는 "Win32 API" 로 작성된 소스코드 입니다. Win32 API는 "Windows 32bit 용 API (Application Programming Interface)"의 준말입니다. 소스코드의 확장자는 CPP로 저장되지만 컴파일할 때는 순수하게 Windows 운영체제의 C 라이브러리를 이용해 컴파일 됩니다. DOS나 Unix 운영체제에서 제공되는 기본 라이브러리와 같은 것이라고 이해하면 됩니다. 모든 프로그램의 소스코드는 스스로 실행하는 것이 아니라 운영체제가 한줄~한줄~ 대신 실행해주는 것입니다. 즉, 프로그램은 운영체제와의 커뮤니케이션을 위한 것이죠.

하지만 Windows 프로그램의 모든 소스코드를 Win32 API를 이용해 작성하는 것은 엄청난 "노가다"를 요구하는 작업입니다. 그래서 MS에서는 MFC, ATL 등 C언어, C++언어 개발자를 위해 미리 만들어 놓은 일종의 라이브러리를 제공합니다. 또한 Visual Studio는 MFC나 ATL 등을 사용하기 편리하게 최적화해 놓은 통합개발환경 입니다.

위의 윈도C 소스코드를 한줄~한줄 구글링해가면서 분석해보면 윈도가 프로그램을 구동하는 방식을 이해할 수 있습니다.


  • 코초 2019.06.10 10:29

    좋은글감사합니다


IT 분야의 일을 하다 보면 외부에서 혹은 내부 네트워크간 통신을 위해 방화벽을 열어줘야 하는 경우가 생깁니다. 서버에 SW가 설치되고 방화벽에서 열어준 Port를 사용하는 SW가 설치되어 구동 중이라면 원격지의 PC에서 telnet 명령을 통해 손쉽게 방화벽이 잘 열려 있는지를 확인할 수 있습니다.

하지만 서버에 해당 포트를 이용하는 SW가 설치되어 있지 않다면 방화벽에 Open을 요청한 TCP 포트가 제대로 열려 있는지 확인이 어렵습니다. 서버와 포트가 한두개라면 SW를 설치한 뒤 확인하면 되지만...

방화벽 Open이 관리적인 문제와 조직적인 문제로 최소 3~4일씩 소요되는 경우가 다반사입니다. 심하면 그보다 훨신 더 오래 걸리죠. 그럴 땐 보안 담당자가 방화벽을 Open했다고 회신을 주었을 때 즉각적으로 확인 후 제대로 Open되지 않았다면 재 요청이나 추가 확인을 요구해야 합니다.

나중에 급하게 방화벽이 제대로 Open되지 않았으니 열어달라고 또 요청하면 "왜~ 이제와서 그러느냐...." 거나 "왜 즉각 확인을 안했냐"는 등 불쾌해 하거나 심지어 프로젝트의 진행에 문제가 생기는 경우까지 발생할 수 있습니다. 방화벽 담당자도 한가한 사람은 아니기 때문이죠. 방화벽 담당자 입장에서는 똑같은 일을 두번 하는 느낌이 들 수있기 때문입니다.

이런 경우를 예방하기 위해 Open을 요청한 TCP 포트를 사용하는 SW가 설치되지 않은 상황에서 해당 포트가 열렸는지 확인할 때 사용할 수 있는 간단한 스크립트를 이용해 서비스 SW가 설치되지 않았어도 즉각적으로 방화벽이 제대로 열렸는지를 확인해주는 센스가 필요합니다. 프로젝트의 지연도 예방하고 방화벽 담당자와 트러블도 차단하는 일석이조의 효과를 볼 수 있습니다.



아래 스크립트는 스크립트 앞 부분에서 지정한 IP와 TCP Port를 Bind하여 Listen 하고 있으면서.... 원격지에서 접속 시도가 있을 경우 한줄의 메시지를 응답하는 기능을 수행합니다. 그리고 서버에서는 클라이언트의 접속시도가 있었음과 IP를 출력합니다. 

이 스크립트는 서버에 운영체제만 설치되어 있으면 동작합니다. 기본 운영체제에 Perl은 함께 기본적으로 설치되기 때문이죠. 서버에서 아래 스크립트를 실행시켜 놓고 원격지에서 telnet 명령어를 통해 해당 TCP Port로 접속을 시도하면 방화벽이 Open되어 있을 경우 한줄의 응답 메시지가 출력됩니다.

방화벽 Open 확인.. 아주 쉽습니다.. ^^

------ server.pl ------

#!/usr/bin/perl -w

use strict;

use Socket;

 

# 통신포트 (TCP)

​my $port = shift | 8306;

# Bind할 IP (서버에 IP가 여러개일 경우 유용함) 

my $server = "10.200.48.76";

my $proto = getprotobyname('tcp');

 

socket(SOCKET, PF_INET, SOCK_STREAM, $proto) 

or die "Can't open socket $! \n";

 

setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1) 

or die "Can't set socket option to SO_REUSEADDR $! \n";

 

bind(SOCKET, pack_sockaddr_in($port, inet_aton($server))) 

or die "Can't bind to port $port! \n";

​ 

listen(SOCKET, 5) or die "listen: $!";

print "Server started on port $port\n";

 

my $client_addr; 

while ($client_addr = accept(NEW_SOCKET, SOCKET)) {

print NEW_SOCKET "Smile from the server. Server port($port) is opened.\n";

my ($client_port, $client_ip) = sockaddr_in($client_addr);

my $client_ipnum = inet_ntoa($client_ip);

print "Connection recieved from $client_ipnum \n";

close NEW_SOCKET;

}


  • 지후대디 2017.05.09 10:47 신고

    오호 종종 서비스 오픈 전에 방화벽 요청해 두고 다양한 사유로 (이중화 서버 로드발란스 설정 같은) 나중에 서비스 올라온 이후 방화벽이 제대로 안 열려있는 걸 확인하는 일을 자주 겪고 있는데 사전 체크에 도움이 될 스크립트 같습니다.

    • taeho Tae-Ho 2017.05.09 12:14 신고

      넵.. L4로 로드밸런싱을 할 경우에도 서비스가 구축되지 않은 상태에서 기본적인 구성을 테스트할 수 있어 매우 유용하죠. 제대로 로드밸런싱이 되는지 서비스 구축이 완료되지 않아도 기본적인 확인이 가능하니까요~ ^^


게시판을 모아둔 웹사이트를 구축할 때 많이 사용되는 무료게시판 중에 그누보드(GNUBOARD)라는 게시판 솔루션이 있습니다. 저도 애용하는 게시판 소스 중 하나인데요. 이 그누보드는 메일발송 기능까지 포함고 있습니다. 내부적으로는 PHPMailer라는 메일발송 라이브러리를 연동하여 제공하는 기능이죠.


그누보드의 이메일 사용 설정


이 그누보드의 메일발송기능은 다음과 같이 그누보드의 관리자 페이지에서 설정할 수 있습니다.




위 설정화면에서 처럼 회원가입한 사람이 있으면 등급설정을 위해 관리자에게 회원가입 신청이 있음을 알려주는 설정을 비롯해 글쓴이에게 댓글이 작성되었음을 알려주는 등 다양한 용도로 메일 발송기능을 사용할 수 있습니다.


하지만 위 화면에서 메일 발송 기능을 사용하도록 설정한다고 하여 바로 메일이 발송되는 것은 아닙니다.


그누보드의 소스파일 중 일부를 수정해주어야 합니다. 보다 쉽게하기 위해 환경설정을 통해 설정이 되도록 그누보드의 기능을 개선하면 좋겠지만 몇몇 이유로 인해 그렇게까지 기능을 제공하지는 않습니다. 때문에 IT를 전공하고 약간의 이메일서버의 개념과 동작원리를 이해해야만 수정할 수 있습니다.


그누보드의 SMTP(Mail Server) 설정

앞에서 설명한 그누보드의 메일 보내기 기능 사용 설정은 그누보드가 "어느 메일서버에 어떤 계정으로 접속하여 메일을 보낼지"를 알려주어야 제대로 동작합니다.


여기에서 사용되는 메일 서버는 다음이나 네이버 혹은 구글 등 SMTP 기능을 제공하는 다양한 메일서버를 사용할 수 있습니다. (SMTP에 대한 설명은 생략합니다.)


또한 SMTP 설정 시 SSL 설정과 Plain Text 방식 중 하나를 사용할 수 있는데 이 포스트에서는 다음이나 구글, 네이버 등에서 요구하는 SSL(암호화통신프로토콜)을 사용하는 메일 설정과 SSL을 요구하지 않는 Plain Text 방식을 사용할 때의 설정을 모두 설명합니다.


그누보드의 메일서버 주소와 계정 설정은 lib 디렉토리의 mailer.lib.php 파일에서 하게됩니다.

mailer.lib.php 파일에서 mailer() 함수를 찾아 다음과 같이 수정해줍니다. 그누보드라 하더라도 버전에 따라 약간씩 소스가 달라 위치가 다를 수 있습니다.



먼저 plain text 방식의 메일발송을 지원하지 않고 ssl을 요구하는 메일서버에서 설정방식입니다. 다음, 구글등이 해당됩니다. 포트번호도 다르다는 점에 주의해주세요.


function mailer($fname, $fmail, $to, $subject, $content, $type=0, $file="", $cc="", $bcc="") 

{

    global $config;

    global $g5;


    // 메일발송 사용을 하지 않는다면turn;

    if (!$config['cf_email_use']) return;


    if ($type != 1)

        $content = nl2br($content);


    $mail = new PHPMailer(); // defaults to using php "mail()" 

    if (defined('G5_SMTP') && G5_SMTP) {

// Modified By taeho. 2015.12.31, 메일을 보낼 때 메일서버에 접속하기 위한 설정입니다.

        $mail->IsSMTP();

        $mail->SMTPAuth  = true;                  // enable SMTP authentication

        $mail->SMTPSecure = "ssl";                // sets the prefix to the servier

        $mail->Host      = "smtp.daum.net";      // sets GMAIL as the SMTP server

        $mail->Port      = 465;                  // set the SMTP port for the GMAIL server

        $mail->Username  = "다음아이다@hanmail.net";  // MAIL username

        $mail->Password  = "비밀번호";            // MAIL password

        // End. By taeho. 20151231           


    }


    $mail->From = 'noreturn@hanmail.net';   // 사용자에게 보여줄 보내는이 메일주소

    $mail->FromName = 'taeho BBS';  // 사용자에게 보여줄 보내는 사람의 이름 등

    $mail->Subject = $subject;

    $mail->AltBody = ""; // optional, comment out and test

    $mail->MsgHTML($content);

    $mail->AddAddress($to);

        $mail->AddAddress($to);

    if ($cc)

        $mail->AddCC($cc);

    if ($bcc)

        $mail->AddBCC($bcc);

    //print_r2($file); exit;

    if ($file != "") {

        foreach ($file as $f) {

            $mail->AddAttachment($f['path'], $f['name']);

        }

    }

    return $mail->Send();


다음은 plain text를 지원하는 표준 메일서버의 설정입니다.

function mailer($fname, $fmail, $to, $subject, $content, $type=0, $file="", $cc="", $bcc="")

{

    global $config;

    global $g5;


    // 메일발송 사용을 하지 않는다면

    if (!$config['cf_email_use']) return;


    if ($type != 1)

        $content = nl2br($content);


    $mail = new PHPMailer(); // defaults to using php "mail()"

    if (defined('G5_SMTP') && G5_SMTP) {

        $mail->IsSMTP(); // telling the class to use SMTP

        $mail->Host = 'mail.company.kr'; // SMTP server

        $mail->SMTPAuth = true;

        $mail->Username = 'taeho@company.kr';

        $mail->Password = '비밀번호';

    }

    $mail->From = 'noreturn@company.kr';

    $mail->FromName = 'Library Server';

    $mail->Subject = $subject;

    $mail->AltBody = ""; // optional, comment out and test

    $mail->MsgHTML($content);

    $mail->AddAddress($to);

    if ($cc)

        $mail->AddCC($cc);

    if ($bcc)

        $mail->AddBCC($bcc);

    //print_r2($file); exit;

    if ($file != "") {

        foreach ($file as $f) {

            $mail->AddAttachment($f['path'], $f['name']);

        }

    }

    return $mail->Send();

}


표준 SMTP 메일서버의 경우 Port 번호를 명시하지 않아도 됩니다. 포트번호가 명시되지 않으면 표준 SMTP 포트번호인 25번이 자동으로 설정됩니다.


주의사항

프로그래밍을 할 때 절대 삼가해야할 점은 소스코드에 ID와 Password를 하드코딩하지 말아야 한다는 점입니다. 하지만 무료 소스이다보니 위의 사례들 처럼 비밀번호를 소스코드에 그대로 노출시키게 되는 경우가 있습니다. 만약 이 서버에 접속 권한이 있는 개발자나 운영자가 이 비밀번호를 유출시킨다면 큰 피해로 이어질 수 있기 때문에 매우 주의해야 합니다.


RedCastle과 같은 파일접근통제 솔루션을 이용해 개발자나 운영자가 telnet, ssh, ftp 등의 접속을 통해 이 소스파일을 읽지 못하도록 조치한다면 최소한의 보안은 가능하지만 그 이외의 경우... 이 파일에 대한 접근을 통제하기는 매우 어렵다는 점을 항상 유의해야 합니다.



  • 지후대디 2016.01.24 23:13 신고

    무료보드에 참 기능이 많아서 저도 과거에 이용해본 경험이 있습니다 메일도 쉽게 연계가 가능하군요^^

    • taeho Tae-Ho 2016.01.31 19:07 신고

      그누보드엔 참 많은 기능이 있습니다. 그중에서 특별히 활용하는게.. 메일기능과 여분필드 정도네요.. ^^ 개발능력이 부족하거든요.. ^^

  • 휴매니아 2019.09.28 08:08

    안녕하세요?
    홈페이지를 제작한지 얼마되지 않은 초보입니다.
    그누보드5를 설치는 완료를 했습니다만, 메일링테스트에서 다음계정으로 전달이 되지 않습니다.
    여러가지 테스트를 해보았지만 결과는 같았어요.
    오늘 태호님의 자료를 보고 같이 설정을 했습니다만, plain text는 찾지를 못하겠네요.
    혹시 본인의 서버로 돌렸을때만 가능한가요?
    저는 cafe24에서 웹호스팅을 이용하고 있습니다.

    • taeho Tae-Ho 2019.09.28 09:12 신고

      플레인텍스트를 찾을 수 없다는 말씀이ㅠ어떤 의미인지 정확하게 알 수 없네요.
      mailer함수가 따로 있는 것이 아니고 mailer함수의 내용을 수정하시면 됩니다.
      꼭 성공하시길 빕니다~~ ^^


CentOS와 RedHat은 기본적으로 MySQL과 PostgreSQL 같은 RDBMS의 온라인 설치를 지원한다. CentOS와 RedHat이 설치된 서버가 인터넷에 연결되어 있다면 바로 yum 명령을 이용하여 MySQL이나 PostgreSQL을 설치할 수 있다.


그런데 CentOS 6.6 Final DVD를 이용해 CentOS를 설치하고 yum을 이용해 postgreSQL을 설치하게 되면 기본적으로 8.x 버전의 postgreSQL이 설치된다. 하지만 최신은 아니더라도 비교적 최근의 버전을 설치할 일이 생겨버렸다.


그래서 구글링을 해본 결과 다음과 같은 방법으로 상위버전의 postgreSQL의 설치가 가능했다.


CentOS 6.6 Final에 PostgreSQL 9.3 설치하기

먼저 리눅스의 버전확인. 커널버전 2.6.32-504가 6.6 Final 이다. 그리고 64bit 커널이다.

[root@localhost lib]# uname -a

Linux localhost.localdomain 2.6.32-504.el6.x86_64 #1 SMP Wed Oct 15 04:27:16 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

다음과 같이 postgresql 사이트에서 yum의 리포지토리를 업그레이드하는 rpm을 다운받아 설치한다.


[root@localhost lib]# rpm -Uvh http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-redhat93-9.3-1.noarch.rpm

http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-redhat93-9.3-1.noarch.rpm(을)를 복구합니다

경고: /var/tmp/rpm-tmp.jMiE5n: Header V4 DSA/SHA1 Signature, key ID 442df0f8: NOKEY

준비 중...               ########################################### [100%]

   1:pgdg-redhat93          ########################################### [100%]

[root@localhost lib]# 


정상적으로 완료되었다면 yum을 이용해 postgreSQL 패키지를 다운 받는다.

[root@localhost lib]# 

[root@localhost lib]# yum install postgresql93-server postgresql93

Loaded plugins: fastestmirror

Setting up Install Process

Loading mirror speeds from cached hostfile

 * base: centos.mirror.cdnetworks.com

 * extras: centos.mirror.cdnetworks.com

 * updates: centos.mirror.cdnetworks.com

pgdg93                                                                                     | 3.7 kB     00:00     

pgdg93/primary_db                                                                          | 126 kB     00:00     

Resolving Dependencies

--> Running transaction check

---> Package postgresql93.x86_64 0:9.3.10-1PGDG.rhel6 will be installed

--> Processing Dependency: postgresql93-libs = 9.3.10-1PGDG.rhel6 for package: postgresql93-9.3.10-1PGDG.rhel6.x86_64

--> Processing Dependency: libpq.so.5()(64bit) for package: postgresql93-9.3.10-1PGDG.rhel6.x86_64

---> Package postgresql93-server.x86_64 0:9.3.10-1PGDG.rhel6 will be installed

--> Running transaction check

---> Package postgresql93-libs.x86_64 0:9.3.10-1PGDG.rhel6 will be installed

--> Finished Dependency Resolution


Dependencies Resolved


===================================================================================

 Package                          Arch                Version                          Repository           Size

===================================================================================

Installing:

 postgresql93                     x86_64              9.3.10-1PGDG.rhel6                pgdg93              1.0 M

 postgresql93-server              x86_64              9.3.10-1PGDG.rhel6                pgdg93              4.1 M

Installing for dependencies:

 postgresql93-libs                x86_64              9.3.10-1PGDG.rhel6                pgdg93              193 k


Transaction Summary

====================================================================================

Install       3 Package(s)


Total download size: 5.3 M

Installed size: 21 M

Is this ok [y/N]: y

Downloading Packages:

(1/3): postgresql93-9.3.10-1PGDG.rhel6.x86_64.rpm                                          | 1.0 MB     00:03     

(2/3): postgresql93-libs-9.3.10-1PGDG.rhel6.x86_64.rpm                                     | 193 kB     00:00     

(3/3): postgresql93-server-9.3.10-1PGDG.rhel6.x86_64.rpm                                   | 4.1 MB     00:07     

-----------------------------------------------------------------------------------

Total                                                                             451 kB/s | 5.3 MB     00:12     

Running rpm_check_debug

Running Transaction Test

Transaction Test Succeeded

Running Transaction

Warning: RPMDB altered outside of yum.

** Found 1 pre-existing rpmdb problem(s), 'yum check' output follows:

redcastle-4.0.3-1.x86_64 has missing requires of /usr/lib/librclog.so()(64bit)

  Installing : postgresql93-libs-9.3.10-1PGDG.rhel6.x86_64                                                    1/3 

  Installing : postgresql93-9.3.10-1PGDG.rhel6.x86_64                                                         2/3 

  Installing : postgresql93-server-9.3.10-1PGDG.rhel6.x86_64                                                  3/3 

  Verifying  : postgresql93-9.3.10-1PGDG.rhel6.x86_64                                                         1/3 

  Verifying  : postgresql93-server-9.3.10-1PGDG.rhel6.x86_64                                                  2/3 

  Verifying  : postgresql93-libs-9.3.10-1PGDG.rhel6.x86_64                                                    3/3 


Installed:

  postgresql93.x86_64 0:9.3.10-1PGDG.rhel6             postgresql93-server.x86_64 0:9.3.10-1PGDG.rhel6            


Dependency Installed:

  postgresql93-libs.x86_64 0:9.3.10-1PGDG.rhel6                                                                   


Complete!

[root@localhost lib]#

디펜던시까지 알아서 체크하고 libs도 자동으로 다운받아 설치해준다.



설치된 패키지 확인. (postfix는 아니다.)

[root@localhost lib]# rpm -qa | grep post

postfix-2.6.6-6.el6_5.x86_64

postgresql93-9.3.10-1PGDG.rhel6.x86_64

postgresql93-libs-9.3.10-1PGDG.rhel6.x86_64

postgresql93-server-9.3.10-1PGDG.rhel6.x86_64

[root@localhost lib]# 


postgreSQL의 데이터베이스를 초기화한다. 초기 데이터베이스와 시스템카다로그가 생성된다.

[root@localhost lib]# 

[root@localhost lib]# /etc/init.d/postgresql-9.3 initdb

데이타베이스를 초기함:                                     [  OK  ]

[root@localhost lib]# 


이제 완료다. PostgreSQL을 구동한다.

[root@localhost bin]# /etc/init.d/postgresql-9.3 start

postgresql-9.3 서비스를 시작하고 있습니다:                 [  OK  ]

[root@localhost bin]# 


설치되고 구동된 PostgreSQL의 상태와 버전을 체크한다.



여기까지 정상이라면 OK..!!



워드프레스(Wordpress)는 대표적인 설치형 블로그 솔루션이다. 하지만 워드프레스는 블로그는 물론 게시판이나 홈페이지로 까지 변형이 가능할 만큼 유연한 구조를 갖고 있으며 실제로 다양한 플러그인과 테마를 통해 매우 다양한 형태의 홈페이지를 만들 수 있도록 해준다. 게다가 워드프레스는 회원가입을 받을 수 있도록 해주는 플러그인도 지원된다. 그리고 오늘 설명할 회원가입에 대한 이메일 인증 설정은 블로그를 운영하면서 친한 이웃이나 정보를 공유하기 위한 소수의 멤버들을 모아 회원제로 운영할 때 이메일 주소를 확인할 수 있는 이메일 플러그인도 지원한다.


워드프레스 회원 가입 양식

워드프레스는 설치형 블로그 툴이면서도 기본적으로 아래와 같이 회원가입을 할 수 있는 기능을 지원한다.



[사용자명]에 사용할 ID를 입력하고(이메일주소를 ID로 쓸 수도 있다) 

아래 창에 [이메일] 주소를 입력한 뒤 "등록하기" 버튼을 클릭하면 입력한 이메일 주소로 인증메일이 보내지고 인증 메일에 포함된 URL을 클릭하면 비밀번호를 설정하는 방식으로 운영될 수 있다.


하지만 이메일 인증 플러그인을 설치하고 SMTP를 설정해주지 않으면 가입 인증용 이메일이 보내지지 않는다.


워드프레스 이메일 플러그인 설치 및 활성화

워드프레스의 설정 화면에 들어가면 [플러그인] 메뉴가 보인다. [플러그인 추가하기]를 선택하여  키워드 검색란에 "wp-mail-smtp"를 입력하여 검색하면 아래와 같이 Mail 플러그인이 표시된다. [설치]를 클릭하여 설치한다.



wp-mail-smtp 설정

wp-mail-smtp 플러그인을 설치한 뒤 [설치된 플러그인] 메뉴에 가 보면 아래화면 처럼 WP-Mail-SMTP 플러그인이 설치된 플러그인 목록에 보인다. [활성화]를 클릭하여 활성화 하면 [비활성화]로 바뀐다.  화면에 표시된 것 처럼 [비활성화] 메뉴가 보이면 활성화 된 것이다.




그리고 [Settings] 를 클릭하여 회원 가입 인증 메일을 보낼 때 사용할 SMTP 메일 서버 설정창을 실행시킨다.



위의 각 입력항목을 설명하면...


[From Mail] 메일을 보내는데 사용할 보내는 사람 메일주소를 입력한다. 

[From Name] 보내는 사람의 이름이다. 실명이 아니어도 무관하며 일반적으로 사이트에서 사용할 관리자의 닉네임 정도를 입력하면 된다.

[Mailer] 메일을 보낼 메일 클라이언트 프로그램 선택 정도 되는 메뉴다. 어떤 항목이 될지는 SMTP 서버 특성에 따라 다르다. 내 경우 다음메일로 테스트를 해봤는데 아래의 php mail() function을 선택해야 메일이 정상적으로 보내졌다.

[Return Path] 회신 메일 관련 설정인데...그냥 체크해주었다.

[SMTP Host] 보내는 메일 서버 주소다. 이 주소는 각 메일 포털이나 메일서버의 SMTP 주소를 입력하면 된다. 다음 메일(한메일)의 경우 화면에 보이는 값이다. (smtp.daum.net)

[SMTP Port] 보내는 메일 서버의 포트번호다. 이 번호도 메일 포털이나 메일서버의 설정에 따라 맞춰줘야 한다. 위 화면의 포트번호는 다음 메일서버의 포트다.

[Encryption] 암호화 여부다. 마찬가지로 메일서버 설정에 따라줘야 한다.

[Authentication] 메일 발송 시 인증여부다. 메일을 보낼 때 인증이 없으면 해당 서버는 스팸메일 발송지로 악용될 가능성 100%다. 그래서 대부분의 메일 포탈이나 메일서버는 메일 발송 시 보내는 사용자에 대한 인증을 필수적으로 요구한다. 당연히 Yes를 선택해야 할 것이다.

[Username] / [Password] 보내는 메일서버의 인증 ID와 비밀번호다. 위의 경우 다음 메일을 사용하는 사용자의 ID와 비밀번호를  입력한다. 다음 메일 ID 입력시는 ID만 넣고 @hanmail.net 과 같은 도메인 주소는 넣지 않는다.


모두 입력했다면 [변경 사항 저장]을 클릭하여 설정을 저장한 뒤 [send test]나 실제 계정을 등록해 인증메일이 발송되는지 확인한다.


회원 가입 테스트

아래와 같이 워드프레스 회원 가입 양식을 실행하여 사용자 명과 이메일 주소를 입력 한 뒤 [등록하기]를 클릭한다.

그러면 입력한 메일 주소로 회원 가입 인증 메일이 보내진다.



구글 메일에 들어가 수신된 가입 인증 메일을 확인한 것이다. 아래 화면처럼 URL이 발송되어 온다. 인증 URL을 클릭한다.


인증 URL을 방문해보면 아래와 같이 비밀번호를 설정하는 화면이 표시된다. [새 비밀번호]에 도저히 외울 엄두가 안나는 비밀번호를 추천하는데... 모두 지우고 본인이 사용할 비밀번호를 입력하면 된다. 그리고 [비밀번호 초기화]를 클릭하면 회원 가입과 인증 그리고 비밀번호 설정이 완료된다.



비밀번호 설정 후 가입 완료된 화면이다.



이제 가입된 회원은 기본적으로 [구독자] 권한으로 가입된다. 관리자가 워드프레스 사용자 관리 기능을 이용해 글쓰기 등의 권한을 별도로 부여해주면 된다.



시스템엔지니어 일을 하면서 종종 DB를 접하게 된다. IT바닥에 뛰어 든 초기에 개발과 DB를 접하고 특히나 Ingres라는 RDBMS를 제법 깊게 공부했던지라 DB와 SQL에 대해서는 일반적인 엔지니어들 보다 이해도가 높다. 덕분에 이런 저런 시스템SW와 보안솔루션들이 DB를 사용할 때 빠르게 구조를 이해하고 감사로그나 수집된 데이터에 대해 직접 DB에 접속하여 SQL을 통해 분석하고 레포팅할 수 있다.


DB와 DBMS

프로세스와 프로세서를 정확하게 개념적으로 구별하지 못하는 엔지니어가 많듯... db와 dbms를 구별하지 못하는 엔지니어도 많은게 현실이다. DB는 DBMS에 의해 저장된 데이터 객체 중 가장 큰 객체를 의미한다. DBMS는 사용자 프로세스와 DB 사이에서 인터페이스 역할을 수행하는 프로세스와 메모리의 집합체다. 


DB(Database)에는 다양한 데이터 객체들이 존재한다. 그리고 DB는 아래의 객체들이 저장되어 있는 파일의 집합체다. (때론 파일이 아닌 Raw Device 인 경우도 있다.) 


이 포스트에서는 학문적인 관점에서의 추상적인 객체 개념이 아닌 실제 상용으로 사용되는 DB의 물리적인 객체에 대해 설명하므로 참고하길 바란다.


1. 시스템카달로그 (System Catalog)


DB의 기본적인 설정 값들이 저장되어 있는 시스템카다로그(테이블의 일종)에는 DB의 경로와 DB사용자 정보와 접근권한 그리고 데이터가 저장되는 테이블에 대한 속성과 인덱스에 대한 정보 등 DBMS가 데이터를 저장하고 조회하고 관리하는데 필요한 핵심적인 데이터가 저장된다. 



2. 테이블(Table)


실제 데이터가 저장되는 객체가 테이블이다. 테이블은 컬럼(Column)과 행(row)로 이루어져 있는 표와 같다고 생각하면 된다. DBMS는 SQL(Standard Query Language)이라는 언어로 사용자 프로세스와 대화하며 테이블 이름과 컬럼 이름을 기준으로 DB에서 데이터를 조회하고 삽입하고 수정하고 삭제한다.


3. 인덱스(Index)


테이블에는 사용자프로세스에서 입력하는 순서대로 행(로우)가 순차적으로 증가한다. 엑셀과 같은 표문서에서 데이터를 저장하면서 행이 증가하는 것과 같다. 따라서 검색시에 특정 행을 찾기 위해서는 첫번째 행부터 표 전체를 검색해야 한다. 당연히 검색 속도가 느릴 수 밖에 없다. 이러한 검색 속도 문제를 해결하기 위해 검색 조건에 많이 사용되는 컬럼, 즉 사람이라면 주민번호, 전화번호, 이름 등의 컬럼을 내림차순, 올림차순에 따라 정리해 놓은 검색을 위한 표가 바로 인덱스다. 

인덱스가 많을 수록 좋을 것 같지만 데이터가 추가(insert) 될 때 인덱스도 함께 생성하고 경우에 따라서는 정리도 해주어야 하기 때문에 인덱스의 생성은 신중해야 한다. 테이블 생성 시 Primary Key를 지정하는 경우가 많은데 이또한 인덱스의 일종이다.


4. 뷰(View)


뷰는 실제로 데이터가 저장되지 않는 논리적인 테이블이다. 두개의 테이블에 모두 존재하는 데이터를 별도의 테이블로 만들고 싶을 때 View를 생성하면 된다. View는 SQL의 select 문을 이용해 정의되어 시스템카다로그에 저장된다. 뷰도 논리적으로는 테이블이기 때문에 테이블의 이름과 뷰의 이름이 중복될 수 없다.


4. 프로시저(Procedure)


트리거 혹은 DBMS 자체에서 지원하는 4GL언어 (예를 들면 PL/SQL 혹은 T-SQL) 또는 사용자프로세스에서 호출할 수 있는 일종의 사용자 정의 함수다. DBMS 자체에서 지원하는 4GL 언어 또는 C언어 등의 언어와 SQL이 혼합되어 작성되며 시스템카달로그에 저장된다. 대부분 여러 사용자 프로세스 혹은 트리거에서 많이 사용되는 절차를 프로시저로 정의해 놓고 호출하여 사용한다. DBMS에 의해 관리되기 때문에 미리 컴파일(Pre-Compile)되어 있고 개발언어 독립적이라는 장점이 있다.


5. 트리거(Trigger)


쉽게 이해하기 위해서는 트리거를 일종의 이벤트 라고 생각하면 된다. 즉 "특정 테이블에 특정 값이 입력될 때 어떤 프로시저를 호출해라"와 같이 이벤트와 처리루틴을 정의하는 것을 말한다. 사용자 프로세스에서 모든 처리를 수행할 수 있으나 여러 사용자 프로세스에서 공통으로 처리해야 하는 프로시저 중에서 "이벤트"기반으로 처리해야할 내용들을 트리거로 지정하는 경우가 많다.


DB의 가장 대표적인 객체 5가지의 개념에 대해 살펴보았다.


다음은 DBMS다. DBMS는 Database Management System이다. 우리말로 쓰자면 데이터베이스 관리 시스템이다. 예전에 DBMS 기술지원 일을 할 때는 DB와 DBMS를 엄격히 분리하여야 했지만 보안이나 시스템소프트웨어 관련 일을 하면서 궂이 분리해야할 필요를 느끼지는 못한다. DB와 DBMS가 운영체제보다도 더 전문적인 지식을 필요하다보니 특히나 보안 분야에서 일하는 분들은 이 둘을 구별해야할 필요를 전혀 느끼지 못하고 있다.


DBMS 중에서 가장 많이 쓰이는 Oracle이나 MySQL , MS-SQL 그리고 PostgreSQL은 기본적으로 RDBMS다. 여기서 R은 Relational(관계형)를 의미한다. 즉, 테이블에 저장되는 데이터들이 관계를 맺고 있고 이 관계에 따라 가공되고 표현됨을 의미한다. 이 관계형에 대한 설명은 다음을 참고하면 좋다. (커드의 12가지 규칙)


모든 DBMS는 접속관리자(Connection Manager),SQL 파서(Parser), 쿼리 옵티마이저(Query Optimizer), 트랜잭션 관리자(Transaction Manager), DB관리자(Database Manager)  등으로 불리는 프로세스들로 구성된다. 제품에 따라 개수는 다르지만 하나의 프로세스로 구성되어 동작하지 않고 여러개로 분리되어 각각의 역할을 수행하도록 만들어져 있다.


여기까지는 DB와 DBMS에 대한 기본적인 이해를 위한 내용이었고 이제 본론인 Tablespace로 넘어간다.


PostgreSQL에서의 Tablespace (테이블스페이스)

Tablespace는 일부 DB에서 등장하는 개념이다. 오라클과 PostgreSQL에서만 사용되고 MySQL과 MS-SQL 같은 DBMS에서는 언급조차 되지 않는 개념이다. 


하지만 PostgreSQL에서 DB는 PGDATA라는 환경변수에 지정된 디렉토리를 통째로 DB로 사용한다. 그리고 그 하위에 테이블이 파일로 생성된다. 즉 테이블스페이스를 따로 생성하지 않아도 DB에 사용자 테이블을 만들 수 있다. 기본적으로 DB로 지정된 디렉토리 전체가 하나의 기본 테이블스페이스로 인식되는 것이다. 


PostgreSQL 공식사이트에서는 다음과 같이 테이블스페이스를 정의하고 있다.


포스트그레스-큐엘에서 테이블스페이스는 DB관리자에 의해 데이터베이스의 객체가 저장될 수 있는 파일시스템의 경로로 정의된다. 테이블스페이스가 생성되면 데이터베이스 객체에 객체를 생성할 때 이름에 의해서 테이블스페이스가 참조될 수 있다.


포스트그레스-큐엘이 설치될 때 디스크레이아웃에 따라 관리자가 생성할 수 있는데 두가지 관점에서 매우 유용하다. 첫번째는 DB가 생성된 볼륨 또는 파티션에 여유공간이 부족할 때 테이블스페이스를 다른 파티션이나 디스크에 생성하여 시스템을 재구성할 때까지 DB를 확장할 수 있다. 또 다른 하나는 데이터베이스 객체의 성능 최적화를 위해 사용할 수 있다는 것이다. 예를 들어 매우 사용량이 많으면서 자주 업데이트 되는 인덱스를 위해 고성능 SSD를 장착하고테이블스페이스를 생성하여 인덱스를 SSD에 생성하여 성능을 개선하는데 사용될 수 있다.


만약 물리적으로 다른 경로를 DB에 사용하고자 할 때 테이블스페이스로 지정하여 DB를 확장할 수 있다. 테이블 스페이스는 다음과 같은 DDL 문으로 생성할 수 있으며 해당 테이블스페이스에 태이블을 생성할 수 있다.


CREATE TABLESPACE fastspace LOCATION '/ssd/mydb2/data';


CREATE TABLE emp(empno int, name varchr(12)) TABLESPACE fastspace;


DB에 생성되어 있는 테이블스페이스의 정보를 확인하고 싶을 때는 다음의 SQL 문으로 생성되어 있는 테이블스페이스 정보를 확인할 수 있다.


SELECT * FROM pg_tablespace;



그리고 PostgreSQL의 대화형 질의 도구인 psql 을 사용하면 \db;  명령으로도 확인할 수 있다.




  • alpaca623 2016.05.26 01:07 신고

    좋은글 감사합니다.

    • taeho Tae-Ho 2016.05.26 21:59 신고

      댓글까지 남겨주시니..저야말로 감사합니다..

  • 김메리 2016.06.11 23:47 신고

    도움이 많이 되었습니다 >_<

    • taeho Tae-Ho 2016.06.12 22:05 신고

      도움이 되셨다니 제가 더 감사합니다~ ^^

  • ...., 2016.10.13 13:14 신고

    정리가 잘된 좋은글 잘 읽고 갑니다. 감사합니다.

    • taeho Tae-Ho 2016.10.13 21:03 신고

      ㅎㅎ DBMS 고수께서 칭찬해주시니 쑥쓰럽네요~


직장생활을 처음 시작하고 처음으로 한 일은 개발이었다. PC에서 Access와 비주얼베이직, 델파이 등을 이용해 혼자 공부하던 SQL을 직장에서 본격적으로 공부하기 시작했다. 그리고 개발에서 엔지니어로 방향을 튼 뒤 처음 접한 것이 바로 Ingres 라는 RDBMS다. 


그리고 이 Ingres의 증손자(?)뻘 되는 PostgreSQL을 오늘 설치하고 테스트 해야할 일이 생겼다. PostgreSQL은 Post Ingres라는 의미도 갖고 있다고 하니 감회가 새롭다. (PostgreSQL은 포스트그레스-큐엘 이라고 읽는다.)


각설하고... 설치 과정과 DB 생성까지를 남긴다. 


1. yum을 이용한 PostgreSQL 설치

postgress는 postgresql의 공식 사이트인 http://www.postgresql.org/에서 소스를 다운받아 직접 컴파일하여 설치할 수도 있지만 일단 테스트니 yum을 이용해 설치했다.


root 계정에서 yum install postgresql-server 명령을 실행해 설치 한다.



당연히 인터넷에 연결되어 있어야 하고 DNS 설정도 제대로 되어 있어야만 리포지토리로 지정된 서버를 찾을 수 있다.


정상적으로 리포지토리를 찾으면 다음과 같이 설치할 패키지를 보여준다. 만약 설치되어 있지 않다면 updates가 아닌 install이라고 표시된다. 현재 8.4.20 버전이 설치될 것임을 보여준다.


Is this ok 에 y 로 응답하면 설치(업데이트)를 시작한다.



2. 계정 확인

mysql과 같은 DB는 일반적으로 root에서 설치하고 실행하는 경우가 많다. 하지만 DB가 root로 구동된다는 것은 보안 관점에서 많은 취약점을 노출시킨다. 그래서 Postgres는 root에서 실행하는 것을 매우....싫어한다.


때문에 앞에서와 같이 postgresql을 설치하면 postgres를 실행할 계정을 만들어 준다. /etc/passwd 파일을 확인해보면 다음과 같이 postgres 계정이 만들어져 있다.



postgresql 을 초기화하고 구동하려면 이 postgres 계정으로 로그인해야 한다. 때문에 postgres 계정의 비밀번호를 설정해주어야 한다. passwd 명령을 통해 비밀번호를 설정하고 ssh 또는 telnet을 재접속한다. 당연히 postgres 계정으로 로그인 해야 한다.



3. 데이터베이스 생성 경로 지정

PostgreSQL을 초기화하고 구동하기 위해서는 몇가지 설정이 필요하다. 그중에서 가장 중요한 것은 데이터베이스를 어디에 생성할 것인가? 이다.


데이터베이스의 생성 경로는 postgresql을 실행하는 계정의 환경변수에 지정하도록 되어 있다. 기본적으로 postgres 계정으로 구동하게 되므로 해당 계정의 환경변수에 설치 시 기본경로가 자동으로 설정되어 있다. postgres 계정의 홈디렉토리는 /var/lib/pgsql 이며 이 디렉토리의 .bash_profile 파일이 프로파일이다.


이 .bash_profile은 다음과 같이 확인할 수 있다.



.bash_profile에는 PGDATA 환경변수를 설정하는 내용이 포함되어 있다. 이 PGDATA라는 환경변수가 바로 postgreSQL의 DB가 생성되는 경로를 갖고 있는 환경변수이며 postgreSQL을 구동할 때 DB경로를 별도로 지정하지 않으면 이 변수의 경로를 DB경로로 지정하여 구동된다.

이 변수는 다음과 같이 env 명령으로 확인할 수 있다. (bash, ksh의 경우)



만약 DB의 경로를 다른 디스크나 디렉토리로 변경하고 싶다면 .bash_profile의 PGDATA 경로를 원하는 경로로 변경해준 뒤 다시 로그인하면 된다.그리고 이 경로의 변경은 반드시 initdb를 실행하기 전에 하는 것이 좋다. 후에 변경하려면... 좀 복잡해질 수 있다.


4. initdb 실행

initdb는 postgreSQL 설치 후 시스템카달로그를 포함하고 있는 postgres 기본 DB를 생성하는 명령어다. 이 기본DB는 postgres 라는 이름으로 생성되며 이 기본 DB 생성 후 psql과 같은 대화형 명령어를 실행한 뒤 CREATE DATABASE 명령을 통해 사용자가 사용할 DB를 생성하게 된다.



5. PostgreSQL 서버 실행

PostgresSQL 서버를 다음과 같이 실행한다. 


1. postgres 계정으로 로그인 (ssh 혹은 telnet)


2. pg_ctl start 명령 실행



3. 구동상태 확인


ps -ef | grep post 명령으로 확인.



보통 -D 옵션과 DB명을 주라고 하는데 PGDATA 환경변수의 경로에 DB가 있다면 궂이 DB명을 표시하지 않아도 된다. 


6. 사용자 DB 생성

db를 생성하기 위해서는 psql 이라는 도구를 실행하고 psql 내에서 CREATE DATABASE 쿼리문을 이용해 생성한다.



psql 명령에도 DB경로를 지정하는 옵션이 있는데 이 옵션은 하나의 서버에 물리적인 여러개의 DB서버를 운용할 때 필요한 옵션이다. 이 이야기는 initdb를 서로 다른 경로에 2번 이상 했을 경우(2개 이상의 인스턴스 운용)에만 운용하면 된다.


-- 끝~~~~ --







  • 2016.04.06 22:33

    비밀댓글입니다

    • taeho Tae-Ho 2016.04.06 22:57 신고

      ㅎㅎ 그러게요~~ 딴생각하며 썼나봅니다~
      수정했습니다~


디지털 IT 기기들이 생활 속 깊이 파고들면서 옛날 같으면 종이 문서와 사진으로 남겨질 수 많은 일상의 흔적들이 디지털 정보로 노트북이나 컴퓨터 혹은 외장하드에 쌓여가고 있다. 하지만 이렇게 남겨진 디지털 정보들은 언제든지 순간의 실수 혹은 저장 기기들의 고장으로 사라져버리기 쉬운 것도 사실이다. 


My Book Live 3TB (이하 MBL)

그래서 구입한 것이 3 Tera Byte 저장 공간을 갖고 있는 NAS 장비인 My Book Live다.



MBL을 구입한 뒤 제일 먼저 한 것은 MySQL DB를 설치한 일이다. 그리고 그누보드를 설치해 게시판까지 쓸 수 있도록 했다. 그런데 문제가 발생했다. 워낙 CPU가 저-사양이니 속도가 느린 것은 이해하겠지만 수시로 메모리 부족으로 웹서버가 Hang 되는 현상이 발생했다.


이 MBL의 CPU와 메모리는 다음과 같은 사양을 갖고 있다.



문제가 되는 것은 Memory다. 그나마 128MB가 아닌 것이 다행일 지경이다.

웹서버인 Apache가 동작을 거부(?)하는 상황에서 CPU와 RAM 상태를 보면 다음과 같다.



Memory 여유분이 12480KByte이고 Swap을 440832KByte(440M)나 사용한다. 램이 256인데 440을 쓰다니.. -.- 어떤 상황인지 통 알 수가 없다. 하지만 256 MByte의 대부분을 Apache와 Mysql이 사용하는 것은 자명하다. 위 화면에는 표시되지 않았지만 mysql이 메모리를 왕창차지하고 일하기를 거부하고 있었다.


그래서 Mysql을 튜닝해보기로 했다.


저용량 메모리 환경에서 MySQL 튜닝 - my.cnf

관계형 DBMS의 하나인 Mysql은 여타 DBMS들과 마찬가지로 많은 메모리를 사용한다. 하지만 MySQL의 전통적인 관계형 DB엔진인 myisam의 경우 튜닝여부에 따라 저용량 메모리(RAM)를 가진 기기에서도 구동이 가능하다. 이는 MyISAM 엔진이 page level locking과 row level locking을 지원하지 않고 Table Level Locking만을 지원하고 Transaction 개념을 지원하지 않기 때문이다. Transaction 개념을 지원하지 않는다는 것은 commit과 rollback 등을 사용할 수 없다는 것을 의미한다. (MyISAM 이후에 지원하는 InnoDB 엔진은 이 개념들을 모두 지원한다.)


하지만...


그런 여러 고급 기술들을 지원하지 않기 때문에 작은 메모리를 가진 NAS 기기에서도 구동이 가능한 장점(?)을 갖게 됩니다.


MySQL을 튜닝하기 위해서는 /etc/mysql/my.cnf 파일의 내용을 이해해야 한다. (위치는 설치 환경에 따라 다를 수 있다.)

하지만... 그 개념들을 하나씩..하나씩 이해하면서 튜닝하기에는 시간도 노력도 투자하기가 쉽지 않다. 그렇다면?? 이미 남들이 만들어 놓은 my.cnf에서 필요한 항목을 따다~~쓰면 된다.


우리나라의 검색엔진인 Naver나 Daum에서는 그런 정보들을 찾기 쉽지 않지만 Google 에서는 그러한 정보를 찾을 수 있었다. 역시..구글..!!


그리하여 찾은 my.cnf의 내용은 다음과 같다. MySQL 파일의 내용 중 아래에서 진하게 표시된 부분만 덮어 쓰면 된다.


[mysqld]

#

# * Basic Settings

#

user            = mysql

pid-file        = /var/run/mysqld/mysqld.pid

socket          = /var/run/mysqld/mysqld.sock

port            = 3306

basedir         = /usr

datadir         = /var/lib/mysql

tmpdir          = /tmp

language        = /usr/share/mysql/english

skip-external-locking

#

# Instead of skip-networking the default is now to listen only on

# localhost which is more compatible and is not less secure.

bind-address            = 127.0.0.1

#

# * Fine Tuning

key_buffer_size         = 16M

max_allowed_packet      = 1M

table_open_cache        = 64

sort_buffer_size        = 512K

net_buffer_length       = 8K

read_buffer_size        = 256K

read_rnd_buffer_size    = 512K

myisam_sort_buffer_size = 8M


#if no other servers are going to be connecting to this server, uncomment the following line

#bind-address            = 127.0.0.1


skip-innodb

default-storage-engine = MyISAM


max-connections = 25


query-cache-size  = 2M

query-cache-limit = 1M


thread-stack      = 256K

thread-cache-size = 2M


slow-query-log

long_query_time   = 5


[mysqldump]

quick

max_allowed_packet = 16M


[mysql]

no-auto-rehash


[myisamchk]

key_buffer_size  = 20M

sort_buffer_size = 20M


일부 내용은 수정되기 전과 동일한 값이 설정되어 있을 수 있다.


이렇게 설정한 뒤 MySQL을 재구동하거나 리부팅하면 된다.


이 값을 설정한 뒤 또 문제가 생기면 일부 값들을 다시 튜닝해보려 했으나... 3일 째 문제 발생 없이 잘 돌고 있다.



Memory는 게시판에 업로드 하거나 하면 90% 이상으로 사용량이 증가하지만 Swap을 사용하지는 않는다. Swap을 사용하기 시작하면 기기의 성능은 급격하게 떨어지기 시작한다.



  • 지후대디 2015.03.18 23:45 신고

    mysql 유용하게 이용될때가 많은데 튜닝등에 많은 참고가 될듯 합니다 환절기 건강 유의하시고 좋은 한주 되세요 ^^

    • taeho Tae-Ho 2015.03.19 09:12 신고

      무슨 문제인지는 몰라도... 4일만에.. mysql이 다운됐습니다. mysql로그에도... 서버의 message 로그에도 에러가 기록되진 않네요.. 수행되는 sql과 데이터 특성까지 봐야하는 건지..
      256 램에서 그누보드와 일정관리까지 돌리는 건 무리일 듯 싶기도 하네요.

  • 에스델 ♥ 2015.03.19 12:01 신고

    역시...구글에 공감하며...ㅎㅎ
    오늘은 날씨가 참 좋습니다.
    행복한 봄날 보내세요!

  • 토리's 2015.03.25 02:47 신고

    음. 모니위키같은 위키위키엔진은 어떠신가요. mysql과 같은 dbms를 안쓰는것으로 알고 있습니다. (파일시스템기반)
    아니면 sqllite 를 사용할 수 있는 CMS를 찾아보시는것도 나쁘지 않은 선택으로 보입니다.


게시판과 같은 글쓰기 기능이 포함된 웹페이지를 만들 때 가장 간단한 방법은 HTML 태그 중에서 <textarea></textarea>을 사용하는 것이다. 하지만 이 태그는 너무도 단순해서 HTML 코드나 이미지 첨부 또는 폰트 크기나 색상의 변경 등을 처리할 수 없는 단점이 있다. 그래서 사실상 거의 사용되지 않는다고 보는 것이 좋다.

그누보드5(GNUBOARD5) 베타에 포함되어 있는 CKEditor

그 대안으로 사용되는 것이 CKEditor와 같은 javascript로 만들어진 에디터다. 아래 화면은 내가 개발해 사용 중인 프로젝트 및 일정관리 시스템의 일정 등록 화면이다. 수행업무 내역을 입력하는 노란색 상자 내부가 CKEditor다. 게시판으로 함께 사용중인 그누보드5(beta)에 CKEditor가 포함되어 있어서 그 CKEditor를 그대로 사용했다.



위 화면의 소스를 들여다 보면 <textarea></textarea>가 존재하며 <textarea>태그에 id와 name 속성을 지정하고 아래에서 해당 id를 가진 textarea 객체를 javascript로 만든 에디터 객체로 대체(?)하는 형태를 띄고 있다.


<!-- 글쓰기 기능을 가진 페이지의 <header></header>부분에 아래 포함

<!-- 아래는 그누보드 5(beta)의 CKEDITOR를 사용하기 위한 설정 -->

<script src= "/plugin/editor/ckeditor4/ckeditor.js"></script>

<script>

var g5_editor    = "ckeditor4";

var g5_editor_url = "/plugin/editor/ckeditor4";

</script>

<!-- 그누보드5(beta)에 설치된 CKEDITOR를 사용하는 설정 -->


<!-- 실제 글쓰기 부분에서는 아래 처럼 사용 -->

<tr>

<td>내용</td>

<td colspan=3><textarea name="desc" id="desc" class="ckeditor" wrap="VIRTUAL">

수행업무내역을 상세히 입력합니다.

</textarea>

<script language="javascript">

    /* 그누보드5(beta)의 CKEditor 에디터설정을 그대로사용할 때... */

var editor=CKEDITOR.replace('desc'); 

</script>


</td>

</tr>


이런 에디터를 사용하면 본문에 이미지를 첨부하거나 표를 만들어 넣거나 또는 제목 등을 표시하는 것이 가능하다. 간단한 문서편집기 기능을 수행하기 때문이다. 


이 CKEditor는 <textarea></textarea> 태그에 rows 속성과 cols 속성을 주면 크기 설정이 자동으로 되어 편리했다.


그누보드5 정식버전에 포함되어 있는 네이버스마트에디터2.0


하지만 그누보드5 정식버전에는 CKEditor가 아닌 Naver에서 개발하여 무료로 배포하고 있는 SmartEditor 가 포함되어 있다. CKEditor보다 조금 더 무겁긴 하지만 사용자 입장에서 익숙하고 조금 더 스마트하기 때문에 많이 사용되고 있다. 2015년 2월 20일 경 다운로드 받은 그누보드5.0.30에는 2.3 버전이 포함되어 있다.


앞의 프로젝트 일정관리 화면의 CKEditor를 Naver SmartEditor2 버전으로 교체한 화면이다.



CKEditor 보다 조금 더 깔끔한 스타일을 보여준다. 물론 CKEditor의 스킨을 더 스마트한 버전으로 교체하면 동일한 수준으로 사용할 수 있다.


이 네이버 스마트에디터도 <textarea></textarea> 객체를 대체하는 형식으로 만들어져 있기에 소스수준에서의 적용방법은 거의 동일하다. 다만 Naver SmartEditor의 경우 <textarea></textarea> 태그의 cols 속성은 동작하나 rows 속성은 제약이 있다. 스마트에디터의 최소 높이가 소스 내부적으로 고정되어 있어 일정 높이 이하로 높이를 줄일 수 없게 되어 있다.

위 화면의 Naver SmartEditor2의 사용 예제 소스를 보면 다음과 같다.


<!-- CKEditor와 마찬가지로 페이지의 <head></head>에 다음의 내용을 추가

<!-- 아래는 그누보드 5의 SmartEditor2를 사용하기 위한 설정 추가로 설정할 필요없음. -->

<script type="text/javascript" src="/plugin/editor/smarteditor2/js/HuskyEZCreator.js" charset="utf-8"></script>

<script language="javascript">

var g5_editor    = "smarteditor2";

</script>

<!-- 그누보드5에 설치된 SmartEditor2를 사용하는 설정 -->



<!-- 실제 쓰기 기능을 가진 페이지의 textarea 태그 부분에 다음내용 추가 -->

<tr>

<td>내용</td>

<td colspan=3><textarea name="desc" id="desc"  class="smarteditor2" style="width:100%;height:220px; display:none;">

수행업무내역을 상세히 입력합니다.

</textarea>

    <!-- 네이버 스마트에디터2 적용 부분 시작-->

<script src="/plugin/editor/smarteditor2/js/HuskyEZCreator.js"></script>

<script>var g5_editor_url = "/plugin/editor/smarteditor2", oEditors = [];</script>

<script src="/plugin/editor/smarteditor2/config.js"></script>

<script>

function submitContents(elClickedObj) {

oEditors.getById["desc"].exec("UPDATE_CONTENTS_FIELD", []); // 에디터의 내용이 textarea에 적용됩니다.

// 에디터의 내용에 대한 값 검증은 이곳에서 document.getElementById("ir1").value를 이용해서 처리하면 됩니다.

try {

elClickedObj.form.submit();

} catch(e) {}

</script>

    <!-- 네이버 스마트에디터2 적용 부분 끝.-->

</td>

</tr>

<!-- CKeditor와는 달리 다음과 같이 Submit 부분에 onclick 이벤트 추가 -->

<tr>

<td colspan=4><center><input type=submit value="저장하기" onclick="submitContents(this)"><input type="reset" name="reset" value="취소" onClick="window.close();"> </center></td>

</tr>


네이버 스마트에디터 2.0의 에디터 최소 높이 조정

네이버 스마트에디터는 소스 내부적으로 최소 높이가 지정되어 있다.그래서 그 높이를 최소 높이 이하로 줄이려고 <textarea></textarea> 의 rows 속성이나 style의 height를 아무리 줄여도 일정 높이 이상으로는 줄일 수 없다. 만약 이 높이를 줄이려면 에디터의 최소 높이 즉 높이를 지정하지 하지 않을 경우의 기본 높이를 변경해 주어야 한다.


이 스마트에디터의 최소 높이는 SE2BasicCreator.js 파일에 htDimension의 nMinHeight 값으로 지정되어 있다.

var htDimension = {

nMinHeight:220,

nMinWidth:parseInt(elIRField.style.minWidth, 10)||570,

nHeight:elIRField.style.height||elIRField.offsetHeight,

nWidth:elIRField.style.width||elIRField.offsetWidth

};


위와 같이 220으로 변경하면 에디터의 초기 높이 기본값이 변경된다.


만약 에디터의 높이를 더 높이고자 한다면 <textarea></textarea>의 style 에서 height를 220px 보다 크게 주면 된다.


이 네이터 스마트에디터의 높이를 조정하는 방법을 알아내는데...꼬박...하루(8시간 정도)가 걸렸다.

난..웹 개발자의 소양은 갖추지 못한 모양이다. 

웹 개발은 너무 어렵다.



  • 에스델 ♥ 2015.02.26 16:04 신고

    직접 개발해서 사용중이신 프로젝트및
    일정 관리 시스템이 멋집니다.^^
    좋은 하루 보내세요!

    • taeho Tae-Ho 2015.02.27 12:52 신고

      과한 칭찬에 꽈배기가 될 것 같습니다.


요즘은 게시판 위주의 홈페이지를 만들기가 무척 편해졌다. 제로보드XE나 그누보드(GNUBOARD)를 아파치와 PHP 그리고 Mysql 환경에 설치하면 여러 게시판을 가진 포탈스런(?) 홈페이지를 뚝딱~만들 수 있다.


아래 화면은 그누보드(GNUBOARD5)를 이용해 한나절만에 만든 게시판 위주의 자료실 홈페이지다.



ATOM CPU(D510??으로 기억)달린 2G 메모리의 4년쯤된 컴에 레드햇 6.3을 깔고 (웹서버로) 보니 mysql이 없어서 yum의 리포지토리로 레드햇CD를 등록한 뒤 yum을 이용해 mysql을 설치했다.


yum을 이용해 mysql을 설치하면 의존성을 자동으로 체크하여 의존적인 패키지를 함께 설치해주기 때문에 무척 편리하다. 일일히 의존성 체크해가며 설치하자면 하루도 더 걸릴 듯... -.-


하지만 yum을 사용하여 리눅스 설치 CD의 패키지를 설치하려면 그냥은 안되고 yum에서 설치 cd를 리포지토리로 사용하도록 설정해 주어야 한다. 리눅스 (redhat, centos)의 설치 cd를 yum 리포지토리에 추가하는 방법은 유명하신 스누피님 블로그에서 찾아볼 수 있다. (여기)


아파치, PHP, MYSQL의 설치가 완료되면 게시판을 선택하여 설치한다. (여기서는 설명하지 않는다.)


게시판 소스을 설치하고 나면 게시판을 생성하여야 하는데 일반 글과 작은 이미지 파일 정도를 업로드 하는데는 별 문제가 없지만 제안서나 브로셔 등 사이즈가 10M 이상되고 그런 파일들을 10개 까지 업로드 하려 하면 많은 문제가 발생한다.


아파치는 DOS공격이나 DDOS 공격을 방어하기 위해 하나의 서버사이드스크립트(php, jsp 등)가 한번에 실행될 수 있는 시간을 제한하거나 웹페이지에 접속하고 아무런 후속 요청이 없으면 세션 타임아웃이 발생해 접속이 끊어지도록 되어 있다. 그 외에도 대용량 파일을 게시판에 업로드 할 때 사용되는 세션의 메모리나 시간, 파일 크기 등을 여러 파라미터를 통해 조정을 해줘야 원활하게 자료실 형태의 게시판으로 운영할 수 있다.


먼저 조정해줘야 할 것은 게시판 자체의 파일 업로드 크기 제한이다.

아래 이미지는 그누보드5의 업로드 파일 크기 제한 설정 화면이다.



기본적으로 1M Byte로 되어 있었는데 10M 바이트로 늘린 화면이다. 하나의 게시물에 여러개의 파일이 올라가도 각각 개별적인 파일의 크기만 제한한다. 즉 위처럼 설정되어 있다면 10M 파일을 여러개 업로드 할 수 있다. 이 설정은 게시판~마다 설정해줘야 한다.


하지만 이 설정만 변경해서는 용량이 큰 파일을 업로드할 수는 없다.

다음은 php.ini 파일에서 업로드 파일 관련 설정을 변경해주어야 한다. php.ini는 /etc 디렉토리에 있다.



먼저 file_uploads가 On으로 되어 있어야 하며

upload_max_filesize를 원하는 용량으로 변경해주면 된다. 위의 설정은 한번의 파일 업로드 즉 하나의 php 스크립트가 실행되면서 해당 세션에서 업로드할 수 있는 용량을 의미한다.


만약 아파치서버의 임시디렉토리가 포함된 파일시스템의 용량이 작다면(일반적으로 /tmp) upload_tmp_dir을 설정할 필요도 있다.


다음은 php.ini에서 post 메소드 실행 시 사용할 수 있는 메모리 제한값을 설정해 주어야 한다.



그누보드의 경우(대부분 그럴 것으로 보임) 파일을 업로드 하면 POST 메소드로 전송이 되는데 이때 업로드하는 파일의 크기만큼 POST로 전송되는 메시지가 커진다. 이 설정도 보안과 관련이 있지만 게시판의 기능인 자료실 용도이니 만큼 제한을 작게 할 수는 없다. 아펭서 파일의 업로드크기 제한을 100M로 했으므로 POST 시 사용할 수 있는 메시지의 크기도 100M보다 커야한다. 


위에서는 128M로 설정했다. 왜 100이 아니고 128이냐고 묻는다면 8의 배수 그리고 16의 배수, 32의 배수, 64의 배수로 설정해주는게 습관이 돼서라고 이야기 해주겠다.


그리고 메모리 관련 설정이 또 하나가 있다. (제약이 참 많기도 하다.) 앞에서 POST 메소드에서 사용할 수 있는 메모리를 설정해 주어도 PHP 스크립트 하나에서 사용할 수 있는 메모리 제약이 걸려있기 때문에 post_max_size 보다 아래의 memory_limit 가 작다면 의미가 없다.


아래 처럼 post_max_size인 128M 보다 크거나 같게 설정한다.



이제 업로드 파일의 용량과 업로드 시 사용되는 웹서버 측의 메모리 제약에 대한 설정은 모두 변경하였다.


하지만 이것만 설정해선 또 오류가 발생할 수 있다. 파일을 업로드 하는 것은 하나의 PHP 스크립트 파일이 아파치 대몬에 의해 실행되는 것이다. PHP에선 하나의 스크립트가 실행될 수 있는 최대 시간도 제한이 걸려 있다. 만약 100M의 업로드에 제약이 걸린 시간보다 오랜 시간이 소요된다면 timeout 오류가 발생할 수 있다. 이 문제를 예방하기 위해 하나의 php 스크립트가 실행될 수 있는 최대 실행시간 즉, max_execution_time 을 변경해준다.



60초 이내에 100M 바이트의 파일 업로드가 완료되어야 한다. 만약 시간이 부족하다면 더 늘려주면 된다. 단위는 초다.


이제 아파치 대몬을 재구동하고 파일 업로드를 해보라..

잘 되는가?? ^^





블로그를 운영하는 블로거에게 최대의 숨겨진 고민(?)은 블로그가 설치된 서버가 내것이 아니라는 것이다. 블로그를 운영한 시간이 길면 길 수록 블로그에 올려져 있는 포스트들은 자식과 같이 느껴져서 블로그가 없어지는 것을 상상하는 것은 너무도 끔찍한 일이다. 게다가 워낙 많은 포스트 탓에 하나씩 하나씩 다른 블로그로 이사하는 것 조차 불가능한 블로거는 지금 운영하고 있는 블로그 서비스가 문을 닫으면 완전..!! 낙동강 오리알 신세가 될 수 밖에 없다.


하지만 티스토리는 다르다. 티스토리는 소스가 오픈된 오픈소스 블로그이기 때문에 몇몇 다른 블로그로 이사가 가능하다.


예전에 올린 포스트(티스토리 블로그를 설치형 블로그인 태터툴즈(TextCube)로 이사하기) 처럼 별도의 호스팅서비스에 태터툴즈를 설치하고 데이터를 복구하면 똑같은 쌍둥이 블로그를 만들 수 있다. 이것은 티스토리가 오픈소스 블로깅 시스템인 태터툴즈에 기반하였기 때문에 가능한 일이다.


하지만 태터툴즈, 현재 텍스트큐브로 불리는 설치형 블로그는 개발이 중단된 상태다. 텍스트큐브를 개발하던 회사가 구글에 인수되면서 개발이 중단되었기 때문이다. 그래서 티스트로리를 떠난다 해도 개발이 중단된 텍스트큐브의 마지막 버전을 사용해 블로그를 새로 만들기는 조금 찜찜하다.


그래서 찾아본 것이 바로 최근 가장 많은 사용자를 확보하고 있는 워드프레스로의 데이터 이전 방법이다. 워드프레스는 국산 설치형 블로그는 아니지만 전세계적으로 가장 많은 블로거를 확보하고 있는 설치형 블로그로서 텍스트큐브처럼 오픈소스이기 때문에 수 많은 자발적으로 스킨이나 플러그인을 개발하는 개발자들을 확보하고 있다.


자..본론으로 들어가자. 


먼저 티스토리에서 데이터를 백업 받고 워드프레스가 설치된 서버에 FTP를 이용해 업로드 해 두어야 한다.백업은 앞선 포스트에서 설명하였으므로 생략한다. ^^


그리고 워드프레스를 설치해야 한다. 워드프레스 한글판은 이곳에서 다운로드 받아 설치하면 된다. 설치 과정 또한 어렵지 않으며 다른 곳에 설치 방법이 잘 소개되어 있으므로 생략한다~ ^^


1. TTXML 플러그인 다운로드 


워드프레스가 설치되어 있다면 TTXML 이라는 워드프레스의 플러그인을 다운받아야 한다. 

다운로드 주소는 이곳이다. [  http://wordpress.org/plugins/ttxml-importer/installation/  ]


2. TTXML 플러그인 업로드


다운로드 받은 TTXML 플러그인을 워드프레스에 설치하기 위해서는 zip 파일을 압축해제하고 FTP를 이용해 업로드를 해야한다.


먼저 압축을 해제한다. 폴더이름을 살려서 압축을 푼다.


압축을 해제하였으면 FTP접속하여 다음과 같이 워드프레스의 설치 경로아래의 wp-content/plugins 디렉토리에 ttxml-importer 와 같이 폴더 통채로 업로드를 한다.


3. TTXML 모듈 활성화


ttxml 임포터를 plugins 디렉토리에 복사해 넣었으면 워드프레스의 플러그인에 ttxml이 보이게 된다. 이 ttxml을 활성화 시킨다.

위의 화면 처럼 플러그인 설정화면에서 TTXML을 활성화를 클릭하면 비활성화 버튼으로 바뀌어 보인다. 비활성화 라고 표시되어 있다면 활성화 된 것이다.


4. 티스토리 백업 XML 파일 임포트


TTXML 플러그인이 정상적으로 활성화 되면 도구 메뉴 화면에 TTXML이 보인다.    


다음과 같이 서버에 업로드한 티스토리의 백업 XML 파일 위치를 입력한다.

PC에 XML을 저장해두고 업로드하게 되면 캐릭터셋 문제 혹은 XML파일의 전송 중 특수문자 깨짐 현상 등으로 인해 제대로 복구가 안될 수 있다. 가장 좋은 방법은 서버에 FTP를 이용하여 업로드하고 위의 그림처럼 로컬의 경로를 직접 지정해주는 방법이다. 나의 경우 205 MByte 짜리의 XML 백업파일이 정상적으로 복구되는 것을 확인할 수 있었다.


위의 그림에서 "제출" 버튼을 누르면 다음과 같이 복구되는 과정을 속~시원하게 보여준다.


5. 티스토리에서 워드프레스로 블로그 이사 완료.


이렇듯 오픈소스의 개방성과 호환성은 상용툴들의 그것에 비할바가 아니다. 하지만 다음에서 인수한 티스토리의 경우 기술지원이나 서비스의 중단은 쉽게 발생하지는 않을 것이다. 인터넷의 대부분의 컨텐츠가 블로거들에 의해 블로그에서 생산되고 전파된다. 최근 SNS가 커뮤니케이션 수단으로 각광받고 있지만 주요 컨텐츠들은 블로거들에 의해 생산되어 블로그에 저장되는 것이 일반적이다. 따라서 다음이 티스토리를 버릴 가능성은 매우 희박하다고 생각된다. 당연히 티스토리의 서비스도 지속될 것이다.


하지만 혹시 모를 불상사에 대비하거나 독립형 블로그의 유혹이 강해질 때를 대비해서 워드프레스로의 블로그 이사를 테스트해보았고 성공적으로 이사가 가능함을 알게되었다. 이제 열심히 주기적으로 블로그를 백업해두기만 하면 된다.



  • 이개락 2016.12.30 13:06 신고

    안녕하세요
    궁금한 게 있는데요,

    티스토리에서 블로그 API 와 백업 기능을 12월 16일 부로 없앴는데요,
    해서 워프로 이사하는 데 위와 같은 방식으로 진행하기가 까다로워졌습니다.
    혹시 백업이 가능하던 시절 xml 마크업을 공유받을 수 있을까요

    지금은 게시글 가져오기가 단일포스팅에 한해서만 가능해서 약 100개의 글을 가져온다는 가정하에
    100개의 xml 을 다운받아, 취합해서 위와 같은 방식으로 워프에 import 할 생각인데요

    어떤 마크업으로 취합해서 워프관리자에서 import 할 수 있는지 궁금합니다.
    감사합니다.

    • taeho Tae-Ho 2016.12.30 15:51 신고

      아...백업 받아놓은 데이터를 찾아봐야겠네요. URL을 이용해 포스트를 가져오고 해당 XML 마크업으로 변환해 저장한 뒤 워드프레스에서 불러오는 방식으로 이사하시려는 건가요? 프로그래밍도 할 줄 아신다면 좋은 방법이 될지도 모르겠네요.

    • 이개락 2016.12.30 16:03 신고

      빠른 답변 감사드립니다.

      네 말씀 하신 방법으로 진행하려는데
      글이 1800개가 넘어서 가능할 지 모르겠네요..
      일단 시도는 해보려구요
      성공하면 포스팅과 댓글로 알려드리겠습니다.
      혹시 백업 데이터가 있으시다면 마크업만 공유부탁드립니다 ^^

    • taeho Tae-Ho 2016.12.30 17:49 신고

      이메일 주소 보내주시면...백업받아두었던 파일에서 샘플링해서 보내드릴께요~

    • 2016.12.30 21:06

      비밀댓글입니다


조그마한 웹페이지를 하나 만들어도 Internet Explorer와 Chrome, Firefox 등 여러 브라우저에서 정상적으로 동작하는지를 검토해야하고 게다가 모바일에서까지 잘 동작하는지 체크하고 안되면 수정하는 것은 많은 웹개발자들에게 큰 어려움이다.

어쩌다 한번 웹 소스를 수정하는 나에게도 이건 정말 욕나오는 시추에이션이다.

오늘도 그런 일이 하나 있었다. 그런데 이 경우는 엄밀하게 이야기해서 "나의 실수"였지만 그 실수를 유발하는 것은 다름아닌 Microsoft의 IE였다.

뭔고하니 바로 자바스크립트에서 웹페이지상에 생성된 객체(select box, text box 등)를 조회하여 해당 객체를 리턴해주는 getElementById() 함수의 동작방식이다.

아래와 같은 소스가 있다.

<script language=javascript>

function dateupdate()

{

var target = document.getElementById("order");

iudate=target.value;

opener.location.href="request_issuedate_update.php?rqid=<? echo $rqid; ?>&updatedate=" + iudate + "&olddate=<? echo $udate ?>";

window.close();

}

</script>

<body>

<br>

<table border=1 width=250>

<tr>

<td>이슈 기한/요청일자</td>

</tr>

<tr>

<td><input type=text name=order size="15" maxlength="15" value="<? echo $udate; ?>" readonly>

</td>

</tr>

<tr>

<td><br><input type=button value="변경하기" onClick="dateupdate();"></input></td>

</tr>

</table>

위의 소스는 IE9.0에서 잘 실행된다. 하지만 Chrome 브라우저에서는 에러가 발생한다. 그 이유를 찾는데 두 시간 여가 걸렸다. 이 얼마나 시간낭비인가? 그리고 그 이유는 아주 단순한데 있었다. 이유가 뭔고하니...

getElementById() 함수는 객체의 ID를 기준으로 Document에 있는 객체를 찾는다... 그런데 <input type=text name=order size....> 의 order 입력상자는 name은 갖고 있지만 ID는 갖고 있지 않다. 때문에 크롬에서는 동작하지 않고 getElementByID() 함수가 null 을 리턴한다.

하지만 IE에서는 이상하게도 위의 소스가 에러없이 동작한다. 추측하건데 ID가 지정되지 않았으면 name 키워드로 찾아주는 불필요한 센스(?)를 갖고 있는 것 같다. 

언뜻볼때 ID가 없으면 알아서 객체의 name으로 찾아주는 MS의 친절함 같겠지만 이런 과잉친절은 절대 있어서는 안된다. 왜냐하면 IE는 Java Script가 실행되는 운영체제의 역할을 수행한다. 하지만 Java Script는 IE, Chrome, Firefox 등 다양한 브라우저(가상플랫폼) 위애서 소스의 수정없이도 정상적으로 실행되도록 "엄격한" 규칙의 준수가 필요하기 때문이다.

위의 소스는 다음과 같이 두줄이 수정되어야 IE와 Chrome 두 브라우저에서 동일하게 정상적으로 실행된다.

<script language=javascript>

function dateupdate()

{

var target = document.getElementById("closedate");

iudate=target.value;

opener.location.href="request_issuedate_update.php?rqid=<? echo $rqid; ?>&updatedate=" + iudate + "&olddate=<? echo $udate ?>";

window.close();

}

</script>

</head>

<body>

<br>

<table border=1 width=250>

<tr>

<td>이슈 기한/요청일자</td>

</tr>

<tr>

<td><input type=text name=order id="closedate" size="15" maxlength="15" value="<? echo $udate; ?>" readonly>

</td>

</tr>

<tr>

<td><br><input type=button value="변경하기" onClick="dateupdate();"></input></td>

</tr>

</table>





윈도 서버의 IIS와는 달리 Java 가상머신 위에서 구동되는 톰캣은 하나의 머신에 여러개가 설치되어 각각 구동될 수 있다. 특히 윈도서버에 설치되는 이런 저런 솔루션들은 톰캣과 JDK를 내장하고 웹서비스를 제공하는 경우가 있다. 이런 경우 JDK와 톰캣이 2개 이상 동시에 구동된다.

톰캣은 기본적으로 TCP/8080 포트로 웹서비스를 제공한다. 두개를 설치하였다면 둘중 하나의 서비스 포트를 8080 이외의 다른 포트번호로 변경하여 주면 두개의 톰캣이 각기 다른 JDK를 이용해 구동되는 것이 가능하다.

하지만 여기에서 문제가 발생하는 경우가 있다. 각각 다른 웹서비스인 두개의 톰캣은 사용자 로그인(웹 서비스 로그인) 세션관리를 위해 JSESSIONID라는 세션쿠키(?)를 사용한다. 그런데 서로 다른 JDK에서 구동되는 두개의 톰캣이 이 JSESSIONID라는 세션쿠키를 공유한다라는 조금은 이해가 안되는 문제가 발생한다. (지금도 왜 이렇게 만들었는지 이해가 안감... -.-)

즉, A와 B 두개의 톰캣이 설치되어 있을 때 C라는 PC에서 웹서비스 A와 B에 각각 다른 사용자 계정으로 로그인하면 먼저 로그인한 A라는 톰캣의 웹서비스에 로그인한 세션이 풀려 다시 로그인 페이지로 연결되는 문제가 발생하는 것이다.

톰캣에 대한 지식이 부족한 나에게 이 문제는 조금은 커다란 벽(?)처럼 느껴졌다. 한회사에서 만든 두 제품이 각기 다른 버전의 JDK를 사용해야만 하도록 한 것이나, 두개의 전혀 다른 성격의 제품을 하나의 서버에 설치하지 않기로 했다(누구 맘대로???)는 개발팀 스스로의 결정(?)을 보며 참 답답함을 금치 않을 수가 없었다.

결국... 스스로 문제의 해결책을 찾아야 했다..(목마른 자가 우물을 파는 법~~)

방법은 톰캣의 환경설정에서 그리 어렵지 않게 찾을 수 있었다. 톰캣에서 사용하는 JSESSIONID의 이름을 바꿔주면 된다는 아주 단순하고 쉬운 방법이었는데, 톰캣 왕초보인 필자는 도대체 어디에서 어떤 방법으로 설정을 바꿔줘야하는지를 찾는데 시간이 좀 걸렸다.

그 방법을 간단히 소개하고 포스트를 마무리 한다.


1. 톰캣 실행파일 (tomcat6w.exe)를 찾아 실행한다.

톰캣이 설치된 경로의 bin 폴더에 가면 아래와 같이 tomcat6w.exe라는 실행파일을 찾을 수 있다. 이 파일을 찾아 실행한다.

2. Apache Tomcat 6 Properties 창이 실행되면 java 탭으로 이동하여  Java Options: 부분에 아래 적색 박스의 내용을 입력한다. 이때 JSESSIONID 의 이름을 적색박스의 내용 처럼 다른 이름으로 지정해 주면 된다. (오타 주의!!!!)

즉, SESSION_COOKIE_NAME과 SESSION_PARAMETER_NAME의 기본값이 JSESSIONID를 다른 이름으로 변경해주면 된다는 결론에 도달하게 된다. 두개의 톰캣을 운영중이라면 서비스에 등록된 톰캣의 설정을 변경해주는 것이 편하다 하겠다.


다음에는 두개의 톰캣을 서비스관리자에 등록하는 방법을 찾아야 할 듯 하다.




  • 초보웹개발자 2013.11.28 13:21

    안녕하세요?
    JAVA기반 초보 웹 개발자입니다.
    현재 저희 회사에서도 JSESSIONID때문에 논의가 이어졌는데요,
    다름이 아니라, 솔루션에서 필요한 쿠키를 자체 생성하기 때문에 그 외의 쿠키인 JSESSIONID 쿠키를 삭제하란 지침이 내려왔습니다.
    혹시, 톰캣에서 말고, JSP에서 JSESSIONID가 생성 안되게 할 수 있는 방법은 없나요?
    알아본 바로는 저것을 없애면 session기능을 아예 못쓰게 된다는 말도 있는데, 검색을해도 당췌 나오질 않습니다. 관련 포스팅이나, 책자가 있다면 가르침 청해도 될런지요?

    • taeho Tae-Ho 2013.11.28 13:40 신고

      에구..전 개발자는 아니고 취미삼아 조금씩 코딩하는 수준의 사람입니다.
      세션과 쿠키는 모두 웹페이지와 서버가 정보를 공유하고 서로에게 전달하기 위해 사용되는 것인데..
      한번 참고해보세요.
      https://groups.google.com/forum/#!topic/ksug/7Cn16nBjlrU



오랫만에 PHP 용 게시판의 대명사 제로보드를 설치할 일이 생겼다. 일 때문이라기 보단 그저 궁금함..?? 때문이기도 했다. 제로보드에서 XpressEngine으로 이름을 바꾸고 네이버의 탈(?)을 쓰긴 했지만 오픈소스를 유지하며 계속 버전업이 되고 카페모듈까지도 지원이 되니 개발에 취미가 없는 나 같은 사람에게는 딱~좋은 무료 게시판 소스다.
그저 감사히 사용할 따름이다.

UTF-8 캐릭터셋을 지원하는 리눅스 서버에 http://www.xpressengine.net 에서 다운받은 xe.tar를 올려놓고 (zip으로 제공한다.) tar를 해제한 뒤 http://IPAddress/xe 와 같이 브라우저로 접근한다. (DocumentRoot의 xe 디렉토리 아래에 압축을 해제한경우)

설치하다보니... 이런... GD 라이브러리가 사용 불가능하단다.



gd 라이브러리 설치하려고 http://ftp.daum.net/centos 로 가서 최신 gd-devel 패키지를 받아 설치하니 이런... 뭐 이렇게도 디펜던드한 패키지가 많은지.. -.- 디펜던시가 있는 패키지를 받아 설치하려하면 또 다른 패키지가 필요하고...그래서 그냥 다음과 같이 yum 으로 업데이트를 했다.

# yum -y install gd gd-devel


그리고 나서 하나더... 빼먹은 것을 설치 했다.. 바로 php-gd... 위에서 한꺼번에 설치해도 된다.

# yum install php-gd


설치가 완료된 뒤 다음과 같이 gd 관련 패키지가 설치되어 있다면 gd 모듈 관련 XpressEngine 설치 문제는 사라지고 설치가 잘 진행된다.


다시 XpressEngine의 설치를 진행하면 gd 관련 오류가 사라진 것을 확인할 수 있다.


XpressEngine을 설치하고 나면 관리 페이지 접속으로 접속이 된다. 이 때 접속되는 페이지의 URL.은 다음과 같이 URL이 단축되어 접속을 시도하게 된다.

http://IP-Address/xe/admin

그런데 이 URL로 접속을 시도하면 404 Not Found가 뜨는 경우가 발생하였다.


단축되기 전의 URL로 접속하여 정상적으로 접속된다면 아파치의 mod_rewrite 모듈이 정상동작하지 않거나 설치되어 있지 않기 때문이다.


이 mod_rewrite 모듈의 설치 여부를 확인하기 위해서는 다음과 같이 아파치 웹서버의 설정파일인 httpd.conf 를 열어 mod_rewrite.so 모듈이 LoadModule 라인에 추가되어 있는지 확인하면 된다.

만약 위와 같이 포함되어 있는데도 단축 URL로 접속이 안된다면 다음과 같이 httpd.conf 파일의 아랫 부분을 확인하여야 한다. 확인해야 하는 섹션은 아파치 웹서버의 DocumentRoot 경로의 접근 권한을 설정하는 부분이다.

아래의 두 부분 중 아랫부분을 다음과 같이 수정해주면 된다.

DocumentRoot의 물리적 경로에 해당하는 <Directory "/var/www/html"> 섹션의 AllowOverride None
AllowOverride All 로 변경해주어야 한다.


None 을 All 로 수정하고 저장한 뒤 아파치 대몬을 재구동하여야 한다.
아파치를 재구동 한 뒤 http://IP-Address/xe/admin 으로 접속하면 잘 접속이 된다.


 


  • 데벨 2012.05.15 22:08

    감사합니다!



처음 Java를 공부했던 2000년 즈음에는 쓸만한 java 개발환경을 지원하는 IDE가 없었다. 비주얼베이직이나 비주얼C는 훌륭한 개발환경을 Microsoft에서 제공하기 때문에 "자바는 뭐 이따위야..."라는 생각을 했었던 기억이 있다.

하지만 10여년이 지난 지금 Java 언어는 이제 개인홈페이지에도 쓰일 만큼 대중화가 되었고 대부분의 엔터프라이즈 급 어플리케이션 개발 프로젝트의 대부분에 주요 언어로 사용되고 있다. 그리고 여러 Java 개발환경 지원도구들도 개발되어 많은 개발자들의 개발을 도와주고 있다.

비록 지금은 개발분야의 일을 하고 있지는 않지만 이따금씩 코딩이 필요한 경우가 있다. 엔지니어 조직을 관리하면서 기술업무를 병행하기 위해 만들었던 프로젝트관리 및 엔지니어 일정관리(http://cybercafe.tistory.com/9) 페이지와 심심해서(?) 만들어본 개인 일정관리(http://cybercafe.tistory.com/197)가 그런 예라고 할 수 있다. 이 두 웹페이지는 Apache-PHP-Mysql 기반으로 만들었다. 아무래도 Java 보다는 PHP가 더 쉽기(?) 때문이다.

하지만 두 웹페이지의 일정을 구글 캘린더와 연동해 보고 싶다는 생각이 퍼뜩~~들었다. 그래서 방법을 찾아보니 역시.. PHP의 경우 구글이 공식적으로는 지원하지 않고 있는 듯 하다. 서드파티 개발업체에서 제공하는 모듈을 사용해야 한다고 한다. 반면에 JSP의 경우 구글에서 공식적으로 지원하고 있고 연동방법도 더 쉬운 듯 하다.

결국 미루고 미루었던 두 웹사이트의 JSP 버전으로의 포팅을 시작할 때가 된것 같다. 그래서... 안드로이드 프로그래밍을 맛보기 위해(http://cybercafe.tistory.com/200) 설치했었던 이클립스를 다시 설치했다.


짧은 자바 지식으로 과연 포팅에 얼마나 시간이 소요될지 ....
나이먹고 쫌스러운 코딩을 해야하는게 버겁긴 하지만 일정관리와 구글캘린더 연동을 꼭 시켜보고 싶으니 어쩔 수 없다.

가자..!!!



2 byte 코드를 사용하는 한글을 데이터베이스에 저장할 때 DB의 잘못되어 있는 캐릭터셋 설정은 많은 개발자와 DBA에게 혼란을 야기한다. 아주 오래전 신입사원시절에 Ingres라는 DB의 기술지원을 할 때도 가끔 한글코드가 잘못 지정되어 있어 DB를 업그레이드하거나 다른 서버로 마이그레이션할 때 불편함을 겪곤 했다.

그리고 15년이 지난 요즘...취미삼아 붙잡고 있는 Apache, PHP, MySql 의 환경에서도 여전히 DB의 한글코드 문제는 이따금씩 발생하곤 한다.

예를 들자면 웹페이지의 한글은 정상적으로 깨지지 않고 표시되는데 웹페이지를 통해 DB에 한글을 저장하고 다시 웹페이지에서 불러오면 DB에 저장한 한글데이터가 깨져보이는 현상이 대표적인 "한글깨짐" 증상이다.

이때 확인해야할 것은

1. 웹브라우저의 캐릭터셋.
2. 웹서버의 캐릭터셋.
3. 데이터베이스 서버의 캐릭터셋.
4. 생성되어 있는 데이터베이스의 캐릭터셋.
5. DB에 접속하는 세션의 캐릭터셋.

크게 4가지라 할 수 있다.

이 네가지 캐릭터셋 설정 중 어느하나가 다른 세개와 다르게 설정되어 있다면 여러가지 증상이 발생할 수 있다. DB에는 정상적으로 저장되는데 웹페이지에서 조회하여 보면 깨져있거나, 웹브라우저 화면에선 정상적으로 DB에 저장되어 있는 것 처럼 보이는데 DB의 쿼리툴에서 조회해보면 깨져서 저장되어 있을 수도 있다. 초심자로서는 잘 이해되지 않는 경우일 수도 있다.

즉, 클라이언트인 웹브라우저의 캐릭터셋부터 DB에 접속하는 세션의 캐릭터셋, 그리고 데이터베이스서버와 데이터베이스 생성시 지정되는 캐릭터셋, 마지막으로 테이블 생성 시 지정된 캐릭터셋이 일관되게 설정되어 있어야만 어떠한 환경에서 저장, 조회하더라도 문제가 발생되지 않는다.

 

먼저 웹브라우저의 캐릭터셋을 보자.

웹브라우저의 캐릭터셋은 서버에 저장되어 있다가 웹브라우저가 호출하는 웹페이지의 소스에서 설정할 수 있다.


meta 태그로 설정되는 charset = "utf-8" 부분이 바로 웹브라우저가 해당 웹페이지를 호출했을 때 설정할 브라우저의 캐릭터셋이다.

다음은 웹서버의 캐릭터셋이다.


아마치의 경우 httpd.conf 파일에서 'AddDefaultCharset' 파라미터에서 캐릭터셋을 설정할 수 있다. 기본적으로 utf-8을 지원하는데 이부분은 특별히 건드리지 않아도 utf-8이나 euckr을 처리해 주는 것 같다. 아직까지는 웹서버의 캐릭터셋으로 인해 DB에 저장되는 데이터의 캐릭터셋 오류는 보지 못했다.
(난 현재 웹이나 DB엔지니는 아니므로 경험부족일지도 모른다.. -.-)

세번째는 데이터베이스 서버의 캐릭터셋 설정이다.

mysql의 경우 이부분이 참 복잡했다. 한글이 깨지는 경우 대부분 서버의 캐릭터셋 환경과 생성된 DB의 캐릭터셋이 틀린 경우인것 같은데 또 꼭 그렇지만도 않은 듯 하다.

먼저 서버의 캐릭터셋 환경을 보면...


왜인지는 모르겠지만 character set client와 character set connection의 Global value가 latin1 으로 되어 있다. 이 의미는 클라이언트 프로그램 즉 브라우저를 통해 DB에 저장할 데이터를 전달받은 아파치 웹서버가 DB에 세션을 맺을 때 특별한 캐릭터셋을 지정하지 않으면 latin1 으로 캐릭터셋을 지정한다는 의미다.
한글은 2바이트 코드이고 latin1은 1바이트 코드다. 따라서 2바이트인 한글을 쪼개서 저장하면 당연히 깨져서 저장이 될 수 밖에 없다. 만약 이런 환경이라면 아무리 데이터베이스를 euckr 이나 utf8로 생성하더라도 클라이언트를 통해 커넥션을 맺고 한글을 저장하면 깨져서 저장될 수 밖에 없다.

네번째, 데이터베이스의 캐릭터셋 설정


각 데이터베이스마다 사용할 캐릭터셋을 다르게 지정할 수 있다.

마지막으로 문제해결의 키를 가진 DB 접속 세션의 캐릭터셋...

DB에 접속하는 세션의 캐릭터셋을 잘 이용하면 한글깨짐의 문제를 해결할 수 있다. 하지만 그 전에 앞에서 설명한 mysql 서버의 캐릭터셋 환경을 utf8로 통일시켜주는 것이 가장 좋은 방법이라는 점을 명심해야한다. mysql의 소스를 가져다 컴파일하여 설치할 때 컴파일옵션에 캐릭터셋을 utf8로 설정하는 것이 가장 좋은 방법이다.

하지만 오래전부터 운영하던 mysql 서버라면 쉽게 서버의 캐릭터셋을 변경할 수는 없을 수도 있다. 이런 경우 mysql 서버의 캐릭터셋 환경이 어떻든 간에 DB를 용도에 따라 euckr 혹은 utf8로 생성하고 각각의 db를 사용하는 웹페이지 소스에서 meta 태그를 이용해 euckr 혹은 utf8로 페이지의 캐릭터셋을 지정할 수 밖에 없다.

그리고 각 db에 접속하는 mysql_connect() 함수가 포함된 소스페이지에서 db에 접속한 세션의 캐릭터셋을 각각 euckr 혹은 utf8로 설정하여 사용할 수 있다.


위의 mysql_query('set names utf8') 함수를 실행하면 접속한 DB세션의 캐릭터셋이 utf8로 설정되고 MySql 서버의  character set client와 character set connection 환경변수보다 우선하게 되어 한글이 깨지지 않고 저장/조회된다. 만약 euckr로 설정하고자 한다면 다음과 같이 utf8 대신 euckr 을 지정하면 된다.

mysql_query('set names euckr');

물론 웹브라우저에서 한글이 깨지지 않도록 php 파일 자체의 캐릭터셋을 utf8 혹은 ansi 코드 중 하나로 저장하는 것도 중요하다. 만약 php 파일 자체의 코드를 맞추지 못하면 DB에서 조회한 데이터뿐만 아니라 HTML 내의 한글도 모두 깨지게 되므로 주의가 필요하다.

2011년 9월의 조금 흐린 어느날.....






어제부터 끙~끙~대던 협력사 엔지니어 교육 준비....
내가 하기로 했던 교육을 류과장에게 부탁했는데... 벌을 받은 듯... APM이 설치된 Solaris10 vmware 이미지가 말썽을 부리기 시작했다. 이유없이 TTY 모니터링도 동작을 안하고 이런 저런 오류도 발생하고.... 그동안 별의별 짓을 다하며 잘 부려먹었는데 드디어 탈이 난 모양이다.

그런데....

백업해둔줄 알았던 APM 설치된 Solaris10의 VMWare 이미지가  없다... -.- 이런 낭패가....
아무리 백업 디스크를 뒤져봐도 없다. APM이 설치 안된 Solaris10은 있는데 APM이 설치된 Solaris10은 없다. 설상 가상 SunFreeWare에서 패키지를 다운받아 pkgadd를 실행하는데 통... 설치가 안된다. 분명 전에도 그렇게 설치했던 것 같은데 안된다. 환장할 노릇이다... T.T

에러메시지는 다음과 같다.

WARNING: Stale lock installed for pkgadd, pkg <pkage-name> quit in initial  state. Removing lock.

이 에러가 발생하여 /var/sadm/install 디렉토리에 생성되는 . 으로 시작되는 lockfile을 지워주고 pkgadd를 해도 설치가 되지 않는다. 결국 Solaris 10 x86에서 발생하는 이 에러메시지는 운영체제의 버그로 판단된다. 그래서 Apache 소스를 다운받아 컴파일하려 했지만 그 역시도 configure가 되지 않는다. C++ 프리프로세서가 없어 에러가 난다. 에이...

그래서 www.oracle.com 에서 Solaris 10 x86을 다시 다운로드 받아 VMWare player 3.1에서 다시 이미지를 만들었다. 그리고 다음의 과정을 거쳐 APM을 설치 했다.

http://www.sunfreeware.com 에서 다음의 패키지를 다운받아 서버에 업로드 하고 gzip 명령으로 압축을 푼다.


Apache 2.0.59 와 PHP 5.2.1 그리고 MySQL 5.0.67을 제외한 나머지 패키지를 먼저 설치하는 것이 좋다. 세개를 제외한 나머지는 APM이 구동되는데 필요한 의존성을 갖는 패키지들이다.

설치 명령은 다음과 같다.

pkgadd -d ./<package-name>

즉 pkgadd -d ./zlib-1.2.5-sol10-x86-local 과 같이 명령을 수행하여 설치한다.

Apache 2.0.59 를 설치한 뒤에는 두가지를 고쳐주어야 한다.

1. /usr/local/apache2/conf의 httpd-std.conf 를 httpd.conf 로 복사한다.
2. httpd.conf 파일을 vi로 열어 "Group -1"을 찾아 "Group nobody" 로 변경해준다.

PHP 5.2.1 을 설치한 뒤에는 다음의 작업을 수행한다.

3. httpd.conf 파일을 vi로 열어 다음의 두줄을 추가한다.
    LoadModule php5_module modules/libphp5.so
    AddType application/x-httpd-php .php


아파치 구동은 /usr/local/apache2/bin/apachectl start  명령으로 수행한다.

다음은 phpinfo() 를 수행한 결과다.



   

  • 김진아 2013.09.24 04:45

    으아~~~~~~ 벌써 새벽 5시가 다되어가네요ㅜㅜ 솔라리스 이것저것 만지다가 벌써 새벽이 ㅜㅜ
    솔라리스 웹서버 구축하는거 찾다가 들어와 보니 이사님 홈페이지가 똭!!!!!!
    이것저것 둘러보고 많이많이 배우고 갑니다 ~~~~~~~~!!!! 앞으로도 자주 들릴게요 좋은정보 부탁드려요!^^

    • taeho Tae-Ho 2013.09.24 08:10 신고

      헉... 이 구석텡이 포스트까지 찾아오다닝.. ^^
      솔라리스10에 아파치와 PHP 구축???
      ㅎㅎ 도움이 됐을랑가 모르겠네...


윈도 모바일 스마트폰을 사용할 때는 어플의 개발에 별 관심이 없었습니다. 윈도 모바일 자체가 워낙 불안정한데다 윈도의 개발환경과 별반 다를 바가 없기 때문이었죠. 헌데 안드로이드 운영체제와 IOS의 등장으로 모바일 기기 운영체제가 다양해지니 왠지 개발환경을 한번 경험해보고 싶어졌습니다. 그리고 모바일기기에서 실행되는 어플의 특징을 한번 살펴봐야겠다 싶었습니다.

그래서 안드로이드 개발환경을 한번 구축해보기로 했습니다.

= 기본적으로 필요한 것은 다음과 같습니다.

  * JDK
   * 이클립스
  * 안드로이드SDK

   이클립스에 플러그인 형식으로 설치되는 안드로이드 툴킷(ADT)는 이클립스를 설치하고 이클립스
   실행 후 인터넷으로부터 설치해도 되기 때문에 따로 파일을 다운로드 받아둘 필요는 없었습니다.

= 먼저 JDK를 다음의 사이트에서 다운로드 합니다.
  http://www.oracle.com/technetwork/java/javase/downloads/index.html 



= JDK에 추가로 설치할 안드로이드 SDK를 다음사이트에서 다운로드 한다.
  http://developer.android.com/sdk/index.html
  여기에선 install 버전이 아닌 zip 파일을 다운로드 받아 수동으로 파일을 복사합니다.



= 이클립스를 다음 주소에서 다운받는다.
  http://www.eclipse.org/downloads/packages/release/galileo/sr2

이클립스는 최신버전인 3.6 (Helios)도 있지만 여기에선 안정버전인 3.5 (Galileo) 를 다운받는다.


= 다운로드 받은 세개의 파일들. 파일 이름에 붙은 순서대로 설치를 진행하면 됩니다.




= 먼저 JDK를 설치합니다.
  설치 중 묻는 질문에는 그냥 기본으로 넘어갑니다. 설치 경로도 변경하지 않고 진행합니다.

= 다음은 Android SDK를 설치합니다. Java 개발환경에서는 설치의 개념이 그저 파일의 복사이기 때문에 궂이 Install 버전을 다운받지 않아도 됩니다. 다음과 같이 C:\android-sdk-r09-windows 폴더를 만들고 압축을 해제하면 끝입니다.



= 설치된 안드로이드 SDK 설치 매니저를 실행합니다. (SDK Manager.exe)
  처음실행하면 설치할 API를 보여줍니다. 아래의 Install 버전을 누르면 인터넷을 통해 API를 다운로드
  받아 설치합니다.


  만약 일부만 설치되었다면 Available Packages 메뉴에서 추가로 설치할 수 있습니다.
  
  안드로이드 2.2 프로요에서 구동되는 어플을 개발하기위해선 Android 2.2 SDK,  API 8 관련 항목을
  필수로 설치해야 합니다.
 

= 이클립스 설치

  이클립스도 설치는 그저 파일의 압축해제와 원하는 폴더로 복사하는 것이 설치의 전부입니다.
  다운로드 받은 이클립스 압축파일을 압축해제하여 C:\Eclipse 폴더로 복사합니다.
 



= 이클립스를 설치하고 나면 이클립스 설치 폴더 안에 eclipse.exe라는 실행파일이 있습니다.
   이제 eclipse.exe를 더블클릭하여 이클립스를 실행하고 ADT라는 Android Develpoment Toolkit 을
   설치해야 합니다.

   먼저 이클립스를 실행하면 개발하게되는 소스를 저장할 워크스페이스를 지정해야합니다.
   워크스페이스를 지정하고 나면 다음과 같이 이클립스 개발환경이 실행됩니다.
 



= 이제 ADT를 설치하기 위해 "Help" 메뉴 속에 있는 "Install New Software..." 메뉴를 선택합니다.
   다음과 같이 Install 창이 실행되면 오른쪽 위의 "Add" 버튼을 누릅니다.



= "Add" 버튼을 클릭하면 "Add Site" 창이 실행됩니다. 여기에 다음의 Name과 Location을 입력합니다.

    Name : ADT
    Location : https://dl-ssl.google.com/android/eclipse/

    주소를 입력하고 "Ok" 버튼을 클릭합니다.
    잠시 후 다음과 같이 설치 가능한 안드로이드 개발 툴킷의 목록을 보여줍니다. 모두 선택한 뒤
    "Next" 버튼을 클릭하면 다운로드가 가능한지 점검하고 다음과 같이 리뷰화면이 표시됩니다.


  "Next" 버튼을 클릭하면 라이센스 동의화면이 표시됩니다. 동의하고 "Finish" 버튼을 누르면 아래 화면
  과 같이 다운로드와 설치가 자동으로 진행됩니다.
  
  중간에 인증관련 창이 표시되는 경우가 있는데 대충 OK 해주고 넘어가면 됩니다.
  
  ADT의 설치가 완료되면 자동으로 이클립스가 종료되고 재구동 됩니다.


= 안드로이드 SDK와 ADT의 연동

   이클립스에 ADT (안드로이드 개발 툴킷)을 설치하고 나면 ADT가 안드로이드 SDK를 인식할 수
   있도록 안드로이드 SDK가 설치된 폴더를 알려주어야 합니다.

   이클립스에서 "Windows" 메뉴를 선택하고 하위의 "Preferences" 메뉴를 선택합니다.
   그리고 Preferences 창이 실행되면 오른쪽 창에서 "Android"를 선택합니다.
  


SDK Location에 Android SDK를 설치한 경로를 선택한 뒤 "Apply" 버튼을 누르면 설치된 Android SDK 2.2 항목이 보이게 됩니다. "OK"를 눌러 연동을 마무리 합니다.

= 완료됨.

이제 Android 어플을 개발하기 위한 개발환경은 모두 만들어졌습니다.
추가로 에뮬레이터를 생성하여 코딩한 어플을 실행해보는 환경도 만들 수 있습니다만....
에뮬레이터의 속도는 정말 느려서 에뮬레이터를 이용해 어플을 개발하는 것은 추천하지 않습니다.
안드로이드가 탑재된 스마트폰을 USB로 직접연결하여 코딩 중간중간 실행시켜보는 것이 훨씬 편하고 확실한 개발방법입니다.

시간이 되면 스마트폰을 USB 인터페이스를 이용하여 연동하고 코딩된 어플을 스마트폰에서 실행하는 방법에 대해서도 포스트를 올려보겠습니다.
 



  • 이상한 사람중 하나 2011.05.30 22:08

    ㅠㅠㅠ전 설치하는데만 1주일은 걸릴것 같네요.......
    전화선도 아닌데 다운속도가 왜이렇게 느린지ㅠㅠ

    • 주인장 2011.05.30 22:44

      아...그런경우도 있군요...
      전 그렇게 느리진 않던데...

  • 2011.06.06 17:59

    비밀댓글입니다

  • 영훈 2011.06.10 16:46

    환경변수 설정에 대해서는 설명이 없네요?

    • 주인장 2011.06.12 21:56

      음...java 환경변수 말씀이신가요?
      그 변수는 원래 자동으로 PATH와 JAVA_HOME이 설정되죠. 궂이 설정해주지 않아도 됩니다. java 경로나 class를 못찾으면 설정해주면 되죠.


취미삼아 PHP를 이용해 웹으로 이것 저것 코딩하며 노는 나로서는 HTML이나 CSS, PHP 함수에 대해 많은것을 항상 외우고 있지를 못하다. 코딩을 할 때마다 똑같은 키워드를 매일 인터넷을 뒤져가며 하다보니 코딩 속도도 더디고 힘도 많이 든다.

그러다 발견한 나모코드에디터.... 바로 내가 찾던 에디터다. 직접 만들 실력은 안되니 실력자들이 만들어 놓은 것을 주로 활용하는 내게 나모코드에디터는 사막을 헤매다 오아시스를 만난 듯한 느낌을 주었다. (물론 조금 아쉬운 부분들도 있지만..)

그런데...

UTF-8로 저장하고 서버에 업로드한 뒤 브라우저에서 호출하면 이런 에러가 찍힌다.. 아무리 해도 이유를 알아내지 못하다가 얼마전에야 그 원인을 알았다.
(관련포스트 : http://cybercafe.tistory.com/178 )



그런데 문제는 나모코드에디터의 파일저장 화면에 "UTF-8 BOM 없음" 과 같이 파일헤더부분에 BOM(Byte Order Mark)를 기록하지 않는 저장옵션을 찾지 못했다. 그래서 결국 나모코드에디터를 사용하지 못할 처지에 놓이게 되었다.

하늘이 무너져도 솟아날 구멍은 있는 법...

나모코드에디터의 도움말부터 모든 메뉴의 설정 화면을 뒤졌다. 그리고 결국 찾아낸 옵션....


"도구 - 프로그램 설정" 메뉴에서 찾아낸 "BOM이 없는 UTF-8 파일 지원" 이라는 체크옵션이 있었다. 그런데 문제는 이 옵션을 체크(V)하고 저장한 뒤 웹서버에 업로드하고 호출해도 같은 오류가 발생한다는 것이다.

혹시나 버그(?)일까 싶어 체크를 해제하고 저장해보니.... 빙고..!!!

옵션이 내가 생각했던 것과 반대였다. 옵션을 체크하면 BOM 없이 저장되어야 할 것 같은데 BOM을 포함하여 저장이 하는 것 같다. 그리고 체크를 해제하면 BOM이 저장되지 않는다. 코드에디터 개발자가 잠시 착각하고 if 문을 잘못 코딩하였거나 뭔가 다른 의미로 생각하고 코딩한 것 같다.

어쨌든... 이 옵션을 만들어준 나모코드에디터 개발자에게 감사드린다... 흑흑~~~~






  • oseb 2011.02.23 11:27 신고

    그렇네요. 좀 애매한 표현이네요 어떻게 했을까요?

    if (인코딩=utf8) then
    if (BOM 없는 지원)
    // 음... 없다는 표시니깐 BOM 넣지말자
    else
    // 이건 토글이니 위꺼랑 반대로
    end

    아니면 아래처럼 간략화로 했을까요?
    if (인코딩=utf8)
    BOM 체크값!=(BOM옵션체크박스값)

  • 주인장 2011.02.23 22:18

    ㅎㅎ 네..그렇겠죠~~ ^^


PHP는 날짜 계산을 위한 함수를 다양하게 제공한다.
그중에서도 오늘날자를 원하는 포맷으로 구하는 방법... 그리고 몇일 전을 구하는 방법... 그리고 오늘을 기준으로 이번주의 월요일을 구하는 방법을 소개한다.

<?
    //오늘 날짜 구하기
    //$today = date("Y-m-d", mktime(0,0,0,date("m"),date("d"), date("Y")));
    //$today = "2011-01-10";
    //$timetoday = strtotime($today);
   
    // 1일전 날짜 구하기
    //$beforeDay = date("Y-m-d", strtotime($today . " -1 day"));
    //echo $beforeDay . "<br>";
   
    // 이번주 월요일 구하기
    // $beforeMonDay = date("Y-m-d", strtotime("last Monday")); 
    //echo $beforeMonDay . "<br>";
?>

     - 아래 이미지의 월요일구하기는 오류발생함 - ^^




PHP의 session 변수를 이용해 사용자 로그인 여부를 검사하는 코딩을 할 때 이따금씩 특정 웹페이지에서 "session_start() [function.session-start]: Cannot send session cache limiter - headers already sent ~~~" 라는 오류를 보게 된다.

처음엔 도대체 이게 무슨 원인으로 발생하는 것인지 몰라 헤매곤 했다.그리고 오늘.. 또 뭔가 새로운 기능을 구현하다가 이 에러를 맞닥뜨렸다.

PHP와 MySql이 각각 euc-kr로 설정된 상태에서 php 소스파일을 UTF-8로 저장하게 되면 바로 이 에러가 발생한다. 당연히 php는 4.x 버전, MySql도 4.x 버전이다. 하지만 반대로 PHP와 MySql이 모두 UTF-8이 지원되는 경우에도 동일하게 발생하는 것 같다. 즉.. APM의 버전과는 별 관계가 없다는 것이다.


이 에러는 많은 PHP 초심자들을 힘들게 하는 것 같다. 수많은 개발자들이 질문을 하고 답변을 하는데... 대부분은 session_start(); 함수 앞에 그 어떤 코드도 포함되어 있으면 안된다는 답변이 가장 많다. (당연히 include(), require()의 앞이다.) 이것도 정답이다. 하지만 가장 앞에 포함되어 있는데도 발생한다면..???

여기서부터 참 막막해진다. session_start();앞에 @를 붙여 @session_start(); 와 같이 사용하면 된다고 하기도 하는데 이렇게 하면 속도가 느려진다는 무시할 수 없는 답변이 또 보인다.

결국 Goole을 뒤질 수 밖에 없었다. 그리고 찾아낸 원인은 APM의 Apache와 PHP의 버전 그리고 php 소스 파일이 저장될 때의 문자셋 때문에 발생한다는 것이다.

그 이유는 바로 아래화면 처럼 PHP 파일의 소스를 저장할 때 파일포맷을 무엇으로 하느냐에 따라 각각 파일 헤더의 내용이 다르고 그 헤더의 차이로 인해 Apache가 session_start() 함수의 앞부분에 무엇이 있는가 없는가를 판단할 때 오류의 원인을 제공하게 되기 때문이다. 특히 UTF-8 포맷으로 저장할 때 BOM 없음 옵션을 선택하고 저장해야한다는..정말로 어이없는 정답이었다.

  울트라에딧에서 확인한 UTF-8 (BOM 아님) 저장옵션

PHP 버전이 낮은 경우에, 즉 PHP와 MySql이 모두 euc-kr인 경우는 ANSI 포맷으로 저장하면 session_start() 에러가 사라졌고 PHP5, Mysql이 모두 UTF-8인 경우에는 UTF-8 BOM 아님 옵션으로 지정하여 저장해야 session_start() 오류가 사라졌다.

이 문제로 골치아픈 초보 PHP 개발자들에게 도움이 되면 좋겠다.

영원한 초보인 난... 하루를 꼬박 헤맸다.. ^^



  • qewr 2011.07.17 14:44

    최근 php를 시작하게 되었는데
    좋은 정보 잘 얻고 갑니다.

    • 주인장 2011.07.17 22:26

      졸필에 댓글까지 남겨주시니 감사하네요~ ^^

  • musicbar 2011.07.25 17:26

    세션 관련 글을 검색하다가 들르게 되었습니다.
    세션을 사용할때도 캐릭터셋을 맞춰줘야 하는군요.
    좋은 글 잘 읽었고, 많은 도움이 되었습니다.

    • 주인장 2011.07.25 22:07

      댓글 감사합니다~

  • sanarea 2012.03.05 01:45

    감사합니다^^ session 오류나서 찾다보니 최고의 답변이네요 ㅎㅎ

  • 2012.03.12 10:52

    비밀댓글입니다

  • 초보 2013.05.28 14:12

    php가 동작하기는해도 에러땜에 신경쓰였는데 한번에 다 해결됬네요
    넘넘 감사합니다~^^

  • 지니가다 2013.06.04 13:15

    와.. 정말 감사합니다. 파일포맷 문제.. 파일의 고유 헤더 문제가 있을 수 있다는건 몰랐네요. 좋은 글 감사합니다. 다른 어디서 개발을 하더라도 파일 고유의 헤더를 염두에 둘 수 있겠네요. ^^ 건승하세요!!

  • rarity 2014.05.09 10:14 신고

    멋져요

    • taeho Tae-Ho 2014.05.09 13:36 신고

      프로그래머로 대성하시길 바랍니다.. ^^

  • 2015.12.14 15:38

    비밀댓글입니다

    • taeho Tae-Ho 2015.12.14 22:56 신고

      그 블로그는 제 블로그는 아니구요.. (네이버블로그는 폐쇄했습니다. ^^)
      제 글을 그대로 퍼간분이 계시다는 건 알고 있습니다. 똑같이요.. ^^
      살펴봐 주셔서 감사합니다.



최근에 미니 PC를 한대 구입했다. 회사에서 이것 저것 잡다한 테스트와 파일저장소로 사용하기 위해서다.
이것 저것 따지다.. 궂이 강력한 퍼포먼스가 필요한 것이 아니어서.. 전력소모 적고 발열이 적은 아톰CPU를 가진놈으로 샀다. 다만 그래도~ 서버로 쓸거라서 아톰 듀얼인 D510이 들어간 놈으로 주문했다.

CPU : Atom D510 1.66GHz
RAM : 2 GByte
HDD : 1.5 T

그리고 거기에 Windows 7을 설치하고 체험지수를 봤다. 아...1.0.... 그런데.. 그래픽성능이 1.0이었다. ㅋㅋ
그나마 다행... 뭐.여기서 게임할건 아니니까.. 상관없다. ㅋㅋㅋ
의외로 프로세서나 메모리는 그런대로 쓸만했다.



이제 테스트용으로 쓸 웹서버와 게시판소스를 골랐다. 별 고민없이 그냥 APMSetup7과 제로보드XE로 낙찰봤다. 그런데 사실 제로보드XE는 처음써본다. 제로보드4는 써봤지만 XE는 크게 변경되었다는 글만 봐온터라..쫌 헷갈렸다.
그래서 제로보드5 즉, XpressEngine 설치에 대해 정리해봤다.

1. 다운로드

   제로보드 XE(xpress Engine)은 이곳에 가면 다운받을 수 있다. 그중에서 제일먽 XE Core를 다운받아 설치해야했다.
    http://www.xpressengine.com/download

   다운받으면 아래와 같이 xe.1.4.0.10.zip 파일이 보인다.


zip 파일의 압축을 풀고 다음과 같이 제로보드를 설치할 디렉토리로 복사한다. 난 D:\bbs 로 했다.



2. 아파치에 가상디렉토리 등록

위와 같이 제로보드XE를 APM의 기본 Document Root가 아닌 D:\bbs 와 같이 다른곳에 설치하기 위해선 아파치의 httpd.conf 파일에 가상디렉토리(Virtual Directory) 설정을 해주어야 한다. httpd-aliases.conf 파일에 하면 왠지 적용이 안됐다.



그래서 그냥 httpd.conf 파일에 직접 해줬다.

노트패드로 httpd.conf 파일을 찾아 열고...


위와 같이 D:\bbs 를 /bbs 로 인식하도록 가상디렉토리 설정을 추가한다. 당연히 APM을 재구동해주어야 한다.

3. xpress Engine 설치진행

웹브라우저를 통해 알리아스가 설정된 곳 http://IPADDRESS/bbs 를 호출하면 바로 다음과 같이 설치 조건 점검화면으로 넘어가면서 설치가 진행된다.


모든 조건이 "가능"이어야 한다. APM Setup7은 당연히 모든 조건을 충족한다.

언어는 아래와 같이 "한국어"를 선택한다.



데이터베이스는 원하는 DB를 설치하면 된다. 난 당연히 APM에 포함된 mysql을 선택했다. 


이 화면은 내가 선택한 DB인 mysql 접속정보와 제로보드XE의 관리자 정보를 입력한다.


- DB 호스트네임 : 만약 아파치와 DB가 다른 머신에 분리되어 있다면 모를까... 하나의 머신에서 같이 실행된다면 그냥 localhost 를 입력하면 된다.
- DB Port : 변경하지 않았다면 기본값.. 3306 을 그대로 둔다.
- DB 아이디 : 아래의 DB 데이터베이스에 접근권한을 갖는 DB의 사용자 계정을 입력한다.
- DB 데이터베이스 : 제로보드XE를 설치하기 전에 mysql에 DB를 만들어두어야 한다. 여기서는 zero 라는 DB 미리 만들어 둔 것이다.
- 테이블 머리말 : 제로보드XE가 구동되는데 필요하 테이블들을 생성할 때 이름규칙(머릿말)
- 관리자 정보는 그냥 새로 만들어주는 것이다. 제로보드XE의 관리기능을 사용할 관리자 계정.


설치중인화면...


설치 완료 화면..


4. 제로보드XE 엔진설치 후...

제로보드XE가 버전4와 가장 달라진 점이 있다면.. 코어의 설계와 게시판의 모듈이 완전하게(?) 분리되었다는 것이다. 앞에서 설치한 것은 제로보드XE의 엔진이다. 엔진 주변부의 UI와 UI관련 기능들을 수행하는 게시판 모듈은 별도로 설치하여야 한다.

게시판과 방명록, 앨범 등 모듈은 제로보드XE의 관리자 화면에서 클릭~클릭~ 만으로 설치할 수 있다. (초보라면 조금 까다롭지만..)

관리자 화면은 다음과 같이 웹브라우저에 주소를 입력하면 접속할 수 있다.

https://IPADDRESS/bbs/?module=admin


실제 게시판 모듈의 설치와 접속은 다음에...

이만 총총...

(점심먹으러 가야쥐~~~)


  • anonymous 2010.09.10 21:48

    죄송하지만, zb5와 xe는 엄연히 다릅니다. xe는 zb라는 틀 자체에서 벗어난거죠. zb4 -> zb5 -> zbxe - > xe 순서인데 zb5는 zb4에서 전혀 새로워졌고, zbxe는 zb를 거의 완전히 뜯어고친 것이며 xe는 zbxe에서 더 나아가 완전히 새로워진 것입니다.

    • 주인장 2010.09.10 22:08

      그런가요? 오랫만에 제로보드를 보니 헷갈린 모양입니다. 그리고 죄송할것 까지는 없죠~~ ^^


디스크를 증설하거나 다른 디스크로 데이터베이스를 이동해야하는 경우가 있다. 이런 필요성이 있는 경우는 대부분 데이터베이스에 데이터가 무척 빠른 속도로 증가하여 디스크의 공간이 부족한 경우가 대부분이다.
때문에 Export / Import 하기도 부담스럽고 또 귀찮기도 하다. 만약 중간에 에러가 나면... 큰일이기도 하고...

그렇기 때문에 데이터베이스의 물리적인 데이터파일을 이동시키는 것이 어찌보면 가장 빠르고 편한 방법이다.
이때는 다음과 같이 데이터베이스를  떼어내고 파일을 복사한 뒤 다시 붙이는 방법으로 진행하면 된다.


SQL엔터프라이브 매니저에서 새쿼리 창을 열고
(그 전에 데이터베이스를 사용하는 다른 서비스들을 종료한다.)

1. sp_detach_db 으로 데이터베이스를 분리시킨다.

    USE master
    EXEC sp_detach_db '데이터베이스이름', 'true'

    SQL엔터프라이즈매니저에서 해당 데이터베이스가 사라진다.
    하지만 실제로 데이터베이스 파일은 그대로 남아 있다.

2. C 드라이브에 있는 데이터베이스 파일을 D:\DATA\ 와 같이 원하는 곳으로
    이동한다. (복사 혹은 CUT/PASTE)

3. sp_attach_db 를 이용하여 D드라이브(D:\DATA\)에 데이터베이스를 붙여준다.
    만약 데이터베이스 명칭이 변경되면 데이터베이스를 사용하는 서비스들의 DB설정을
    다시해주어야 하므로 변경하지 않는 것이 편하다.

    EXEC sp_attach_db @dbname = N'데이터베이스이름',
    @filename1 = N'D:\DATA\데이터베이스파일이름.mdf',
    @filename2 = N'D:\DATA\로그파일이름.ldf'

4. DB를 사용하는 서비스를 재구동 한다.


SQL서버의 데이터베이스를 주기적으로 백업하기 위해서는 다음과 같은 설정을 통해 수행할 수 있다.

먼저 다음 화면과 같이 Management Studio를 실행하고 SQL 서버 에이전트에 "작업"을 등록한다.

사용자 삽입 이미지


위의 작업을 등록할 때 이름은 어떤 백업 작업인지 알기 쉽도록 주면된다.

작업을 등록하게 되면 두번째 항목에 "단계"라는 것이 인다. 이 단계에는 모두 2개가 등록된다.

DB를 백업하는 T-SQL 수행단계와 백업된 DB 파일을 FTP로 다른 서버로 전송하는 운영체제의 CmdExec 수행단계이다.

사용자 삽입 이미지

먼저 DB 백업 단계는 다음과 같이 Backup이라는 T-SQL이 등록되어야 한다.

사용자 삽입 이미지

이 스크립트는 ATCDB라는 데이터베이스를 "ATCDB-200807009.BAK"와 같이 데이터베이스명과 날짜를 포함하는파일명으로 백업하는 TSQL이다.

그리고나서 "고급"탭으로 이동하여 작업완료(성공)시 "다음 "단계로 이동"을 선택해주어야 한다. 그렇지 않으면 다음의 단계를 수행하지 않고 종료하게 된다.

다음은 백업된 파일을 다른 서버로 FTP를 이용하여 전송하는 단계이다. 다음과 같이 단계를 등록한다.

사용자 삽입 이미지

upload.cmd 라는 파일은 다음과 같은 내용이 포함되어 있는 도스 명령어 파일이다.

***** upload.cmd *****

for /F "tokens=1" %%a in ('date /t') do set date_today=%%a

set yy=%date_today:~0,4%
set mm=%date_today:~5,2%
set dd=%date_today:~8,2%

SET FILENAME=ATCDB-%yy%%mm%%dd%.BAK
d:
cd D:\ATC_BACKUP
ren %FILENAME% NOW_BACKUP.BAK
del ATCDB*.BAK
ren NOW_BACKUP.BAK %FILENAME%

echo open {서버IP} > D:\ATC_BACKUP\upload.txt
echo user {서버계정} >> D:\ATC_BACKUP\upload.txt
echo {계정패스워드} >> D:\ATC_BACKUP\upload.txt
echo bin >> D:\ATC_BACKUP\upload.txt
echo prompt off >> D:\ATC_BACKUP\upload.txt
echo lcd  D:\ATC_BACKUP  >> D:\ATC_BACKUP\upload.txt
echo cd {이동할서버경로} >> D:\ATC_BACKUP\upload.txt
echo mdel {이전의백업본삭제명령} >> D:\ATC_BACKUP\upload.txt
echo put %FILENAME%  >> D:\ATC_BACKUP\upload.txt
echo quit >> D:\ATC_BACKUP\upload.txt
c:\windows\system32\ftp -v -n -s:D:\ATC_BACKUP\upload.txt

del D:\ATC_BACKUP\upload.txt

두단계의 작업을 모두 등록하였으면 다음과 같이 일주일에 한번 수행되도록 일정을 등록하여 주면 백업 스케줄링은 완료된다.

사용자 삽입 이미지


 

  • 준나인 2008.09.17 11:12

    DB백업하는 T-SQL 부분좀 자세히 설명좀 해주세요~


아파치2.x/PHP5.x 에서 파일다운로드 시 한글이름의 파일이 다운로드 안될 때는 아파치 웹서버의 httpd.conf 파일에 한글 URL의 인코딩이 가능하도록 하는 다음의 내용이 포함되어 있는지 확인한다.

LoadModule redurl_module      modules/mod_url.so

<IfModule mod_url.c>
        CheckURL On
</IfModule>

만약 위의 내용이 포함되어 있지 않다면 서버와 브라우저가 실행되는 PC의 캐릭터셋이 호환되지 않을경우 이름이 영문으로 되어 있지 않는 더블바이트(한글, 일본어 등등)로 이름이 되어 있는 파일은 파일을 찾을 수 없다는 메시지와 함께 다운로드가 되지 않는다.

해결방법은 다음과 같다.

1. 다음의 URL에서 mod_url.c 소스를 다운로드 받는다.

사용자 삽입 이미지


나는 1.20을 다운로드 받았다. 사실 어디서든 소스만 구하면 된다.

2. 서버의 아파치 include 디렉토리에 업로드 한다.

   나의 경우 /usr/local/apache2/include 였다.

3. 소스를 업로드한 디렉토리로 이동하여 다음의 명령으로 컴파일한다.

    gcc -fpic -DSAHRED_MODULE -DEAPI -c mod_url.c

4. 오브젝트 파일을 Shared Object로 변환한다.

    gcc -shared -o mod_url.so mod_url.o

5. 아파치의 modules 디렉토리로 복사한다.

    나의 경우 /usr/local/apache2/modules 였다.

6. httpd.conf 파일의 적당한 위치에 다음의 라인을 추가한다.

   LoadModule redurl_module      modules/mod_url.so

   <IfModule mod_url.c>
            CheckURL On
    </IfModule>

7. 아파치를 재기동한다.



갑자기 운영하던 웹사이트(RedHat Linux, Apache, PHP, MYSQL)에 접근이 안되는 장애가 생겼다.

root 계정으로 로그인하여 확인하니 httpd 대몬이 평소보다 훨씬 많은 숫자가 실행중이었고 mysql 대몬은 정상적으로 실행중인 것 처럼 보였다.

급하게 apache와 mysql을 재구동 하려 하였으나 mysql의 종류(mysql.server stop)가 안되었고 강제로 kill한 뒤 mysql을 구동하려 하였으나 평소와는 달리 프로세스는 한참만에 떴으나 mysql 클라이언트 및 apache를 통한 db 접근이 안되었다.

mysql 로그를 확인하니 Filesystem의 full로 인해 오류가 발생하였음을 확인할 수 있었다.

먼저 mysql db가 위치한 파일시스템의 불필요한 파일... (나의 경우 tomcat의 mod_jk.log(??) 파일이10G이상으로 커져있었다...)을 지우고 ....

mysql과 apache를 재구동하였다.

웹도 정상적으로 접근하였으나 특정 테이블을 접근하는 php 소스 부분에서 mysql_fetch()의 오류가 발생하였다.

mysql 클라이언트로 접근하여 

mysql> repair table 테이블명;

을 수행하여 복구하였다.

그 전에

mysql>analyze table 테이블명;

을 수행하였더니 테이블이 Crach되어 있다는 분석보고가 나왔다.



.. 리눅스에 apache...mysql...php를 우여곡절끝에 설치하고 phpMyAdmin을 설치한다..
MYSQL은 5.0 버전이다.

VMWARE에 설치된 RedHat Enterprise 4 update 4 (i386)에서는 별 문제없이 최신버전의 A.P.M을 설치했지만 이상하게도 회사의 Intel X86 서버에서는 libphp5.so가 생성되지 않는다...

결국 apache 5.0의 안정버전과 mysql 5.2.. 그리고 php 4.4.4를 설치했다. 이 조합에서는 잘 된다... -.-

하지만 phpMyAdmin 최신버전을 설치하여 로그인하려는데...

#1251 - Client does not support authentication protocol requested by server; consider upgrading MySQL client

요런 에러가 난다...

찾아보니...

mysql> set password for
    -> root@localhost = OLD_PASSWORD('비밀번호');

Query OK, 0 rows affected (0.02 sec)

mysql> flush privileges;

Query OK, 0 rows affected (0.00 sec)

요렇게 해줘야...로그인이 되더라는 말씀... mysql5와 mysql4 버전의 패스워드 암복호화 방식의 변경으로 인한 문제인것 같다.

넘 힘들다..증말...



금일 (2007년 1월25일) 기준 최신버전의 MYSQL인 5.0.33 설치 중 다음과 같은 에러가 발생한다.
네이버...구글 등 한글 검색사이트 검색 결과 관련 정보가 하나도 -.- 없었다.

./configure -- .....

sql_class.cc: In constructor 'THD::THD()':
sql_class.cc:265: error: 'query_cache_init_query' was not declared in this
scope
make[5]: *** [sql_class.o] Error 1

이 에러는 configure 옵션 중

./configure --without-query-cache 

위의 옵션을 줄 경우 발생한다.

--- 해결방법---

소스디렉토리 아래의 sql 디렉토리에 sql_class.cc 파일을 열고 다음과 같이 두줄을 추가해 준 뒤 다시 configure와 make, make install을 실행한다.

   client_capabilities= 0;                       // minimalistic client
   net.last_error[0]=0;                          // If error on boot
   #ifdef HAVE_QUERY_CACHE       <--- 추가....
   query_cache_init_query(&net);                 // If error on boot
   #endif                                       <--- 추가....
   ull=0;
   system_thread= NON_SYSTEM_THREAD;
   cleanup_done= abort_on_warning= no_warnings_for_error= 0;



mysql 5.0 이상버전의 소스로 컴파일하여 설치할 때에는 client library를 별도로 한번 더 컴파일해주어야 했다.

mysql 설치 후

./configure \
--enable-thread-safe-client \
--with-charset=euckr \
--without-server \
--without-query-cache \
--without-docs \
--without-man \
--without-bench \
--without-readline \
--without-libedit
make && make install


위와 같이 prefix 를 지정하지 않고 MySQL 클라이언트만을 설치할 경우에는 /usr/local/lib/mysql 디렉토리에 library들이 설치된다.

그리고 /usr/local/bin/ 디렉토리에 실행스크립트를 비롯한 MySQL 관련 파일들이 자리잡게 된다.



MySQL을 설치할 때는 Daemon 들이 root 소유자로 실행되지 않도록 하는 것이 좋다. 보안상 MySQL의 취약성이 발결되어 공격을 당하게 되면 곧바로 root shell을 획득하는 것이 가능하기 때문이다. 따라서 MySQL을 mysql과 같이 일반 계정으로 실행되도록 설치하라.

그리고 부팅 시 자동으로 실행되도록 하기 위해서는 다음과 같은 작업 절차를 거친다.

사용자 삽입 이미지

1. 설치된 디렉토리 (여기서는 /app/mysql5 로 가정한다.) 아래의 support-files 디렉토리로  이동하고...

2. mysql.server 라는 파일을 /etc/init.d 로 적당한 이름을 주어 복사한다.   (여기서는 mysql5022 로 복사했다.)

3. chkconfig --add mysql5022 명령을 실행하여 서비스로 등록한다.

4. chkconfig --level 2345 mysql5022 on 명령을 실행하여 mysql을 runlevel 2,3,4,5에서 실행하도록 설정한다.

5. 서버를 리부팅하여 정상적으로 서비스가 기동되는지 확인한다.



1. mysql 을 다음과 같이 --skip_grant 옵션으로 실행한다.

     mysqld_safe --skip_grant &

    패스워드 없이 접근이 가능합니다.

2.  mysql 만 치고 접속합니다.

3. connect mysql;    (root의 패스워드 수정할 때)

4. update user set password=password('new-password') where user='root';

5. flush privileges;

root 패스워드를 잊어 버렸을 경우 root 패스워드 재설정해 주는 과정임