웹 애플리케이션 만들기 실습

MySQL

본 수업은 웹 애플리케이션 만들기 수업으로 대체 되었고, 2015년 6월 이후에 폐지됩니다. 개편된 수업에서 뵙겠습니다.http://opentutorials.org/course/1688

데이터베이스란?

데이터베이스란 데이터의 저장, 출력, 삭제, 수정과 같은 작업을 쉽고 안전하게 할 수 있도록 도와주는 시스템이다. 이해를 돕기 위해서 유사 데이터베이스인 엑셀을 보자.

좋아하는 영화

그림처럼 엑셀은 데이터를 표의 형식으로 저장해서 정보의 종류에 따라서 분류한다. 이런 특성 덕분에 '제목'을 기준으로 오름차순 정렬을 한다든지, 감독이 피터위어인 작품을 검색하는 것이 가능하다. 데이터베이스는 데이터를 표(table)라는 형식으로 저장해서 정렬, 검색, 그룹핑등을 할 수 있다. 엑셀과 다른 점은 이런 작업을 프로그래밍적으로 할 수 있다는 점이다. 그렇다면 '프로그래밍적'의 의미가 무엇일까?

SQL

지금까지 배운 HTML, CSS, JavaScript 처럼 데이터베이스도 SQL이라는 언어가 있다. 이 언어를 이용하면 데이터를 생성, 수정, 삭제, 열람을 할 수 있다. 예를 들어 위의 엑셀문서에서 감독이 오시이 마모루인 영화만 가져오고 싶다면 아래와 같이하면 된다.

SELECT * FROM `좋아하는 영화` WHERE 감독 = '오시이 마모루';

이 명령을 실행하면 엑셀 기준으로 아래와 같이 출력될 것이다.

패트레이버의 길이가 2:10이 아니고 2:20이라면 이 영화의 식별자인 '번호'를 기준으로 길이를 변경할 수 있다. 이를 위한 SQL문을 보자.

UPDATE `좋아하는 영화` SET 길이=2:20 WHERE 번호 = 4;

'프로그래밍적'으로 데이터를 관리한다는 말의 의미가 이해되는가? 명령을 입력해서 데이터를 조작하는 것이 불편하게 느껴질 수도 있다. 하지만, 앞으로 배울 PHP와 같은 언어를 이용하면 웹을 이용해서 데이터베이스에 제어할 수 있는데 이때 SQL이 사용된다. 또 데이터베이스 관리 소프트웨어를 사용하면 엑셀처럼 GUI(그래픽 유저 인터페이스) 환경에서 데이터를 조작할 수 있기 때문에 SQL 문법에 정통하지 않아도 데이터베이스를 사용하는 데는 큰 지장이 없다. 꼭 알아둬야 하는 SQL문은 딱 4줄이다. 필자는 이마저도 근 10년째 헷갈려서 자주 찾아본다. 헷갈리는 것은 습관이다. 겁먹지 말자.

  • 조회 - SELECT
  • 수정 - UPDATE
  • 삭제 - DELETE
  • 추가 - INSERT

스키마(scheme)

스키마란 데이터의 구조를 의미한다. 말이 어렵게 느껴질 수도 있는데 사실 별거 아니다. 이를테면 위의 예제를 가만 보면 정보의 구조가 있다. 번호, 제목, 길이, 감독이라는 정보로 구성되어 있고, 번호는 숫자, 제목과 감독은 문자, 그리고 길이는 시간이라는 포맷을 가지고 있다. 그리고 번호는 다른 항목과 중복되지 않는 유일무일한 식별자다. 이것이 정보의 구조다. 데이터베이스를 사용하려면 이 구조를 먼저 만들고, 그 구조에 맞게 데이터를 등록해야 한다. 정보의 구조를 설계하는 행위를 데이터 모델링이라고 부르는데, 이것은 개발의 편의, 유지보수의 복잡도, 시스템의 성능에 결정적인 영향을 미친다.

위의 예제와 같은 정보를 만드는 SQL 문은 아래와 같다.

CREATE TABLE `좋아하는 영화` (
    `번호`  int NOT NULL AUTO_INCREMENT ,
    `제목`  varchar(255) NOT NULL ,
    `길이`  time NOT NULL ,
    `감독`  varchar(20) NOT NULL ,
    PRIMARY KEY (`번호`)
)

TABLE은 표라는 뜻인데 데이터베이스는 표에 데이터를 담는다. CREATE TABLE `좋아하는 영화`는 '좋아하는 영화'라는 이름의 테이블을 생성하라는 명령이다. 괄호 다음에는 열(column, 예제에서는 번호, 제목, 길이등)의 정보가 어떤 형식인가를 지정하는데, 이를테면 '번호' 뒤의 'int'는 숫자 데이터라는 의미고, 'NOT NULL'은 꼭 데이터를 입력해야 한다는 의미다. PRIMARY KEY (`번호`)는 번호의 값이 중복되면 안 되는 유일무이한 식별자여야 한다는 의미다. 이 식별자를 기준으로 정보를 수정하고 삭제한다. 이 부분은 뒤에서 다시 한번 살펴볼 것이다.

데이터베이스에 대한 자세한 내용은 생활코딩 데이터베이스편을 참고 한다. http://opentutorials.org/course/195

MySQL

MySQL은 데이터베이스라는 장르에 속하는 제품으로 현재 ORACLE에서 무료/오픈소스로 제공되고 있다. 가장 많이 사용되는 고성능 데이터베이스 중의 하나다. 우리는 '개발 > 서버구축' 시간에 MySQL을 이미 설치했다. 이제 사용하는 방법에 대해서 알아볼 것이다.

opentutorials 모델링 실습

지금까지는 생활코딩 플랫폼인 opentutorials의 겉모습을 만들었다. 이제는 시스템의 내면을 설계할 차례다. 모델링을 시작하려면 우선 만들고자 하는 것이 어떤 정보들로 구성되어 있는지를 분석하는 것이 우선이다. 먼저 우리가 만들려고 하는 웹서비스의 UI를 보자.

이 중에 데이터베이스화할 수 있는 데이터를 뽑아보면 아래와 같다.

  1. 수업 제목 : 문자, 앞으로 수업을 토픽('topic')라고 부르겠다.


     
  2. 수업 내용 : 문자

위의 정보를 바탕으로 토픽을 테이블로 만들어보면 아래와 같다.

참고 opentutorials.org에서는 하나의 글을 토픽(topic)라고 부르고, 토픽의 집합인 수업을 모듈(module)라고 부른다. 또 모듈을 묶어서 만든 메뉴를 코스(course)라고 부른다.

이름 데이터베이스 내에서 사용할 이름 데이터 타입 데이터 타입 설명
번호 id int 숫자,
토픽(수업) 제목 title varchar(255) 최대 255자인 문자
토픽 내용 description text 길이 제한 없이 문자 사용 가능
토픽 생성시간 created datetime 2012-04-04 06:16:51 와 같은 형식으로 시간을 표현

Table, Row, Column, Field의 관계

실제로 데이터베이스 스키마를 생성하기 전에 알아둘 것이 있다. 데이터베이스는 데이터를 표(table)의 형식으로 저장한다. 아래 그림을 보자.

Row는 행을 의미하고 Column은 열, Field는 행과 열이 교차하는 칸을 의미한다. 열은 토픽의 제목, 토픽내용, 토픽 생성시간과 같이 데이터의 종류별로 그룹핑되고, 행은 서로 연관된 데이터들의 그룹을 의미한다. 아래의 그림을 보자.

열은 번호, 제목, 길이, 감독처럼 데이터의 종류에 따라서 그룹핑되고, 행은 '1, 공각기동대, 1:30, 오시이 마모루'처럼 연관된 데이터끼리 그룹핑된다. 열과 행의 관계에 대해서 잘 따져보자.

접속

이제 실제로 작업을 시작해보자. 우선 터미널을 실행한 후에 아래와 같이 입력한다.

mysql -uroot -p 

비밀번호를 입력하면 설치과정에서 등록했던 비밀번호를 입력한다.

 

참고 이 명령은 MySQL Monitor라는 프로그램을 실행한다. 이 프로그램은 MySQL에서 기본적으로 제공하는 데이터베이스 클라이언트인데, 이 프로그램을 이용해서 MySQL 서버를 제어할 수 있다. 이 프로그램 자체가 MySQL이라고 착각하기 쉽지만, 실제로 데이터가 저장되는 곳은 서버고 서버에 접속해서 데이터를 제어하는 것은 클라이언트다. MySQL Monitor 외에 많은 클라이언트가 있고 이런 클라이언트를 사용하면 엑셀처럼 편리하게 데이터베이스를 제어할 수 있다.  http://opentutorials.org/course/195/1413

참고 수업의 코드를 복사&붙여넣기 할 때는 우분투에서 마우스 오른쪽 클릭을 한 후에 '붙여넣기' 혹은 'paste' 항목을 선택하면 된다.

 

데이터베이스 생성

로그인에 성공하면 이제 데이터베이스를 생성한다. 여기서 의미하는 '데이터베이스'는 데이터를 저장하는 시스템을 통칭하는 용어로서 데이터베이스가 아니라 연관된 테이블들을 그룹핑하는 단위다. 비유하자면 테이블이 파일이라면 데이터베이스는 디렉터리라고 할 수 있다. 아래의 SQL문을 이용해서 opentutorials라는 이름의 데이터베이스를 생성할 수 있다.

CREATE DATABASE opentutorials CHARACTER SET utf8 COLLATE utf8_general_ci;

아래와 같은 화면이 보인다면 데이터베이스의 생성에 성공한 것이다.

방금 생성한 데이터베이스에 들어가자. 아래 명령을 실행하면 opentutorials 디렉터리로 들어가게 된다. 그 상태에서 명령을 내리면 opentutorials 디렉터리에 있는 테이블들을 대상으로 작업이 수행된다. cd 명령으로 디렉터리에 들어가는 것과 같은 원리다.

use opentutorials;

테이블 생성

아래는 지금까지의 상황을 종합해서 만든 스키마다. 복사&붙여넣기 해서 실행하자.

CREATE TABLE topic (
    id  int(11) NOT NULL AUTO_INCREMENT,
    title  varchar(255) NOT NULL ,
    description  text NULL ,
    created  datetime NOT NULL ,
    PRIMARY KEY (id)
);
위의 내용을 선택할 때 더블클릭을 사용하지 말자. 몇가지 이유로 붙여넣기를 했을 때 오류가 발생할 것이다. 코드를 드래그해서 선택한 다음에 붙여넣기 한다. 

각 구문의 의미는 아래와 같다.

  • CREATE TABLE `topic` (
    topic 테이블을 생성한다.
  • `id`  int(11) NOT NULL AUTO_INCREMENT ,
    id 컬럼은 숫자형이고 조회시 11자리까지 보여준다. 입력필수(값을 반듯이 입력해야 한다). 값을 특정하지 않으면 자동으로 가장 큰 값이 생성된다. (중복방지)
  • `title`  varchar(255) NOT NULL ,
    title 칼럼은 가변형 텍스트이고 최대 255자리까지 입력된다. 입력필수.
  • `description`  text NULL ,
    description은 길이 제한이 없는 텍스트 형이고 입력은 옵션이다.
  • `created`  datetime NOT NULL ,
    created은 2012-04-04 06:16:51와 같은 시간의 형식이 오고, 입력필수다.
  • PRIMARY KEY (`id`)
    id는 유일무이한 값이어야 한다.
  • );
    ';'는 명령이 끝났다는 것을 알려준다. ';'를 사용하지 않으면 명령의 실행이 유보된다.

 

데이터 입력

topic 테이블을 생성했다. 이제 데이터를 저장할 만반의 준비가 됐다. 아래 명령을 이용해서 빈테이블을 조회해보자.

SELECT * FROM topic;

각 구문의 의미는 아래와 같다.

  • SELECT
    테이블의 데이터를 조회한다. 
  • *
    모든 컬럼에 대한 조회 결과를 보여준다. 만약 일부 결과만을 원한다면 '*' 대신에 'title, description' 으로 변경
  • FROM topic;
    topic 테이블에서 조회한다.

자 이제 데이터를 입력해보자.

INSERT INTO `topic` (title,description,created) VALUES ('JavaScript란', '<h2>\r\n    자바스크립트는</h2>\r\n<ul>\r\n	<li>\r\n		브라우저에서 실행되는 언어</li>\r\n	<li>\r\n		가장 많이 사용되는 언어</li>\r\n	<li>\r\n		주로 html을 프로그래밍적으로 조작하기 위해서 사용됨</li>\r\n</ul>\r\n<h2>\r\n	예제</h2>\r\n<ul>\r\n	<li>\r\n		자바스크립트는 3가지 방식으로 사용됨</li>\r\n	<li>\r\n		외부의 파일을 로드</li>\r\n	<li>\r\n		&lt;script&gt;태그 사이에 기술</li>\r\n	<li>\r\n		태그에 직접 기술</li>\r\n</ul>\r\n<h2>\r\n	참고링크</h2>\r\n<ul>\r\n	<li>\r\n		<a href=\"http://www.maroon.pe.kr/webmaster/java/java_study.html\" target=\"_blank\">스크립트 세상</a></li>\r\n	<li>	\r\n</ul>\r\n', now());
INSERT INTO `topic` (title,description,created) VALUES ('변수와 상수', '<p>\r\n	변수란</p>\r\n<ul>\r\n	<li>\r\n		변하는 값</li>\r\n	<li>\r\n		x = 10 일 때 왼쪽항인 x는 오른쪽 항인 10에 따라 다른 값이 지정된다.</li>\r\n</ul>\r\n<p>\r\n	상수란</p>\r\n<ul>\r\n	<li>\r\n		변하지 않는 값</li>\r\n	<li>\r\n		x = 10 일 때 오른쪽항인 10이 상수가 된다.</li>\r\n</ul>\r\n<pre class=\"brush: xml\">\r\n&lt;script type=&quot;text/javascript&quot;&gt;\r\n&nbsp;&nbsp;&nbsp; // x의 값이 오른쪽 항에 따라서 변한다.\r\n&nbsp;&nbsp;&nbsp; // x가 변수라는 명시적인 의미\r\n&nbsp;&nbsp;&nbsp; var x = 10;\r\n&nbsp;&nbsp;&nbsp; alert(x);\r\n&nbsp;&nbsp;&nbsp; var x = 20;\r\n&nbsp;&nbsp;&nbsp; alert(x);\r\n&lt;/script&gt;</pre>\r\n<p>\r\n	&nbsp;</p>\r\n', now());
INSERT INTO `topic` (title,description,created) VALUES ('연산자', '<p>\r\n	연산에 사용되는 기호들. (y = 5 일 때)</p>\r\n<table class=\"table\">\r\n	<tbody>\r\n		<tr>\r\n			<th align=\"left\" width=\"15%\">\r\n				Operator</th>\r\n			<th align=\"left\" width=\"40%\">\r\n				Description</th>\r\n			<th align=\"left\" width=\"25%\">\r\n				Example</th>\r\n			<th align=\"left\" width=\"20%\">\r\n				Result</th>\r\n		</tr>\r\n		<tr>\r\n			<td valign=\"top\">\r\n				+</td>\r\n			<td valign=\"top\">\r\n				더하기</td>\r\n			<td valign=\"top\">\r\n				x=y+2</td>\r\n			<td valign=\"top\">\r\n				x=7</td>\r\n		</tr>\r\n		<tr>\r\n			<td valign=\"top\">\r\n				-</td>\r\n			<td valign=\"top\">\r\n				빼기</td>\r\n			<td valign=\"top\">\r\n				x=y-2</td>\r\n			<td valign=\"top\">\r\n				x=3</td>\r\n		</tr>\r\n	</tbody>\r\n</table>\r\n', now());
INSERT INTO `topic` (title,description,created) VALUES ('JSON', '<h2>JSON이란?</h2>\r\n\r\n<p>서로 다른 언어들간에 데이터를 주고 받는 여러 방법이 있다. 대표적인 것이 XML인데, XML은 문법이 복잡하고, 엄격한 표현규칙으로 인해서 json 대비 데이터의 용량이 커진다는 단점이 있다.</p>\r\n\r\n<p>JSON은 경량의 데이터 교환 형식으로 JavaScript에서 숫자와 배열등을 만드는 형식을 차용해서 이것을 다른 언어에서도 사용할 수 있도록 한 텍스트 형식이다.&nbsp;</p>\r\n\r\n<p>아래 예제는 위의 예제에서 전송한 데이터를 받아서 몇가지 부가정보를 추가해서 json으로 인코드한 후에 다시 반환하는 PHP 코드다.&nbsp;</p>\r\n\r\n<p>json.php - (<a href=\"https://github.com/egoing/codingeverybody_javascript/blob/master/JSON/json.php\" target=\"_blank\">github</a>)</p>\r\n\r\n<pre class=\"brush: php\">\r\n&lt;?php\r\n$userinfo = json_decode($_GET[&#39;data&#39;]);\r\n$userinfo-&gt;address = &#39;seoul&#39;;\r\n$userinfo-&gt;phonenumber = &#39;01023456789&#39;;\r\necho json_encode($userinfo);\r\n?&gt;</pre>\r\n\r\n<h2>json의 형식</h2>\r\n\r\n<h3>object</h3>\r\n\r\n<p>객체는 아래와 같은 문법을 가지고 있다.</p>\r\n\r\n<p>예제</p>\r\n\r\n<p>{&quot;userid&quot;:&quot;egoing&quot;,&quot;pwd&quot;:&quot;12345567&quot;}</p>\r\n\r\n<p><img height=\"113\" src=\"http://www.json.org/object.gif\" width=\"598\" /></p>\r\n\r\n<h3>array</h3>\r\n\r\n<p>배열은 아래와 같은 문법을 가지고 있다.&nbsp;</p>\r\n\r\n<p>예제</p>\r\n\r\n<p>[1,2,3,4]</p>\r\n\r\n<p><img height=\"113\" src=\"http://www.json.org/array.gif\" style=\"line-height: 1.8em;\" width=\"598\" /></p>\r\n\r\n<h3>Value</h3>\r\n\r\n<p>위에서 사용된 Value는 값을 의미하는데&nbsp;큰 따옴표로 묶인 문자나 숫자, 불린 값이 사용된다.</p>\r\n\r\n<p>예제</p>\r\n\r\n<ul>\r\n	<li>문자 : &quot;헬로우 월드&quot;</li>\r\n	<li>숫자 : 1</li>\r\n	<li>불린 : true</li>\r\n</ul>\r\n\r\n<p><img height=\"278\" src=\"http://www.json.org/value.gif\" width=\"598\" /></p>\r\n', now());

각 구문의 의미는 아래와 같다.

  • INSERT
    데이터를 입력한다.
  • INTO topic
    topic 테이블에 데이터를 입력한다.
  • (title, description, created)
    뒤에 따라오는 VALUES의 값이 title, description, created 순이라는 것을 의미한다. 스키마와는 다르게 id가 없는 것은 스키마에서 id 값으로 AUTO_INCREMENT를 지정했는데, 이 특성이 부여된 컬럼은 자동으로 가장 큰 값이 추가되기 때문에 INSERT 명령이 실행될 때마다 제일 큰 값이 부여된다. 덕분에 데이터가 중복되는 문제를 방지 할 수 있다.
  • VALUES ('...', '....', '....')

데이터가 잘 입력 됐는지 확인해보자. '\G'은 컬럼의 수가 많을 때 화면이 깨지는 문제를 우회하기 위한 방법으로 칼럼이 수직으로 출력된다.

SELECT * FROM topic\G

결과는 아래와 같다.

우리가 만들고 있는 opentutorials 서비스의 특징은 최신글이 나중에 오고, 오래된 글이 처음으로 정렬되는 특성을 가지고 있다. 이를 위해서는 데이터를 조회할 때 정렬 방법을 지정해야 하는데 아래와 같이 한다.

SELECT * FROM topic ORDER BY Id ASC;

ORDER BY id ASC 는 id 칼럼을 기준으로 작은 값이 먼저 출력되도록 정렬한다는 의미다. 반대로 정렬하고 싶으면 ASC 대신에 DESC를 사용하면 된다.

정리

여기까지다. 만들려는 서비스에 맞게 테이블을 만들고, 이 테이블에 데이터를 저장한 후에 이것을 필요에 따라 조회하면 원하는 정보를 얻을 수 있다. 대부분의 웹서비스들이 이렇게 정보를 저장, 수정, 삭제, 조회하는 작업을 웹상에서 수행하는 것을 목적으로 하기 때문에 웹서비스에 있어서 데이터베이스는 심장이라고 할 수 있다. 다음 시간에는 이 데이터베이스를 웹을 통해서 조작하는 방법에 대해서 알아볼 것이다. 고지가 코앞이다.

댓글

본 수업은 웹 애플리케이션 만들기 수업으로 대체 되었습니다. 개편된 수업에서 뵙겠습니다. 본 수업은 2015년 6월 이후에 폐지됩니다. http://opentutorials.org/course/1688

 

궁금하신 점은 각 강의의 댓글로 문의해주세요. 답변이 없는 것은 운영자가 못 봤거나 모르는 것입니다. 생활코딩 커뮤니티에 질문하면 더 많은 분의 도움을 받을 수 있습니다. 그리고 문제를 해결했다면 본문의 댓글로 공유해주시면 다른 분에게 큰 도움이 됩니다. 원하는 답변을 얻는 것은 확률의 문제입니다. 질문의 품질이 높으면 그 확률도 올라갑니다. 질문자의 상황을 더 잘 전달하기 위해서 screenr.com이나 이미지 캡처의 이용을 권합니다.

 

댓글 본문
버전 관리
egoing
현재 버전
선택 버전
graphittie 자세히 보기