본문 바로가기
코드이그나이터와 php7와 mysql

크레이의 라라벨 도전기#3 - 컨트롤러(Controller)

※ 이 게시글은 크레이의 IT개발 관련 성장기를 다루고 있습니다. 관련지식이 약간 있어야 이해되실 수 있습니다. 가벼운 마음으로 읽어보시면서 흥미가 생기고 의욕이 생긴다면? 개발자의 자질이 있으신 겁니다 :)

PHP 프로젝트를 접하다 보면 소스코드 구성 방식이 PHP 고전 방식을 접하게 될 때도 있고
최신 모던화된 방식을 접하게 될 때도 있습니다.
어떠한 경우 프레임워크는 최신이지만 소스코드는 고전 방식일 경우도 있는데요.
이러한 경우 앞으로 붙여나갈 기능을 어떻게 개발해 나가는게 좋을까요?

그러한 경우 소스코드 일관성을 위해 기존에 개발된 방식에 맞춰주는 것이 좋습니다.
개인적인 욕심으로는 최신 방식을 선호하긴 하지만 모든 걸 수정할 것이 아니라면 말이지요 :)


지난 시간에는 뷰(View)에 대해서 알아보았는데요.

크레이의 라라벨 도전기#2 - 뷰우(View) (tistory.com)

 

크레이의 라라벨 도전기#2 - 뷰우(View)

※ 이 게시글은 크레이의 IT개발 관련 성장기를 다루고 있습니다. 관련지식이 약간 있어야 이해되실 수 있습니다. 가벼운 마음으로 읽어보시면서 흥미가 생기고 의욕이 생긴다면? 개발자의 자질

itadventure.tistory.com

라라벨(Laravel)에서는 라우터(Router)와 뷰(View)만 가지고도 전통방식으로 모든 것을 개발할 수 있는 것으로 보이는데요. 이름 짓기를 좋아하는 크레이는 이 방식을 RV 패턴이라고 부르도록 하겠습니다.
이 방식은 고전 PHP 개발방식으로 PHP소스코드와 디자인을 하나의 파일에 몰아서 코딩하는 방식인데요.
사실 이 방식도 나쁘지는 않습니다. 적어도 작동하는 속도면에서 최강이거든요.

프레임워크를 사용하면 아무래도 고전 방식보다는 작동 속도는 느려집니다.
하지만 요새는 웹서버 성능이 좋기 때문에 프레임워크를 사용해도 서버에 별로 부담이 없습니다.

프레임워크를 사용할 경우 소스코드의 표준화가 되기 때문에 오너(사장) 입장에서는 개발하던 직원이 퇴사하더라도 해당 프레임워크에 익숙한 다른 직원을 뽑아 투입하면 비교적 빠른 대처가 가능하기 때문이지요.

개발방법을 가지고 개발자끼리 싸우는 사례를 봐온 적도 있는데요. ( 뭐 크레이는 이러한 경우 회사 발전을 위해 한 발짝 양보합니다 ㅎ.. 제 자신의 이익보다 회사의 이익을 위헤서 말이지요. 싸우는 것은 불필요한 자원 낭비입니다. ) 프레임워크를 어떤 걸로 채택하느냐에 따라 개발 방법 절반은 결정되었다 해도 과언이 아닙니다. 절반의 문제를 해결하고 시작하는 것이지요.

라라벨 프레임워크에서 채택하는 MVC 패턴은 비교적 모던화된 개발 방식인데요.
이는 기능과 디자인(퍼블리셔) 작업을 99.9% 분리할 수 있도록 프레임워크가 자리를 잡아주기 때문입니다.

PHP 백앤드 개발자PHP 소스 코드만 신경써 개발하고,
퍼블리셔 개발자HTML 코딩을 주요 작업으로 하면 되는데요.
혼자 모든 것을 개발하는 1인 개발자라면 도리어 이 부분이 귀찮고 개발하는 작업속도도 떨어집니다.
그래서 프레임워크는 일을 분업할 때 비로서 그 성능이 빛을 발합니다.

오늘 다루는 컨트롤러는 바로 이 부분에 해당합니다.
PHP 백앤드 개발자가 다루는 부분은 보통 컨트롤러(Controller), 모델(Model)이고,
퍼블리셔 개발자가 다루는 부분이 바로 뷰(View)입니다.

오늘은 설명이 꽤 길었군요. 이제 그러면 코드 작업에 들어가겠습니다 :)


설명은 길었지만 내용은 간단한 걸 다뤄볼텐데요. 4권의 책 목록을 조회하고, 목록 중 아무거나 하나를 클릭하면 상세한 내용을 보여주는 아~주 간단한 예제입니다.

먼저 결과물을 확인해볼까요?

목록 페이지에 접근하면 ( 3.86.255.54/book/list )
책의 목록이 보여지는데요.

이 중 하나의 책을 클릭하면,

책의 상세 내용이 보여지는 기능입니다.
책 제목에 비해 이미지는 좀 생뚱맞지요 :)

그리고 목록으로 돌아가기 버튼을 누르면 다시 원래 페이지로 복귀하는 뭐 그런 간단한 서비스입니다.


라우터 수정

각 페이지 명세는 아래와 같습니다.

달랑 2개라 간단하지요.

# 책 목록 조회 : /book/list
# 책 상세 페이지 : /book/{id}
 * id : 책 번호

이를 위해 라우터 페이지에 아래 부분을 추가하였습니다.
지난번과 다른 부분은 뷰 페이지로 연결되는 것이 아니라,
컨트롤러 페이지로 연결된다는 것입니다. 컨트롤러는 잠시 후에 다뤄보겠습니다.

Route::get('/book/list', 'BookController@list');
Route::get('/book/{id}', 'BookController@detail');

 

MYSQL 데이터 구성

책 목록은 mysql로 관리하도록 하였는데요.
과거에 코드이그나이터4로 비슷한 Mysql 컨텐츠를 다룬 적이 있어 링크를 공유합니다.

MYSQL 이 뭐여? [ 마이에스큐엘은 서류철이다! ] (tistory.com)

여기서 사용하는 테이블 구조는 아래와 같습니다.
라라벨에서 소스코드를 이용하여 테이블을 구성하는 방법 대신,
SQLyog 프로그램 그래픽 화면에서 진행하였습니다.
크레이는 툴이 더 편하더라구요.

CREATE TABLE `books` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `bookName` varchar(100) DEFAULT '' COMMENT '책제목',
  `Author` varchar(100) DEFAULT '' COMMENT '저자',
  `Page` int(11) DEFAULT '0' COMMENT '페이지',
  `Publisher` varchar(100) DEFAULT '' COMMENT '출판사',
  `img` varbinary(100) DEFAULT NULL COMMENT '이미지',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

그리고 입력 데이터와 이미지도 준비하였습니다.
SQL문으로 입력한건 아니고 SQLyog 프로그램에서 엑셀 입력하듯이 입력하면 순삭이지요.
SQL입력문도 공유드립니다.

insert into `books` (`id`, `bookName`, `Author`, `Page`, `Publisher`, `img`) 
values('1','유니티3D','크레이','500','크레이펍스','christmas-star-g7aad7e766_640.jpg');
insert into `books` (`id`, `bookName`, `Author`, `Page`, `Publisher`, `img`) 
values('2','토익365','코레이','300','크레이펍스','dog-g37ea67bda_640.jpg');
insert into `books` (`id`, `bookName`, `Author`, `Page`, `Publisher`, `img`) 
values('3','CentOS7정석','카레이','700','크레이펍스','girl-g567be5f03_640.jpg');
insert into `books` (`id`, `bookName`, `Author`, `Page`, `Publisher`, `img`) 
values('4','요리조리','수산나','200','크레이펍스','rose-g33486cdec_640.jpg');

라라벨에서 MYSQL 세팅

라라벨에서 mysql을 사용하기 위해서는 데이터베이스 설정을 해주어야 하는데요.
데이터베이스는 뭘로 할건지, 접속하는 서버 주소, 아이디, 패스워드 등을 정해주어야 하기 때문입니다.
라라벨  프로젝트에 숨김파일로 .env 라는 파일이 있는데 이 파일을 열어서 수정해주면 됩니다.

        :
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=DB이름
DB_USERNAME=root
DB_PASSWORD=패스워드
        :

크레이는 SFTP 프로그램으로 평소에 XFTP 를 사용하는데 글쎼 숨김파일이 안 보이더라구요.
vi에디터로 직접 수정할까 하다가 찾아보니 보는 설정이 있더라구요. 설정을 변경해 수정했습니다.

컨트롤러

이제 책의 목록과 책의 상세 내용 조회를 제공하는 리스트 페이지를 마련해야 겠지요.
이를 위해 컨트롤러 클래스를 마련했는데요.
작동할 PHP 코드는 컨트롤러 코드쪽에 적어주는 것이 좋습니다.
라우터에서 아래와 같이 이름을 정해주었기 때문에

Route::get('/book/list', 'BookController@list');
Route::get('/book/{id}', 'BookController@detail');

컨트롤러 클래스의 이름은 BookController 가 되어야 합니다.
컨트롤러 폴더 기본 위치는 app/Http/Controllers 입니다.

그리고 @ 기호 뒤에 이름지어준 list, detail 은 각각 리스트, 상세 페이지에 해당하는 작동을 할
클래스 메소드인데요.

Route::get('/book/list', 'BookController@list'); 
Route::get('/book/{id}', 'BookController@detail');

컨트롤러 소스에서 아래와 같이 각각 메소드로 구현하면 됩니다.
BookController.php 전체 코드는 아래와 같습니다.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use DB;

class BookController extends Controller
{
	public function list(){
		$result = DB::select("SELECT * FROM books;");
		return view('book.list', [ 
			'books'=>$result 
		]);
	}
	
	public function detail($id){
		$result = DB::select("SELECT * FROM books WHERE `id`='$id' LIMIT 1;");
		if(count($result)==0) return "Book id is error.";
		return view('book.detail', [ 
			'book'=>$result[0]
		]);
	}
}

list() 메소드는 책의 목록을 mysql 데이터베이스로부터 불러오는 기능입니다.
여기서는 책의 목록을 불러올뿐 화면에 직접 출력하지는 않는데요.
출력하는 부분은 뷰에서 담당합니다.
단순히 아래의 2가지 동작을 진행하지요.

1) MYSQL 에서 책을 불러온다.
  $result = DB::select("SELECT * FROM books;");

2) 뷰에 전달한다.
  return view('book.list', [ 
    'books'=>$result 
  ]);

이 때 뷰의 이름이 book.list 인 것은 뷰 파일 위치가
뷰 기본폴더 resources/views 에서 한단계 더 들어간 resources/views/book 폴더이고,
뷰 파일이 list라는 의미입니다. 파일명은 긴 확장자가 붙어 list.blade.php 가 됩니다.
슬래시(/) 기호 대신 점(.) 기호를 사용하는게 좀 희안하다는 느낌이 들었습니다.

detail() 메소드는 입력된 책의 번호에 해당하는 단 하나의 책을 반환하는데요.
책 번호가 잘못 입력되는 경우가 발생할 수 있어 방지 코드가 하나 마련되어 있습니다.
아래의 3가지 동작이 순차적으로 진행됩니다.

1) $id 번호에 해당하는 책 1권의 정보만 MYSQL에서 불러옵니다.
  $result = DB::select("SELECT * FROM books WHERE `id`='$id' LIMIT 1;");

2) 만일 그런 책 정보가 없으면 단순 오류 메시지를 화면에 출력합니다.
  if(count($result)==0) return "Book id is error.";

3) 뷰에 전달하되 책정보가 1권뿐이므로 배열로 전달하지 않고 직접 책의 정보만 전달합니다.
  return view('book.detail', [ 
    'book'=>$result[0]
  ]);

통신 명세와 뷰

이로써 PHP 백앤드쪽 코드가 완료되었고 이어서 뷰쪽 코드를 살펴보겠습니다.
뷰를 개발할 개발자와 의사 소통을 위해서는 백앤드 개발자가 뷰에 어떤 파라미터가 전달되어야 할지 전해주어야 합니다. 혼자만 알고 있으면 뷰 개발자는 당황할 수 밖에 없지요 :)

책목록 뷰 페이지의 파라미터 명세는 아래와 같습니다.
이와 같은 명세를 정리해서 전달해주어야 합니다.

# 페이지 URL : /book/list
- 뷰 파일 : resources/views/book/list.blade.php
- books : Array[]
  -> id : 책의 고유 일련번호 ( 서버에서 결정 )
  -> bookName : 책 이름
  -> Author : 저자
  -> Page : 페이지
  -> Publisher : 출판사

책의 목록을 출력하는 소스 코드는 아래와 같은데요.
나름 간결하게 꾸며보았습니다.

resources/views/book/list.blade.php

<html>
<body>
	<style>
	h1{ text-decoration: underline; }
	table { border-collapse: collapse; }
	td { border:1px solid #373737; }
	.book { cursor:pointer; }
	</style>
	
	<script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
	
	<h1>책 목록</h1>
	
	<table>
	<tr>
		<td>책제목</td>
		<td>저자</td>
		<td>페이지</td>
		<td>출판사</td>
	</tr>
	@foreach ($books as $book)
		<tr class='book' bookId="{{ $book->id }}">
		<td>{{ $book->bookName }}</td>
		<td>{{ $book->Author }}</td>
		<td>{{ $book->Page }}</td>
		<td>{{ $book->Publisher }}</td>
		</tr>
	@endforeach
	</table>
	
	<script>
	$(".book")
	.mouseover(function(){ $(this).css('background-color', '#f0f0f0'); })
	.mouseout(function(){ $(this).css('background-color', ''); })
	.click(function(){
		location.href='/book/' + $(this).attr('bookId');
	});
	</script>
</body>
</html>

주목할 부분은 책을 반복으로 출력하는 아래 코드인데요.

@foreach ($books as $book)
    <tr class='book' bookId="{{ $book->id }}">
        <td>{{ $book->bookName }}</td>
        <td>{{ $book->Author }}</td>
        <td>{{ $book->Page }}</td>
        <td>{{ $book->Publisher }}</td>
    </tr>
@endforeach

단순한 반복 패턴으로 퍼블리셔도 몇번 접하면 쉽게 익숙해질 수 있습니다.

그리고 마우스를 대거나 뗄때 배경색 변경 효과와,
클릭시 상세페이지 이동도 간단히 구성해보았습니다.

<script>
$(".book")
.mouseover(function(){ $(this).css('background-color', '#f0f0f0'); })
.mouseout(function(){ $(this).css('background-color', ''); })
.click(function(){
    location.href='/book/' + $(this).attr('bookId');
});
</script>

이어서 책의 상세 페이지 명세는 아래와 같은데요.

# 페이지 URL : /book/{id}
- 뷰 파일 : resources/views/book/detail.blade.php

- book : Object
  -> id : 책의 고유 일련번호 ( 서버에서 결정 )
  -> bookName : 책 이름
  -> Author : 저자
  -> Page : 페이지
  -> Publisher : 출판사
  -> img : 책 이미지 ( /img/  폴더 기준 )

뷰 코드는 아래와 같습니다.

resources/views/book/detail.blade.php

<html>
<body>
	<style>
	h1{ text-decoration: underline; }
	table { border-collapse: collapse; }
	td { border:1px solid #373737; }
	.book { cursor:pointer; }
	img { margin: 20px; }
	button { cursor:pointer; }
	</style>
	
	<script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
	
	<h1>{{ $book->bookName }}</h1>
	
	<img src='/img/{{ $book->img }}' width=200>
	
	<table>
	<tr>
		<td>저자</td>
		<td>{{ $book->Author }}</td>
	</tr>
	<tr>
		<td>페이지수</td>
		<td>{{ $book->Page }}</td>
	</tr>
	<tr>
		<td>출판사</td>
		<td>{{ $book->Publisher }}</td>
	</tr>
	</table>
	
	<button id='goList'>목록으로 돌아가기</button>
	
	<script>
	$("#goList")
	.click(function(){
		location.href='/book/list';
	});
	</script>
	
</body>
</html>

 

라라벨에서는 이와 같이 PHP코드단과 뷰를 분리하여 관리할 수 있는데요.
소스가 나누어서 분류되기 때문에 깔끔해지는 것을 볼 수 있습니다.

오늘도 스크롤 압박(?) 컨텐츠를 하나 게시하게 되었네요.
필요하신 분께는 도움이 되시기를,
그리고 필요없어도 늘 찾아와주시는 분들께도 늘 감사드립니다 :)