컨트롤러(Controller)

컨트롤러는 HTTP 요청 처리 방법을 결정하며, 어플리케이션의 핵심입니다.

컨트롤러란 무엇입니까?

컨트롤러는 URI와 연결될 수 있는 방식으로 이름 붙여진 클래스 파일입니다.

다음 URI를 살펴보세요.

example.com/index.php/helloworld/

위의 예제에서 CodeIgniter는 Helloworld.php 라는 컨트롤러를 찾아 로드하려고 시도합니다.

컨트롤러 이름이 URI의 첫 번째 세그먼트와 일치하면 로드됩니다.

해봅시다 - Hello World!

간단한 컨트롤러를 만들어 실제로 볼 수 있도록 하겠습니다. 에디터를 사용하여 Blog.php 라는 파일을 만들고 다음 코드를 넣습니다.

<?php namespace App\Controllers;

use CodeIgniter\Controller;

class Helloworld extends Controller
{
        public function index()
        {
                echo 'Hello World!';
        }
}

이 파일을 /app/Controllers/ 디렉토리에 저장합니다.

Important

‘Helloworld.php’는 대문자 ‘H’로 시작되어야 합니다.

이제 이와 유사한 URL을 사용하여 사이트를 방문하십시오.

example.com/index.php/helloworld

제대로 했다면 결과는:

Hello World!

Important

컨트롤러 클래스 이름은 대문자로 시작해야 하며, 첫번째 문자만 대문자입니다.

올바른 예:

<?php namespace App\Controllers;

use CodeIgniter\Controller;

class Helloworld extends Controller {

}

틀린 예1:

<?php namespace App\Controllers;

use CodeIgniter\Controller;

class helloworld extends Controller {

}

틀린 예2:

<?php namespace App\Controllers;

use CodeIgniter\Controller;

class HelloWorld extends Controller {

}

여러분이 작성한 컨트롤러가 모든 메소드를 상속받을 수 있도록 상위 컨트롤러 클래스를 확장해야 합니다.

메소드

위 예제에서 메소드 이름은 index()입니다. URI의 두 번째 세그먼트가 비어 있으면 “index” 메소드가 항상 기본적으로 로드됩니다. “Hello World” 메시지를 표시하는 다른 방법은 다음과 같습니다.

example.com/index.php/helloworld/index/

URI의 두 번째 세그먼트는 컨트롤러에서 호출할 메소드를 결정합니다.

컨트롤러에 새로운 메소드를 추가해 봅시다.

<?php namespace App\Controllers;

use CodeIgniter\Controller;

class Helloworld extends Controller
{

        public function index()
        {
                echo 'Hello World!';
        }

        public function comment()
        {
                echo 'I am not flat!';
        }
}

이제 다음 URL을 로드하여 comment 메소드를 봅니다.:

example.com/index.php/helloworld/comment/

새로운 메시지가 표시됩니다.

메소드에 URI 세그먼트 전달

URI에 세 개 이상의 세그먼트가 포함되어 있으면 메소드에 매개 변수(parameters)로 전달됩니다.

예를 들어 이와 같은 URI가 있다고 가정 해 봅시다.:

example.com/index.php/products/shoes/sandals/123

메소드에 URI 세그먼트 3과 세그먼트 4가 전달됩니다. (“sandals” 와 “123”):

<?php namespace App\Controllers;

use CodeIgniter\Controller;

class Products extends Controller
{

        public function shoes($sandals, $id)
        {
                echo $sandals;
                echo $id;
        }
}

Important

URI 라우팅 기능을 사용하는 경우 메소드에 전달 된 세그먼트가 다시 라우팅됩니다.

기본 컨트롤러 정의

사이트 루트 URL만 요청할 때, Helloworld 컨트롤러를 로드하도록 할 수 있습니다.

기본 컨트롤러를 지정하려면 app/Config/Routes.php 파일을 열고 아래 부분을 수정하십시오.

$routes->setDefaultController('Helloworld');

여기서 ‘Helloworld’는 사용하려는 기본 컨트롤러 클래스의 이름입니다. Routes.php의 라인 코멘트 “Route Definitions” 섹션 몇 줄 아래 있습니다.

$routes->get('/', 'Home::index');

URI 세그먼트를 지정하지 않고 사이트를 탐색하면 “Hello World”메시지가 표시됩니다.

Note

$routes->get('/', 'Home::index');은 “실제” 앱에서 사용하는 최적화된 경로입니다. 시연 목적으로 이 기능을 사용하고 싶지 않습니다. $routes->get()에 대한 설명은 URI 라우팅을 살펴보세요.

자세한 내용은 URI 라우팅 설명서의 “라우트 구성 옵션” 섹션을 참조하십시오.

리매핑 메소드 호출

위에서 언급 한 바와 같이, URI의 두 번째 세그먼트는 일반적으로 컨트롤러에서 호출되는 메소드를 결정합니다. _remap() 메소드를 사용하면 CodeIgniter의 이 동작을 재정의 할 수 있습니다.

public function _remap()
{
        // Some code here...
}

Important

컨트롤러에 _remap()이라는 메소드가 포함되어 있으면 URI에 포함 된 내용에 관계없이 항상 호출됩니다. URI는 어떤 메소드가 호출되는지 판별하여 사용자 고유의 메소드 라우팅 규칙을 정의할 수 있는 일반적인 동작을 대체합니다.

재정의 된 메소드 호출(일반적으로 URI의 두 번째 세그먼트)은 _remap() 메소드에 매개 변수로 전달됩니다.

public function _remap($method)
{
        if ($method === 'some_method')
        {
                $this->$method();
        }
        else
        {
                $this->default_method();
        }
}

메소드 이름 뒤의 추가 세그먼트는 _remap()에 전달됩니다. 이러한 매개 변수는 CodeIgniter의 기본 동작을 에뮬레이트하기 위해 메소드로 전달될 수 있습니다.

Example:

public function _remap($method, ...$params)
{
        $method = 'process_'.$method;
        if (method_exists($this, $method))
        {
                return $this->$method(...$params);
        }
        throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
}

비공개 메소드

경우에 따라 외부에 특정 메소드를 숨겨야할 수도 있습니다. 메소드를 private 또는 protected로 선언하면 URL 요청을 통해 접근할 수 없습니다. “Helloworld” 컨트롤러에 대해 이와 같은 방법을 사용한 예입니다.

protected function utility()
{
        // some code
}

아래와 같이 URL을 통해 액세스하려고 하면 동작하지 않습니다.

example.com/index.php/helloworld/utility/

컨트롤러를 하위 디렉토리로 구성

CodeIgniter를 사용하면 컨트롤러를 하위(sub) 디렉터리에 계층적으로 구성하여 큰 어플리케이션을 구축할 수 있습니다.

메인 app/Controllers/ 아래에 하위 디렉토리를 만들고 그 안에 컨트롤러 클래스를 배치하십시오.

Note

이 기능을 사용할 때 URI의 첫 번째 세그먼트는 폴더를 지정해야 합니다. 예를 들어 다음과 같은 컨트롤러가 있다고 가정해 봅시다.

app/Controllers/products/Shoes.php

위의 컨트롤러를 호출하기 위한 URI는 다음과 같습니다.

example.com/index.php/products/shoes/show/123

각 하위 디렉토리에는 URL에 하위 디렉토리만 호출하는 경우를 위하여 기본 컨트롤러가 지정할 수 있습니다. app/Config/Routes.php 파일의 ‘default_controller’에 이를 위한 컨트롤러를 지정하십시오.

CodeIgniter에서는 URI 라우팅 기능을 사용하여 URI를 다시 매핑할 수도 있습니다.

포함된 속성

생성하는 모든 컨트롤러는 CodeIgniter\Controller 클래스를 확장해야 합니다. 이 클래스는 모든 컨트롤러에서 사용할 수 있는 몇 가지 기능을 제공합니다.

Request Object

어플리케이션의 Request 인스턴스는 클래스의 $this->request 속성으로 제공됩니다.

Response Object

어플리케이션의 Response 인스턴스는 클래스의 $this->response 속성으로 제공됩니다.

Logger Object

Logger 클래스의 인스턴스는 클래스 $this->logger 속성으로 제공됩니다.

forceHTTPS

HTTPS를 통해 메소드에 액세스할 수있는 편리한 메소드를 모든 컨트롤러에서 사용할 수 있습니다.

if (! $this->request->isSecure())
{
        $this->forceHTTPS();
}

기본적으로, HTTP Strict Transport Security 헤더를 지원하는 최신 브라우저는 이 호출을 통하여 HTTPS가 아닌 호출을 1년 동안 HTTPS 호출로 변환하도록 강제합니다. 지속 시간(초)은 매개 변수를 전달하여 수정할 수 있습니다.

if (! $this->request->isSecure())
{
        $this->forceHTTPS(31536000);    // one year
}

Note

숫자 대신 YEAR, MONTH등 시간 기반 상수를 사용할 수도 있습니다.

헬퍼

클래스 속성에 헬퍼를 배열로 정의할 수 있습니다. 컨트롤러가 로드될 때마다 정의된 헬퍼도 자동으로 로드되며, 컨트롤러 내부의 어느 위치에서든 헬퍼에 정의된 메소드를 사용할 수 있습니다.

namespace App\Controllers;
use CodeIgniter\Controller;

class MyController extends Controller
{
        protected $helpers = ['url', 'form'];
}

데이터 검증

데이터 확인을 단순화하기 위해 컨트롤러는 편리한 메소드 validate()를 제공합니다. 이 메소드는 첫 번째 매개 변수와 선택적 두 번째 매개 변수에 항목이 유효하지 않은 경우 표시할 사용자 정의 오류 메시지 배열의 규칙 배열을 허용합니다. 내부적으로 이것은 컨트롤러의 $this->request 인스턴스를 사용하여 데이터의 유효성을 검사합니다. 유효성 검사 라이브러리 문서에는 이에 대한 메시지 배열의 형식과 사용 가능한 규칙에 대한 세부 정보가 있습니다.

public function updateUser(int $userID)
{
    if (! $this->validate([
        'email' => "required|is_unique[users.email,id,{$userID}]",
        'name'  => 'required|alpha_numeric_spaces'
    ]))
    {
        return view('users/update', [
            'errors' => $this->validator->getErrors()
        ]);
    }

    // do something here if successful...
}

Config\Validation.php에 정의된 규칙의 그룹 이름을 $rules 배열에 명시하여 간단하게 구성 파일에 정의된 규칙을 적용할 수 있습니다.

public function updateUser(int $userID)
{
    if (! $this->validate('userRules'))
    {
        return view('users/update', [
            'errors' => $this->validator->getErrors()
        ]);
    }

    // do something here if successful...
}

Note

모델에서 유효성 검사를 자동으로 처리할 수 있지만 때로는 컨트롤러에서 확인하기가 더 쉽습니다. 선택은 당신에게 달려 있습니다.

이게 다임!

이것이 컨트롤러에 대해 알아야 할 모든 것입니다.