"만들면서 배우는 CodeIgniter" (변종원 지음 / 한빛미디어)를 읽고, 도움이 될만한 활용 팁을 정리해 나간다. 인터넷에서 찾은 정보를 함께 정리한다.



개요


>> "PHP 창시자인 라스무스(Rasmus)는 '프레임워크는 쓰지 말라"고 말했다. 

프레임워크를 사용하면 순수한 PHP보다 성능이 떨어지기 때문인데, 그래도 쓰려면 CodeIgniter를 사용하라는 내용으로 라스무스가 DrupalCon 2008에서 "Simple is Hard"라는 내용으로 발표하였다. 여타의 프레임워크와는 달리, 응답속도와 초당 트랜잭션이 현저하게 높은 것을 확인할 수 있다.


>> 다른 프레임워크는 테이블을 기반으로 모델, 컨트롤러, 뷰에 해당하는 코드를 자동으로 생성하는 방식을 택하며, 하나의 기능을 구현하기 위해서는 테이블/모델/컨트롤러/뷰를 모두 만들어야 하는 제약사항이 있는 경우가 많다. 반면 CodeIgniter는 각 레이어 사이의 결합이 느슨하게 유지되므로, 컨트롤러/뷰만 만들어도 기능이 동작하는 방식을 취했다.


>> Clean URL(간편 URL) 포맷을 지향한다. 또는 RESTful URL, SEO(Search Engine Optimization) 친화적 URL을 지향한다.



CodeIgniter 개발환경 구성하기


캐릭터셋>> CodeIgniter의 모든 파일은 UTF-8을 사용한다. euc-kr을 사용하는 경우 한글이 깨진다.


라이브러리>> output 라이브러리는 자동으로 로드된다. 예를 들어 {elased_time}은 현재 페이지의 실행시간을, {memory_usage}는 페이지의 메모리 사용량을 표시한다.



서버 설정하기


>> CodeIgniter에서 index.php 파일이 Front Controller의 역할을 담당한다. 따라서 URL 호출시 아래와 같이 index.php가 위치해야 한다. 

http://localhost/todo/index.php/main/lists


만약 아래와 같이 URL을 사용하고자 한다면,

http://localhost/todo/main/lists


아파치 서버 설정에서 rewrite_module을 로드하고, AllowOverride All로 설정한다. 그리고 CodeIgniter의 설정 파일인 config/config.php 파일에서 index_page 설정 값을 공백으로 바꾼다.

/*

|--------------------------------------------------------------------------

| Index File

|--------------------------------------------------------------------------

|

| Typically this will be your index.php file, unless you've renamed it to

| something else. If you are using mod_rewrite to remove the page set this

| variable so that it is blank.

|

*/

$config['index_page'] = '';


그리고 프로젝트 루트 디렉토리에 .htaccess 파일을 만든 후 아래와 같이 작성한다.

<IfModule mod_rewrite.c>

    RewriteEngine On


    RewriteBase /


    RewriteCond $1 !^(index\.php|images|captcha|include)

    RewriteCond %{REQUEST_FILENAME} !-f

    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteRule ^(.*)$ /~socurites/todo/index.php/$1 [L]

</IfModule>





DB 설정하기


DB>> application/config/database.php 파일에서 DB 정보를 설정할 때, pconnect의 값을 FALSE로 설정한다. pconnect 는 다음과 같다.

pconnect - TRUE/FALSE (boolean) - 영속적연결(persistent connection)을 사용할것인지 말것인지 결정합니다.


영속적 연결이라는 말의 의미가 모호한데, Advantages / Disadvantages of pconnect option in CodeIgniter에서 자세히 설명한다. 번역해보았다.

"영속적 연결과 관련해서 BP(Best Practice)를 몇가지 살펴본 후, 아래와 같은 결론을 얻었다.

가능하면, 영속적 연결을 사용하지 말라.

아래와 같은 환경이라면 영속적 연결을 사용하라.

  • 전용 운영 웹서버와 전용 데이터베이스 서버 장비가 있는 경우
  • 웹서버와 데이터베이스를 효과적으로 튜닝한 경우
  • 운영환경과 동일한 테스트 환경이 있는 경우
  • 데이터베이스 접속시 걸리는 시간으로 인해 성능이 저하되는 경우

영속적 연결을 사용하면 아래와 같은 문제가 생길 수 있다.

  • DB 커넥션이 의도한 바와는 다르게 닫하지 않는 버그가 생길 수 있다.
  • DB 커넥션 개수가 한계치를 넘을 수 있다.
  • 많은 수의 유휴 커넥션션으로 인해 많은 메모리가 사용되므로, DB 성능이 저하될 수 있다.
  • 커넥션의 상태가 너무 오랫동안 지속되는(stale) 버그가 생기며, 어플리케이션에서는 이러한 상태를 인식하지 못할 수 있다.
반면 아래와 같은 장점도 있다.
  • 초기 커넥션을 얻을 때 걸리는 시간(latency)이 줄어든다.
정말로 커넥션 latency가 문제를 일으키는 상황이라면, pconnect를 TRUE로 설정한 후 테스트 환경에서 성능을 테스트해본 후 그에 따른 결과를 측정해야 한다."


보안

보안>> php.ini 파일에서 cgi.fix_pathinfo 값을 0으로 바꿔야 한다. 만약 기본값인 1을 그대로 두면, http://localhost/bad.hack/aa.php와 같이 비정상적인 접근을 할 수 있다.

; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI.  PHP's

; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok

; what PATH_INFO is.  For more information on PATH_INFO, see the cgi specs.  Setting

; this to 1 will cause PHP CGI to fix its paths to conform to the spec.  A setting

; of zero causes PHP to behave as before.  Default is 1.  You should fix your scripts

; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.

; http://php.net/cgi.fix-pathinfo

cgi.fix_pathinfo=0


>> 컨트롤러에 index() 메서드를 선언하면, http://localhost/[컨트롤러]까지만 주소를 입력해도, http://localhost/[컨트롤러]/index로 라우팅 된다. 에러 방지를 위해서라도 index() 메서드는 항상 만드는 게 좋다.


>> 보안 코딩

보안을 고려해서 코드를 작성하려면, 보안과 관련된 함수를 일일이 작성해야 하며, SQL 인젝션 공격을 막기 위해서는 파라미터를 이스케이프 처리해야 하는 등 신경쓰야 할일이 많다. CodeIgniter를 사용하면, XSS 스크립트 공격과 SQL 인젝션 공격에 대응하는 코드를 쉽게 작성할 수 있다. 


>>  SQL 인젝션 막기

SQL 인젝션을 막는 방법에는 3가지가 있다.

1. Model 레이어 - $this->db->escape_str() 함수 사용하기

아래의 예제를 참고한다.

$sql = "SELECT * FROM user WHERE id = '".$this->db->escape_str($id)."' AND password = '".$this->db->escape_str($password)."'";


2. 모델 레이어 - SQL 바인딩 사용하기

아래의 예제를 참고한다.

$sql = "SELECT * FROM user WHERE id =  ? AND password = ?";

$this->db->query($sql, array($id, $password));


3. 컨트롤러 레이어 - $this->input->post() 함수 사용하기

아래와 같이 컨트롤러에서, 파라미터를 필터링한 후 변수에 할당한다. 이후의 모델 레이어에서는 필터링된 값을 가져다 쓰도록 한다.

$id = $this->input->post('id', TRUE);


>>  XSS 막기

SQL 인젝션을 막는 방법에는 개별 필터링, 전역 필터링 2가지가 있다.


1. 개별 필터링

컨트롤러 레이어에서 $this->input->post() 함수를 사용한다.


2. 전역 필터링

config.php 파일에 아래와 같이 설정하여, 모든 POST/GET 입력값에 대해 TRUE가 자동으로 설정되도록 한다.

/*

|--------------------------------------------------------------------------

| Global XSS Filtering

|--------------------------------------------------------------------------

|

| Determines whether the XSS filter is always active when GET, POST or

| COOKIE data is encountered

|

*/

$config['global_xss_filtering'] = TRUE;


전역 설정을 할 경우, textarea에 <span id="test">와 같은 내용이 있는 경우, 자동으로 <spa>으로 치환해버린다. 만약 위지위그 에디터를 사용하는 사이트라면, 전역 필터리응 사용해서는 안된다.


>>  CSRF 막기

CSRF 공격을 막기 위해서는 먼저 config.php 파일에서 csrf_protection 값을 TRUE로 바꿔야 한다.

/*

|--------------------------------------------------------------------------

| Cross Site Request Forgery

|--------------------------------------------------------------------------

| Enables a CSRF cookie token to be set. When set to TRUE, token will be

| checked on a submitted form. If you are accepting user data, it is strongly

| recommended CSRF protection be enabled.

|

| 'csrf_token_name' = The token name

| 'csrf_cookie_name' = The cookie name

| 'csrf_expire' = The number in seconds the token should expire.

*/

$config['csrf_protection'] = TRUE;

$config['csrf_token_name'] = 'csrf_test_name';

$config['csrf_cookie_name'] = 'csrf_cookie_name';

$config['csrf_expire'] = 7200;


그리고 뷰 레이어에서는 <form> 태그를 사용하는 대신, form helper 함수인 form_open() 함수를 사용해야 한다. 

* form_open() 함수를 사용하는 방식은 조금 성가신데...




[참고자료]


저작자 표시
신고
Posted by socurites
TAG php

CodeIgniter 프레임워크를 학습한 이력은 다음과 같다.


PoC 결과는 대체적으로 만족스럽다.


MVC 프레임워크이면서도 굉장히 가볍다. 그리고 설치랄 것도 없이 압축만 풀면 그만이다. 별도의 설정이 많이 필요하지도 않다. 가장 큰 이슈였던 스마티와의 연동도 크게 어렵지 않았다. 또한 View와 Controller 사이의 결합도도 거의 없다. 또한 문서화도 상당히 잘 되어 있는 편이고, 사용자 포럼도 활발히 진행되어 피드백을 받기가 쉽다.


약간 성가신 부분은 요청 매핑(Request Mapping) 부분이다. config/routes.php 파일에, 요청을 일일이 기술해야 하는데, 사이트가 커지면서 요청 매핑의 갯수가 많아지면 이러한 중앙집중식 설정은 관리가 다소 애매해진다. 논리적인 단위로 파일을 나눌 수 있는지 확인이 필요하다.


또 다른 문제는 Front Controller다. index.php 파일이 Front Controller 역할을 하는데, 요청 URL에 모두 포함되어야 한다. 예를 들어 다음과 같다.

http://localhost/~socurites/ci-test/index.php/smartytest/index


그렇긴 해도 아파치 웹서버의 .htaccess 설정을 통해 처리할 수 있으니 큰 문제는 아니다.


PoC가 끝났으니, 실제 적용하기 전에, 고려할 사항이나 보안 이슈와 같이 주요한 요소를 찾아봐야 할 것 같다. 이 참에 제대로 해보려고 "CodeIgniter 한국 사용자 포럼" 운영자가 쓴 "만들면서 배우는 CodeIgniter 프레임워크" 책을 구매했다.


책 학습 후에 주요 내용을 정리하고자 한다.



저작자 표시
신고
Posted by socurites

CodeIgniter 역시 Smarty와 연동하는 표준 문서가 없어서 약간 헤매기는 했지만, Using Smarty 3 in Codeigniter 2 (a really tiny CI library)의 도움을 얻어서 설치하는데 성공했다.


이 튜토리얼을 따라하려면 반드시 "CodeIginter 프레임워크 사용 이력 - 튜토리얼" 시리즈를 따라하기를 바란다.


먼저 Github의 Vheissu/Ci-Smarty에 가서 ZIP 파일을 다운로드 한다. 압축을 풀어서, application/ 하위에 모두 붙여 넣는다. 3버전대의 스마티가 포함되어 있으므로 별도로 스마티를 다운로드 하지 않아도 된다.


다운로드한 ZIP 파일에는 예제 코드가 포함되어 있다. 예제코드를 실행하기 위해서, routes.php 파일을 아래와 같이 수정한다.

$route['smartytest/index'] = 'smartytest/index';     <--- 추가한 부분

$route['news/create'] = 'news/create';

$route['news/(:any)'] = 'news/view/$1';

$route['news'] = 'news';

$route['(:any)'] = 'pages/view/$1';

$route['default_controller'] = 'pages/view';


{사이트}/index.php/smartytest/index 로 접속하면 smartytest.tpl 파일이 정상적으로 표시되는 것을 확인할 수 있다.


만약 아래와 같은 에러가 웹서버 에러 로그에 나타난다면,

unable to write file application/cache/smarty/compiled


application/cache/smarty 디렉토리의 cached/, complied/ 디렉토리에 웹서버가 쓸 수 있는 권한을 부여해야 한다.



[참고자료]


저작자 표시
신고
Posted by socurites


티스토리 툴바