카테고리 없음

Laravel 02. Routing & Controller

테디아저씨 2026. 4. 10. 12:22

 

1. Route

1.1  why Route ?

 

PHP 프로젝트에서 우리는 /경로/php파일명을 URL 로 접근할 수 있습니다.

 

/aboutus/aboutus01.php

파일
/aboutus/aboutus01.php   

브라우저 경로
http://url.com/aboutus/aboutus01.php

 

1) 복잡한 URL 을 간결하게 바꿀수 있다.

http://teddy.school.com/board/list.php?board_id=study&step=view&bid=23

=> http://teddy.school.com/board/study/23

 

2) 보안을 위해 직접 php 파일에 접근을 차단한다.

http://url.com/aboutus.php

http://url.com/aboutus.blade.php   ( x ) 

 

 - php 프로젝트를 알수 있다. -> php 취약점 활용

 - 경로를 알수 있다 -> 백도어등의 프로그램을 심어 자신이 심은 php 파일을 실행한다.

 

* Route 는 사용자의 URL 접근을 해석해서 Route 가 알고 있는 파일을 실행해준다.

1.2. Route 살펴보기

routes/web.php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

 

view() 함수는 우리가 1강에서 이야기한 view 페이지를 보여주는 명령입니다.

 

1) 바로 Text 를 보내줄수도 있습니다.

Route::get('/aboutus', function () {
    return 'We are Hokma Teacher!';
});

 

2) 라우트에서 직접 로직을 만들고 결과를 리턴할 수도 있습니다.

Route::get('/addition', function () {
    $result = 2 + 3;    
    return "The result of 2 + 3 is: " . $result;
});

 

 

3) Html  로 작성한 view 를 지정할 수 있습니다.

Route::get('/services', function () {
    return view('services');
});

 

* 여기서 잠깐 존재하지 않는 경로를 호출하면 

 

없는 경로에 접근해보겠습니다.

http://127.0.0.1:8000/school

 

404 에러, 페이지가 존재하지 않다고 알려줍니다.

 

 

3) 리다이렉트

Route::get('/school', function () {
    return redirect('/service');
});

 

 

4) Controller 에게 처리를 지시하기

<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\LectureController;


# 컨트롤어와 function 을 지정해준다.
Route::get('/lectures', [LectureController::class, 'lectureIndex']);

 

# 컨트롤러를 사용할때는 web.php 상단에 LectureController 를 use 해 주어야 한다
# 컨트롤러의 자세한 내용은 다음시간에 공부하고 모양만 확인해보겠습니다.

 

app/Http/Controller/LectureController.php

<?php
namespace App\Http\Controllers;

class LectureController extends Controller
{
    public function lectureIndex()
    {
        return 'This is the lecture page.';
    }
}

 

 

5) 매개변수사용하기

Route::get('/article/{id}', function ($id) {
    return 'Article '.$id;
});

 

* 만약 id  없이 url 을 호출하면

 

404 를 보내줍니다.

 

* 선택적 매개변수

#id 가 있을수도, 없을수도 있습니다.
Route::get('/article/{id?}', function ($id=null) {
    return 'Article '.$id;
});

 

둘 이상의 매개변수를 사용할 수 있습니다.

Route::get('/article/{id}/comments/{commentId}', function ($id=null, $commentId=null) {
    return 'Article '.($id). ' - Comment '.($commentId);
});

 

 

5) 정규식 제약조건

Route::get('/program/{name}', function ($name) {
    return "Program's name " . $name;
})->where('name', '[A-Za-z]+');

 

http://127.0.0.1:8000/program/php

http://127.0.0.1:8000/program/php8

 

* 숫자도 허용하려면

Route::get('/program/{name}', function ($name) {
    return "Program's name " . $name;
})->where('name', '[A-Za-z0-9]+');

 

 

* 기타

Route::get('/user/{id}', function ($id) {
    //
})->where('id', '[0-9]+');

Route::get('/user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);


Route::get('/user/{id}/{name}', function ($id, $name) {
    //
})->whereNumber('id')->whereAlpha('name');

Route::get('/user/{name}', function ($name) {
    //
})->whereAlphaNumeric('name');

Route::get('/user/{id}', function ($id) {
    //
})->whereUuid('id');

 

 

 

6) naming  

Route::get('/user/profile', function () {
    //
})->name('profile');

 

## 컨트롤러등에서 URL 등을 대체해준다.

$url = route('profile');
return "User Index Page. Profile URL: " . $url;

 

## 매개변수를 사용할때

$url = route('profile',['id'=>1, 'name'=>'Teddy']);

 

 

우리는  Controller 를 통해 처리하는 방식을 주로 사용하게 될겁니다.

 

6) method

 

 

Route::get('/aboutus', function () {
    return 'We are Hokma Teacher!';
});

 

Route 에서 사용한  get 은 어떤 의미일까요?

Route::get('/signup', [UserController::class, 'signupForm'])->name("signup");
Route::post('/signup', [UserController::class, 'signup'])->name("signupok");
Route::post('/signupByOTP', [UserController::class, 'signupByOTP']);

Route::get('/register', [LoginController::class, 'registerForm'])->name('register');
Route::post('/register/confirm', [LoginController::class, 'registerConfirm'])->name('register.confirm');

 

네. route 에서는 get 방식으로 접근하는 경로, post 로만 접근하는 경로를 지정할 수있습니다.

* /signup  get, post 접근 가능여부를 직접 진행해볼것.

 

7) prepix

공통된 경로를 하나로 묶어 그룹화하여 간결하고 체계적으로 관리할수 있게 해줍니다.

// homepy 라우트
Route::get('/homepy/{homepyID}', [HomepyController::class, 'home'])->name('homepy.home');

Route::get('/homepy/{homepyID}/guestbook', [HomepyController::class, 'guestbook'])->name('homepy.guestbook');
Route::post('/homepy/{homepyID}/guestbook/update', [HomepyController::class, 'guestbook_update'])->name('homepy.guestbook_update');
Route::get('/homepy/{homepyID}/guestbook/delete/{no}', [HomepyController::class, 'guestbook_delete'])->name('homepy.guestbook_delete');

Route::get('/homepy/{homepyID}/lordplayer', [HomepyController::class, 'lordplayer'])->name('homepy.lordplayer');
Route::get('/homepy/{homepyID}/lordplayer/form', [HomepyController::class, 'lordplayer_form'])->name('homepy.lordplayer_form');
Route::post('/homepy/{homepyID}/lordplayer/update', [HomepyController::class, 'lordplayer_update'])->name('homepy.lordplayer_update');
Route::get('/homepy/{homepyID}/lordplayer/delete/{no}', [HomepyController::class, 'lordplayer_delete'])->name('homepy.lordplayer_delete');

Route::get('/homepy/{homepyID}/diary', [HomepyController::class, 'diary'])->name('homepy.diary');
Route::post('/homepy/{homepyID}/diary/update', [HomepyController::class, 'diary_update'])->name('homepy.diary_update');
Route::get('/homepy/{homepyID}/diary/delete/{no}', [HomepyController::class, 'diary_delete'])->name('homepy.diary_delete');

Route::get('/homepy/{homepyID}/picture', [HomepyController::class, 'picture'])->name('homepy.picture');
Route::get('/homepy/{homepyID}/picture/form', [HomepyController::class, 'picture_form'])->name('homepy.picture_form');
Route::post('/homepy/{homepyID}/picture/update', [HomepyController::class, 'picture_update'])->name('homepy.picture_update');
Route::get('/homepy/{homepyID}/picture/delete/{no}', [HomepyController::class, 'picture_delete'])->name('homepy.picture_delete');
Route::get('/homepy/{homepyID}/picture/form/{no}', [HomepyController::class, 'picture_form'])->name('homepy.picture_form');

Route::get('/homepy/{homepyID}/setting', [HomepyController::class, 'setting'])->name('homepy.setting');
Route::post('/homepy/{homepyID}/setting/update', [HomepyController::class, 'setting_update'])->name('homepy.setting_update');

Route::get('/homepy/{homepyID}/friend', [HomepyController::class, 'friend'])->name('homepy.friend');
Route::post('/homepy/{homepyID}/friend/request', [HomepyController::class, 'friend_request'])->name('homepy.friend_request');
Route::post('/homepy/{homepyID}/friend/cancel', [HomepyController::class, 'friend_cancel'])->name('homepy.friend_cancel');

Route::get('/homepy/{homepyID}/friend/{friendID}/accept', [HomepyController::class, 'friend_accept'])->name('homepy.friend_accept');
Route::get('/homepy/{homepyID}/friend/{friendID}/reject', [HomepyController::class, 'friend_reject'])->name('homepy.friend_reject');

Route::get('/homepy/{homepyID}/friend/request_list', [HomepyController::class, 'friend_request_list'])->name('homepy.friend_request_list');
Route::get('/homepy/{homepyID}/friend/{friendID}/delete', [HomepyController::class, 'friend_delete'])->name('homepy.friend_delete');

Route::get('/homepy/my/friend/list', [HomepyController::class, 'my_friend_list'])->name('homepy.my_friend_list');

 

//  Prefix 를 이용함

Route::prefix('homepy')->name('homepy.')->group(function () {

    Route::get('/{homepyID}', [HomepyController::class, 'home'])->name('homepy.home');

    Route::get('/{homepyID}/guestbook', [HomepyController::class, 'guestbook'])->name('homepy.guestbook');
    Route::post('/{homepyID}/guestbook/update', [HomepyController::class, 'guestbook_update'])->name('homepy.guestbook_update');

    Route::get('/{homepyID}/guestbook/delete/{no}', [HomepyController::class, 'guestbook_delete'])->name('homepy.guestbook_delete');

    Route::get('/{homepyID}/lordplayer', [HomepyController::class, 'lordplayer'])->name('homepy.lordplayer');
    Route::get('/{homepyID}/lordplayer/form', [HomepyController::class, 'lordplayer_form'])->name('homepy.lordplayer_form');
    Route::post('/{homepyID}/lordplayer/update', [HomepyController::class, 'lordplayer_update'])->name('homepy.lordplayer_update');
    Route::get('/{homepyID}/lordplayer/delete/{no}', [HomepyController::class, 'lordplayer_delete'])->name('homepy.lordplayer_delete');

    Route::get('/{homepyID}/diary', [HomepyController::class, 'diary'])->name('homepy.diary');
    Route::post('/{homepyID}/diary/update', [HomepyController::class, 'diary_update'])->name('homepy.diary_update');
    Route::get('/{homepyID}/diary/delete/{no}', [HomepyController::class, 'diary_delete'])->name('homepy.diary_delete');

    Route::get('/{homepyID}/picture', [HomepyController::class, 'picture'])->name('homepy.picture');
    Route::get('/{homepyID}/picture/form', [HomepyController::class, 'picture_form'])->name('homepy.picture_form');
    Route::post('{homepyID}/picture/update', [HomepyController::class, 'picture_update'])->name('homepy.picture_update');
    Route::get('/{homepyID}/picture/delete/{no}', [HomepyController::class, 'picture_delete'])->name('homepy.picture_delete');
    Route::get('/{homepyID}/picture/form/{no}', [HomepyController::class, 'picture_form'])->name('homepy.picture_form');

    Route::get('/{homepyID}/setting', [HomepyController::class, 'setting'])->name('homepy.setting');
    Route::post('/{homepyID}/setting/update', [HomepyController::class, 'setting_update'])->name('homepy.setting_update');

    Route::get('/{homepyID}/friend', [HomepyController::class, 'friend'])->name('homepy.friend');
    Route::post('/{homepyID}/friend/request', [HomepyController::class, 'friend_request'])->name('homepy.friend_request');
    Route::post('/{homepyID}/friend/cancel', [HomepyController::class, 'friend_cancel'])->name('homepy.friend_cancel');

    Route::get('/{homepyID}/friend/{friendID}/accept', [HomepyController::class, 'friend_accept'])->name('homepy.friend_accept');
    Route::get('/{homepyID}/friend/{friendID}/reject', [HomepyController::class, 'friend_reject'])->name('homepy.friend_reject');

    Route::get('/{homepyID}/friend/request_list', [HomepyController::class, 'friend_request_list'])->name('homepy.friend_request_list');
    Route::get('/{homepyID}/friend/{friendID}/delete', [HomepyController::class, 'friend_delete'])->name('homepy.friend_delete');

    Route::get('/my/friend/list', [HomepyController::class, 'my_friend_list'])->name('homepy.my_friend_list');

});

 

컨트롤러를 그룹화할 수도 있습니다. ( 저는 실무에서 사용해본적이 없는데 이런것도 있네요 )

# Route::post('shop/items', [ShopController::class, 'index']);


Route::prefix('shop')->controller(ShopController::class)->group(function () {
    Route::get('/items', 'index');   // /shop/items
    Route::get('/item/{id}', 'show'); // /shop/item/{id}
});

 

 

** 라우트에 대한 질문이 있으신가요?

 

2. Controller

"로직을 처리하는 부분"

"사용자 요청을 받아 모델(Model)과 상호작용하고, 결과를 뷰(View)나 JSON으로 반환하는 '중간 관리자' 역할을 수행"

 

2.1 컨트롤러 생성

php artisan make:controller PostController



# INFO  Controller [app/Http/Controllers/PostController.php] created successfully.

 

생성위치 app/Http/Controllers/PostController.php

 

2.2 컨트롤러 구조

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PostController extends Controller
{
    //
}

 

2.3 Route 와  Controller

Route::get('/posts', [PostController::class, 'index']);   // 목록
Route::get('/posts/create', [PostController::class, 'create']); // 작성폼
Route::post('/posts', [PostController::class, 'store']); // 저장

 

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PostController extends Controller
{
    public function index(Request $request)
    {
         return 'Posts List'
    }
    
    public function create(Request $request)
    {
         return 'Post Form'
    }
    
    public function store(Request $request)
    {
         return 'Post Save'
    }
}

 

 

** 연습을 한번 해보겠습니다.

여러분은 hokma 학원의 홈페이지를 만들고 있습니다.            -  program list

사용자가 Program 목록을 보고                                             -  program view

그중 Program 하나를 선택하면 상세페이지를 볼수 있습니다.  - program apply

신청버튼을 누르면 신청서를 작성하는 페이지가 나옵니다.        - program pply save

저장 버튼을 누르면 저장됩니다.

 

위에 예시를 만든것처럼 컨트롤러를 만들고  페이지를 안내하는 문자열을 출력하도록 해주세요.

 

 

2.4 __invoke  단일 작업 컨트롤러 (Single Action Controller)

 

특정 컨트롤러가 하나의 기능(예: 대시보드 표시, 결제 처리 등)만 수행한다면 여러 메서드를 만들 필요가 없습니다.

이때 __invoke 메서드를 사용합니다.

 

// 단일작업 컨트롤러 생성

php artisan make:controller IndexController --invokable

 

생성된 모양

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class IndexController extends Controller
{
    /**
     * Handle the incoming request.
     */
    public function __invoke(Request $request)
    {
        //
    }
}

 

사용시 function 을 지정하지 않고 사용합니다.

Route::get('/', IndexController::class);

 

 

"Laravel is an object-oriented (OOP) based framework, and all functions are composed of classes."

“Laravel은 객체지향(OOP) 기반 프레임워크이며, 모든 기능은 Class로 구성되어 있다”

 

<?php

class PostController extends Controller

 

<?php

class User extends Model

 

 

그외에도 서비스, 미들웨어 등도 모두 class 로 되어있습니다.

 

클래스는

1. 재사용 가능

→ 같은 코드를 여러 곳에서 사용

2. 구조화

→ 역할별로 나누기 쉬움

3. 확장성

→ 기능을 추가하기 쉬움

 

클래스 vs 객체

 

클래스는 설계도이고, 객체는 그 설계도대로 사용되는것

 

중요한 이야기는 나중에 모델을 공부할때 하도록 하겠습니다.

 

 

RESTful