MVC(Model View Controller) ?

Prologue

학부 시절부터 MVC, MVC 수도 없이 들어왔지만, 똑 부러지게 이해하기 쉽게 설명해주는 사람은 많지 않았다. 그저 “모델 뷰 컨트롤러… 그거야..” 라고 답변이 있을 뿐이어서 프로그래밍 공부를 하는 필자도 와닿지 않는 개념이었다. MVC가 무엇인지, 내 경험과 인터넷 끄적끄적 구글링을 통해 얻은 결론을 한 번 정리해보고자 한다.

CodeIgniter의 MVC구조

php 프레임워크 CodeIgniter 를 예시로 들어보겠다. 위 그림은 코드이그나이터의 MVC 구조이다. 모델, 뷰, 컨트롤러 외에도 여러가지가 있지만 일단 세 가지의 구조라도 잘 이해하고 넘어가자. 그것만 알아도 나머지는 부수적인 것에 지나지 않으니까 말이다. 어디까지나 내가 이해한 방식이니 혹여 다른 생각을 가지고 있는 다른 누리꾼이 코멘트를 남겨주신다면, 이 또한 재밌는 토론이 될 것 같다. :)

모델(Model) : 뒤에서 묵묵히 데이터를 처리한다.

모델은 실제로 우리가 눈으로 보기 힘든 요소이다. 아니, 안보인다고 해도 무방하겠다. 주로 데이터베이스에 접근하여 데이터를 읽고(R), 쓰고(C), 수정하고(U), 삭제하는(D) 역할이다. 다른 로직을 쓰는 것은 모델에게 사치다. 사용자가 브라우저를 통해 데이터와 관련된 어떤 동작(주로 클릭)을 하면 컨트롤러를 통해 모델이 호출되고, 모델은 그저 데이터를 처리하고 컨트롤러로 전달해주는 역할을 수행한다. 사용자는 모델이 실제로 무엇을 하는지 정확히 알 수 없다. 이러한 MVC구조를 모른다면 ‘눌렀으니까 그냥 나오는거군!’ 하고 느낄 수 있지만, 모델 입장에서 섭섭하겠지만 어쩌나… 보이지 않는 것을… 하지만 제 역할을 해야만 어플리케이션이 정상적으로 작동할 것이다.

뷰(View) : 가상의 결과를 현실화하다. 사용자의 눈을 즐겁게 하라.

주로 백엔드 개발을 하는 나에게 를 만드는 프론트엔드 개발자는 해리 포터 못지 않은 마법사다. 화면을 구성하는 언어로 실제로 구현해야 할 것을 뾰로롱~ 하고 만들어내는 듯한 뷰 역시 MVC의 핵심 멤버이다. 모델과 컨트롤러가 제 역할을 수행하고 응답을 뷰에 넘겨주었다면, 뷰는 예쁘게 그리는 것이 관건이다. 사용자는 대부분 어플리케이션(웹, 모바일)에서의 만족도를 뷰에서 느끼기 때문에, 사용자 경험(UX)에 관한 부분을 특히 신경써야 한다. 학부 시절 김교수님은 뷰를 굉장히 중요하게 여기셨다. 눈이 즐거운 어플리케이션은 기능이 조금 부족할 지라도, 사용자로 하여금 만족감을 느끼게 만들 수 있다는 것이다. 과거에는 기능만 잘 돌아가면 된다! 라는 것이 주였지만, 지금은 보여지는 것 또한 기능과 거의 동등하게 여겨질 정도로 뷰도 잘 만들어져야 한다.

컨트롤러(Controller) : 어플리케이션의 핵심, 요청과 응답의 중심지

축구로 치면 중원 미드필더라고 보면 되겠다. 치열한 공싸움이 일어나는 필드처럼 웹서버에서 수많은 요청과 응답을 주고 받는다. 모델과 뷰의 중간다리 역할을 하며 어플리케이션이 잘 작동되도록 요청과 응답을 받고 던지고… 제일 바쁜놈이라고 볼 수 있다. 코드이그나이터에서는 헬퍼, 라이브러리 등의 부가적인 요소들이 있어서 컨트롤러는 더욱 바빠진다. 부가 요소를 호출하고, 모델에게는 ‘데이터 처리 좀 부탁해!’ 라고 요청하며, 모델이 제 역할을 했다면 그 결과를 뷰에게 ‘자 여기 응답 결과야!’ 라며 전달한다. 가장 바쁜 시간에는 연예인 못지 않은 스케쥴이다.

결국 중요한 것은

MVC에서 가장 중요한 요소? 그건 말할 수 없다. 세 가지 요소가 적절히 조화를 이루어야 좋은 어플리케이션이 될 수 있다. 어떻게 보면 개발자들에게 MVC는 부담되겠지만, 잘만 만든다면 제일 인정받는 사람이 될 수도 있다. MVC를 적용한 프레임워크는 현재 개발자들이 주로 사용한다. 우리나라에서는 특히 자바 기반의 스프링(Spring)이 가장 인기 있는 프레임워크일 정도이니…(사실 개발자들이 좋아하는진 모르겠다..)
필자의 글을 읽고 조금이나마 MVC에 대한 개념이 아리송 하거나 몰랐던 분들에게 도움이 되었으면 좋겠다. :)

라즈베리파이 nginx, php-fpm, mysql(mariadb) 설치

php 개발환경을 세팅해보겠다.

nginx 설치

1
2
$ sudo apt-get install nginx
$ sudo service nginx restart

생각보다 설치와 실행이 너무 쉬워서 깜짝 놀랬다.
http://localhost로 접속하여 확인하자.

php7 설치

설치 준비

php7에 대한 정보가 없기 때문에 이를 추가해 주는 과정이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ sudo vi /etc/apt/sources.list

# 아래 줄을 추가한다.
deb http://repozytorium.mati75.eu/raspbian jessie-backports main contrib non-free

# 키서버를 등록해준다.
$ sudo gpg --keyserver pgpkeys.mit.edu --recv key CCD91D6111A06851

gpg: directory '/root/.gnupg' created
gpg: new configuration file '/root/.gnupg/gpg.conf' created
gpg: WARNING: options in '/root/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring '/root/.gnupg/secring.gpg' created
gpg: keyring '/root/.gnupg/pubring.gpg' created
gpg: "key" not a key ID: skipping
gpg: requesting key 11A06851 from hkp server pgpkeys.mit.edu
sudo gpg --armgpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key 11A06851: public key "Mateusz Łukasik <mati75@linuxmint.pl>" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
$ sudo gpg --armor --export CCD91D6111A06851 | sudo apt-key add -

업데이트한다.

1
$ sudo apt update -y

php7 설치 (php-fpm)

1
$ sudo apt install php7.0 php7.0-cli php7.0-common php7.0-fpm php7.0-gd php7.0-json php7.0-mcrypt php7.0-mysql php7.0-readline -y

nginx의 소켓 업데이트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ sudo apt-get install php7.0-fpm
$ sudo vi /etc/nginx/sites-available/default
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php5-cgi alone:
# fastcgi_pass 127.0.0.1:9000;
# # With php5-fpm:
# fastcgi_pass unix:/var/run/php5-fpm.sock;
#}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

# index index.html index.php index.htm 역시 추가하도록 하자

nginx 설정이 수정되었으므로 서비스 재시작을 한다.

1
$ sudo service nginx restart

php 버전을 확인해본다.
버전 정보가 출력된다면 설치가 잘 된 것이다.

1
2
3
4
5
$ php -v
PHP 7.0.19-1~bpo8+1 (cli) (built: May 12 2017 20:05:12) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
with Zend OPcache v7.0.19-1~bpo8+1, Copyright (c) 1999-2017, by Zend Technologies

mysql 설치 (mariadb)

역시 패키지부터 설치해주자.

1
$ sudo apt-get install mariadb-server

root 사용자 비밀번호를 설정하는 창이 나오면 입력하고 한 번 더 입력해준다.

그리고 3306 포트에 대한 방화벽을 열어준다.

1
2
3
$ sudo iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
$ sudo iptables -A OUTPUT -p tcp --dport 3306 -j ACCEPT
$ sudo iptables-save

따로 재시작을 해 줄 필요도, 할 수도 없지만 iptables-save 명령어로 방화벽 정책이 저장된 것이다.

root 로 접속 확인 후
‘사용자명’@‘%’ 를 mysql.user 테이블에 추가하여 테이블 권한을 적절하게 주도록 한다.

라즈베리파이 자동 마운트

라즈베리파이에서 외장하드를 연결하여 사용 중인 사용자가 있다면
장치를 자동으로 마운트시키고 싶을 것이다.
이번 글에서는 외부 장치를 auto mount 시키는 방법을 알아보겠다.

장치 확인

우선 장치 확인을 해 본다.

1
2
3
4
5
6
$ sudo blkid

/dev/mmcblk0p1: LABEL="boot" UUID="95E0-9AC4" TYPE="vfat" PARTUUID="f8e97239-01"
/dev/mmcblk0p2: UUID="b105f9a8-f450-4976-8ac8-69053f57bab4" TYPE="ext4" PARTUUID="f8e97239-02"
/dev/mmcblk0: PTUUID="f8e97239" PTTYPE="dos"
/dev/sda1: LABEL="My Passport" UUID="904A19514A193586" TYPE="ntfs" PARTLABEL="My Passport" PARTUUID="d714a0e3-6980-46a0-ae12-bcf81c70f056"

/dev/sda1 에 연결된 외장하드를 연결해 놓았다.
마운트된 장치를 unmount시킨 후에 다음과 같은 명령어로 특정 폴더에 마운트 되도록 한다.

1
2
3
$ cd /
$ sudo mkdir external
$ sudo mount -t ntfs /dev/sda1 /external

auto mount 설정

/etc/fstab을 수정한다.

1
/dev/sda1       /external       ntfs    default         0       0

위 내용을 추가하고 재부팅하여 cd /external을 통해 장치가 올바르게 마운트 되었는지 확인한다.

라즈베리파이 고정 ip 설정

라즈베리파이를 사용하면서 랜선에 직접 연결하면 좋겠지만
그렇지 못하고 공유기의 와이파이를 이용하는 경우, 자동으로 할당되는 아이피를 고정시키고 싶을 것이다.

왜냐하면 우리는 공유기의 포트포워딩(Port Forwarding)을 사용할 것이기 때문이다.

라즈베리파이 아이피 고정

iptime 공유기를 사용한다고 가정한다.
라즈베리파이를 재부팅하였을 때, ip가 변동되지 않도록

1
2
3
4
5
6
7
8
9
10
11
12
13
$ sudo vi /etc/network/interfaces

# 해당 부분을 찾아서 다음과 같이 수정한다.
allow-hotplug wlan0
iface wlan0 inet static
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
wpa-ssid wi-fi 이름
wpa-psk wi-fi 비밀번호
address 192.168.0.18
network 192.168.0.0
netmask 255.255.255.0
gateway 192.168.0.1
broadcast 192.168.0.255

재부팅 후에 ifconfig 명령어를 통해 확인한다.

라즈베리파이 ssh 활성화

원격 또는 모니터 없이 라즈베리파이를 제어하고 싶다면, ssh를 활성화해야 한다.

1
$ sudo raspi-config

위 커맨드를 실행한 후에
Advanced Options 메뉴에 들어가서 ssh -> enable

라즈베리파이 설치 (MacOS)

img 파일 다운로드

라즈베리파이는 우분투(Ubuntu) 기반의 raspbian 이라는 OS를 사용한다.
lite버전은 cli만 사용가능한 버전이다.
http://www.raspberrypi.org/downloads

터미널에서 디스크 마운트 확인

1
$ diskutil list

sd카드에 해당하는 장치를 언마운트 한다.

1
$ diskutil unmountDisk /dev/disk4

img 파일이 있는 곳으로 이동 후 다음과 같은 명령어로 sd카드에 img 설치

1
2
$ cd /path/to/img
$ sudo dd bs=1m if=2017-04-10-raspbian-jessie.img of=/dev/rdisk4

ctrl + t 를 눌러 설치 현황을 확인할 수 있다.

완료되면 명령어 커맨드 대기상태가 된다.

pc에서 sd카드를 언마운트한 후에, 라즈베리파이에 삽입하여 나머지 설치과정을 진행한다.

참조 : http://forteleaf.blogspot.kr/2016/06/3-via-osx.html
다른 방법 : http://giyatto.tistory.com/28 - 인스톨러 활용