2013년 12월 24일 화요일

MySQL 기본 사용법 및 예제

MySql에 대한 기본 사용방법 및 명령어에 대해 알아본다.

- 목차 -

1. Mysql 기본 사용법
2. 데이터베이스 생성 및 삭제
3. 새로 생성한 데이터베이스 등록하기
4.  Mysql 사용자등록
5. 테이블 생성 및 삭제
6. 테이블속성 및 구조변경법
7. 데이터 입력하기 (INSERT)
8. 데이터 검색 (SELECT)
9. 데이터 수정하기(UPDATE)
10. 데이터 삭제하기(DELETE)
11. 새로운 사용자 등록
12. 일반사용자 권한설정(보안사항)
13 .Mysql root 암호 변경하기
14. root 패스워드를 잊어버렸을 때는 어떻게?
15. 특정 테이블의 구조보기
16. 현재 상태 보기(STATUS)



1. Mysql 기본 사용법


● Mysql 데이터베이스 접속하기

# mysql -u 사용자명 -p dbname

설치 직후에는 root 사용자에 비밀번호가 없으므로 다음과 같이 접속하여 MySQL을 관리할 수 있다.

# mysql -u root mysql


● mysql 관리자 root 패스워드 설정하기

MySQL을 설치한 직후에는 root 계정에 암호가 지정되어 있지 않다.
다음 세가지 방법으로 비밀번호를 변경 할 수 있다.

 ▶ mysqladmin이용
# mysqladmin -u root password 새비밀번호

 ▶ update문 이용
# mysql -u root mysql

mysql> UPDATE user SET password=password('새비밀번호') WHERE user='root';
mysql> FLUSH PRIVILEGES;

mysql> update user set password = password('shcm0816') where user = ' root';

일단 root 비밀번호가 설정된 상태에서는 
mysql이나 mysqladmin 명령을 실행할 때 -p 옵션을 붙여주고 
기존 비밀번호를 입력해야만 한다.

 ▶ Set Password 이용
SET PASSWORD FOR root=password('새비밀번호');


 ▶ 빠져나간후 데이터베이스를 재시작
# mysqladmin -u root reload

 ▶ 패스워드 입력
# mysql -u root -p mysql



● 사용자 추가/삭제

mysql> GRANT ALL PRIVILEGES ON dbname.* TO username@localhost IDENTIFIED BY 'password';

username 이라는 사용자를 password라는 비밀번호를 갖도록 하여 추가한다. 
username은 dbname이라는 데이타베이스에 대해 모든 권한을 가지고 있다.
username 사용자는 로컬 호스트에서만 접속할 수 있다. 

 ▶ 다른 호스트에서 접속하려면
mysql> GRANT ALL PRIVILEGES ON dbname.* TO username@'%' IDENTIFIED BY 'password';

위를 또한 번 실행한다. '%'에서 홑따옴표를 주의한다.

 ※ 추가
'%'를 호스트네임으로 지정해도 모든 호스트에서 접속할 수 없었다. 
각 호스트별로 다 지정해야 했다.

 ▶ 불필요한 사용자 삭제는
mysql> DLETE FROM user WHERE user='username';
mysql> FLUSH PRIVILEGES;





2. 데이터베이스 생성 및 삭제

● 데이터베이스 생성

① 첫번째 방법
# mysql -u root -p mysqlll
    msyql> create database TESTDB;
    msyql> show databases;

② 두번째 방법
# ./mysqladmin -u root -p create testdb2
Enter password:
# ./mysql -u root -p mysql
Enter passwor

현재 존재하는 데이터베이스 목록을 보여준다.
cd /
msyql> show databases;
msyql> exit
Bye
#

특정 데이타베이스를 사용하겠다고 선언한다.
mysql> USE dbname;


● 데이타 베이스 삭제

# ./mysqladmin -u root -p drop testdb2
Enter password:

-- mysql> DROP DATABASE [IF EXISTS] dbname;
mysql> drop database testdb2

IF EXISTS 옵션은 비록 데이타베이스가 없더라도 오류를 발생시키지 말라는 의미이다.

# ./mysql -u root -p mysql
msyql> show databases;
msyql> desc user =>동일한 결과



3. 새로 생성한 데이터베이스 등록하기

데이터베이스를 새로 생성한 후에는 mysql 이라는 관리용 데이터베이스에 등록한다.
mysql 이라는 데이터베이스의 db라는 테이블에 TESTDB를 등록한 것

msyql> insert into db  values('%','TESTDB','root','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
msyql> select host, db, user from db;



4.  Mysql 사용자등록(데이터베이스 소유자)

 ▶ mysql 을 사용할 사용자는 반드시 user 라는 테이블에 등록을 해줘야함
msyql> insert into user (host, user, password) values('localhost', 'sspark', password('shcm0816'));

 ▶ 정상적인 등록여부 확인
msyql> select host, user, password from user; 

 ▶ sspark이라는 사용자로 mysql 데이터베이스로 접속
msyql> mysql -u sspark -p
Enter password:

 ▶ 새로운 데이터베이스를 생성하거나 새로운 사용자를 생성한 후에는 
    반드시 reload를 해줘야함
# mysqladmin -u root -p reload
Enter password:




5. 테이블 생성 및 삭제

 ▶ 테이블 생성
msyql> create table testtable (
         ->uid mediumint(4) unsigned DEFAULT '0' NOT NULL auto_increment,
         -> name varchar(12) DEFAULT "" NOT NULL,
         -> email varchar (20) DEFAULT "" NOT NULL,
         -> PRIMARY KEY (uid)
         -> );
Query OK, 0 rows affected (0.00 sec)

 ▶ 현재 데이터베이스의 테이블 목록 확인
msyql>show tables;

 ▶ 필드 구조가 정의한 필드구조로 생성되었는지 확인
msyql> desc testtable;

 ▶ 테이블 삭제
msyql> drop table testtable;
mysql> show tables;



6. 테이블속성 및 구조변경법

 ▶ 테이블 구조 확인
mysql> EXPLAIN tablesname;
혹은
mysql> DESCRIBE tablename;

 ▶ 기존 테이블에 필드 추가하기
ALTER TABLE 테이블명 CHANGE[COLUMN] 필드명 필드타입

mysql> er table testtable add column homepage varchar(30);
mysql> desc testtable;

 ▶ 기존에 필드 속성 변경하기
ALTER TABLE 테이블명 CHANGE[COLUMN] 기존필드명 새필드명 필드타입

mysql> er table testtable change column homepage home varchar(50);

 ▶ 테이블 이름 변경
mysql> RENAME TABLE tablename1 TO tablename2[, tablename3 TO tablename4];

 ▶ 기존에 필드 삭제
ALTER TABLE 테이블명 DROP [COLUMN] 필드명

mysql> er table testtable drop column home;
mysql> desc testtable;

 ▶ 기존의 테이블삭제하기
mysql> create table sampletable
mysql> show tables;
mysql> drop table sampletable;
mysql> show tables;



7. 데이터 입력하기 (INSERT)

INSERT INTO tablename VALUES(값1, 값2, ...);

mysql> insert into testtable (uid, name, email) 
mysql> values (', 'parksungsoo', sspark09@soback.kornet.net'" target=_blank>'sspark09@soback.kornet.net');

 ※ 주의: uid라는 필드는 auto_increment 라는 속성으로 생성했기 때문에 
이 속성을 가진 필드들은 실제로 데이터값을 주지 않아도 자동적으로 1씩 증가.

 ▶ 삽입할 필드는 생략가능
mysql> insert into testtable values(','sontaesoo','shutterbug@orgio.net');


특정 필드에만 데이터를 입력할 경우에는 
입력할 필드이름만을 나열하고 그에 해당하는 데이터를 입력한다.

mysql> insert into testtable (uid,name) values(','junwooki');

 ▶ 정상적으로 입력되었는지 확인
mysql> select * from testtable;




8. 데이터 검색 (SELECT)

SELECT col1, col2, ... FROM tablename;

 ▶ 테이블의 모든 테이터를 검색
mysql> select * from testtable;

컬럼명을 *로 하면 모든 컬럼 의미.

 ▶ uid와 name 필드만을 조회
mysql> select uid, name from testtable;

 ▶ where문을 사용하여 특정 조건에 맞는 데이터만을 검색
mysql> select * from testtable where name = "sontaesoo";

 ▶ 출력 결과 레코드의 중복제거하기(DISTINCT)
SELECT DISTINCT sex FROM testtable;

 ▶ 'soo'라는 문자가 포함된 데이터를 모두 검색 (LIKE)
SELECT name FROM testtable WHERE name LIKE '%soo%'

mysql> select name from testtable where name LIKE '%soo%';

 ▶ 특정한  한 문자로 시작하는 데이터만을 출력
SELECT name FROM testable WHERE name LIKE 'park%'

mysql> select name from testtable where name LIKE 'park%';

 ▶ 특정 필드에 데이터가 NULL 인 경우
SELECT uid, name FROM testtable WHERE age IS NULL

mysql> select uid, name from testtable where age IS NULL;

 ▶ 특정 필드의 데이터가 NULL이 아닌 경우
SELECT uid, name FROM testtable WHERE age IS NULL

mysql> select uid, name from testtable where age IS NOT NULL;

 ▶ WHERE 조건문이 여러개 일 경우 (AND/OR) 
mysql> SELECT name, uid, email FROM testtable WHERE savem > 5000 AND sex='M';

 ▶ 결과데이터를 정렬하기 (ORDER BY)
mysql> SELECT name, uid, savem FROM testtable WHERE savem >= 5000 ORDER BY savem DESC;

DESC는 내림차순 ASC는 오름차순.

 ▶ 총 개수 구하기 (COUNT())
mysql> SELECT count(*) FROM testtable WHERE sex='M';

 ▶ 평균 구하기 (AVG())
mysql> SELECT avg(savem) FROM testtable WHERE sex='M';

 ▶ 컬럼의 이름을 바꿔서 출력.
mysql> SELECT col1 AS '성명', col2 AS '국어점수' FROM grade;
mysql> SELECT col1, korean + math + english AS '총점' FROM tablename ORDER BY '총점' ASC;

 ▶ 결과중 처음부터 10개만 가져오기
mysql> SELECT * FROM grade LIMIT 10;

 ▶ 결과중 100번째부터 10개만 가져오기.(첫번째 레코드는 0번 부터 시작한다.)
mysql> SELECT * FROM grade LIMIT 100, 10;



9. 데이터 수정하기(UPDATE)

UPDATE 테이블명 
SET 필드명=필드값 또는 산술식 {, 필드명 = 필드값 또는 산술식}
[WHERE 검색조건]

mysql> select * from testtable;

 ▶ uid 4 번의 데이터에 name 값과 email을 입력해 봄
mysql> update testtable set name = 'junyangmi' where age = 23;
mysql> update testtable set email = jym@superuser.co.kr'" target=_blank>'jym@superuser.co.kr' where age = 23;
mysql> select * from testtable;

 ▶ uid 1 인 사람 (parksungsoo)의 나이를 25살로 수정
mysql> update testtable set age= 25 where uid =1;

 ▶ uid 2인 사람의 나이를 30살로 수정
mysql> update testtable set age = 30 where uid =2;
mysql> update testtable set age = 41 where uid=3;

 ▶ 한해가 지났으므로 모든 사람의 나이를 한 살씩 증가
mysql> update testtable set age = age + 1;
mysql> select * from testtable;



10. 데이터 삭제하기(DELETE)

DELETE FROM 테이블명 [WHERE 검색조건]

mysql> select * from testtable;
mysql> delete from testtable where uid = 3;



11. 새로운 사용자 등록

 ▶ Mysql 에 root로 접속
./mysql -u root -p

 ▶ Mysql DB 선택
mysql> use mysql;
mysql> show tables;

 ▶ 새로운 DB 생성
mysql> create database xlare;

 ▶ user 테이블에 입력 
(user 라는 테이블에 새로운 사용자의 계정이름과 권한설정을 할 차례)
호스팅사용자에 대한 설정 user테이블에 현재 사용장0ㅔ 대한 권한들을 모두 'N'로 설정
mysql> insert into user valuses('localhost', 'xlare', password('123'),'Y','Y','Y','Y','Y','N','N','N','N','N','N','N','N','N');

 ▶ user  테이블에 입력확인
mysql> select * from user where user = 'xlare' ;

 ▶ db 테이블에 입력
mysql> insert into db values('localhost', 'xlare', 'xlare', 'Y','Y','Y','Y','Y','N','N','N','N','N',);

 ▶ db 테이블에 입력 확인
mysql> select * from db where db = 'xlare';

새로운 설정을 바로 적용키위해 mysqladmin 이라는 관리자명령어로 mysql을 재시작한다.
reload를 해주지 않으면 생성했던 것들이 적용이 되지 않는다

# ./mysqladmin -u root -p reload;




12. 일반사용자 권한설정(보안사항)

#./mysql -u root -p mysql
Enter password:
mysql> show tables;
--------------------
tables in mysql
--------------------
columns_priv
db
func
host
tables_priv
user
----------------------

 ▶ columns_priv 테이블
모든 특정 DB 의 특정 User 에 대한 특정 테이블의 각 컬럼에 대한 
select, insert, update, reference 권한을 설정한다.

mysql> desc columns_priv;

 ▶ db 테이블
db라는 테이블에는 특정 DB에 대한 user들의 여러가지 권한들을 설정하는 테이블

mysql> desc db;

kebia 라는 데이터베이스의 소유자와 그 권한에 대해서 알아보고자 한다.
kebia 라는 데이터베이스의 소유자는 hyung 이라는 mysqkl 사용자이며 
이 hyung 이라는 사용자는 이 kebia 라는 데이터베이스에 대한 각종 권한을 볼수 있다.

mysql> select * from db where db = 'kebia';
| localhost | kebia | hyung | Y  |   - - - - - ...........
------------------------

 ▶ tables_priv테이블
columns_priv 테이블처럼 각 데이터베이스와 사용자 및 그 테이블에 대한 권한을 설정한다.

mysql > desc tables_priv;
---------------------

 ▶ user 테이블
- 새로운 사용자를 생성할 때 이 테이블에 등록한다.
- 특정 사용자에 대한 Mysql에 존재하는 모든 데이터베이스에 대한 권한을 설정한다.
- 특정 사용자의 어떤권한에 대한 사항은 특정 데이터베이스가 아니라 Mysql에 존재하는 모든 데이터베이스에 권한이 주어진다.
- host와 user, password 항목을 제외한 나머지 권한들은 모두 'N'으로 설정한다.
- 특정한 사용자에 대한 특정한 데이터베이스에 대한 권한을 주려면 위에서 보았던 db라는 테이블에서 그 권한설정을 하는것이 안전하다.



13 .Mysql root 암호 변경하기

 ▶ 방법 1
mysqladmin 이라는 명령어 사용
# ./mysqladmin -u root -p password 12345

 ▶ 방법 2
mysql의 set 이란 명령어로 root 암호 변경
# ./mysql -u root -p mysql
mysql> set password for root=passwd('12345678');

 ▶ 방법 3
mysql 데이터베이스로 접속하여 update문을 사용하는 방법
# ./mysql -u root -p mysql
mysql> update user set password=password('12345' where user = 'root';
mysql> flush privileges;

 ▶ flush-privileges
권한 테이블을 재시작한다. 권한 설정을 변경했을경우 반드시 재시작한다.
mysql> flush privileges;



14. root 패스워드를 잊어버렸을 때는 어떻게?

 ▶ 단계 1
실행중인 mysql 종료
# ps -ef | grep mysqld
# killall mysqld

 ▶ 단계 2
grant-table 미사용모드로 mysql시작 및 root로 접속
# .safe_mysqld --skip-grant-tables&

 ▶ 단계 3
update문으로 root사용자 패스워드 변경
mysql> update user set password=password('12345') where user = 'root';
mysql> flush privileges;

 ▶ 단계 4
실행중인 mysql 다시 종료
# ps -ef | grep mysqld
# killall mysqld

 ▶ 단계 5
일반모드로 Mysql 재시작
# ./safe_mysqld&
# ps -ef | grep mysql



15. 특정 테이블의 구조보기(show columns from 테이블)

특정테이블의 필드명 type, 설정값들을 보기 위한 것이다.

 ▶ 특정한 테이블의 칼럼(필드)구조 확인
SHOW COLUMNS FROM tablename;

mysql> show columns form user;

 ▶ 필드 구조가 정의한 필드구조로 생성되었는지 확인
DESC 테이블명

 ▶ 특정 테이블의 인덱스 보기
mysql> show index from user;

 ▶ 데이타베이스의 설정상태 보기(show status)
mysql> show status;
# ./mysqladmin -u root -p status

 ▶ 데이터베이스의 설정환경변수와 값보기(show variables)
mysql> show variables;
# ./mysqladmin -u root -p variables

 ▶ 현재 데이터베이스에 연결된 프로세스들 보기(show processlist)
# ./mysqladmin -u root -p processlist


 ▶ mysql 원격접속 권한 설정

mysql> use mysql
mysql> grant all privileges on *.* to 'oops'@'192.168.5.14'      
mysql> identified by 'passwd' with grant option;

ip대신 % 를 주면 모든 호스트허용!
oops 라는 유저가 모든 권한을 부여받을 수있다. 
단 해당 아이피의 호스트 에서만.
이와 같은 설정은 select host,user from user; 로 확인해볼수 있다.



16. 현재 상태 보기

mysql> status;

--------------
mysql Ver 11.18 Distrib 3.23.58, for pc-linux (i686)

Connection id: 26
Current database: study
Current user: study@localhost
Current pager: stdout
Using outfile: '
Server version: 3.23.58
Protocol version: 10
Connection: Localhost via UNIX socket
Client characterset: latin1
Server characterset: euc_kr
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 2 hours 9 min 59 sec

Threads: 1 Questions: 160 Slow queries: 0 Opens: 28 Flush tables: 1
Open tables: 1 Queries per second avg: 0.021
--------------

VirtualBox 복제

1. MAC 주소 수정
  •  vi /etc/sysconfig/network-script/ifcfg-eth0
  • 복제한 VirtualBox MAC 주소로 수정
2. 기존 설정파일 삭제
  • rm /etc/udev/rules.d/70-persistent-net.rules
  • rm /lib/udev/write_net_rules

2013년 12월 14일 토요일

OOP(Object Oriented Programming)

OOP의 개념과 성장과정

현재 OOP를 지원하는 언어는 여러 가지가 있으나, 가장 대표적인 것으로는 C++  JAVA, 그리고 4GL로 불리는 Perl, Tcl/Tk가 있다. 그 중에서도 Windows를 운영체제로 사용하는 로컬 머신의 애플리케이션의 개발에는 C++가 독보적으로 많이 쓰이고 있다.
C++는 그 언어를 설계할 때부터 OOP를 염두에 두고 만들었으며, 과거 OOP 언어들의 장점들은 모으고 단점들은 제거하거나 수정, 보완하여 흡수시킨 것이라고 할 수 있다.


OOP의 개념은 비교적 오래 전부터 제창되었으며, 당시 Pascal C로 대표되는 구조와 언어의 시대에서부터 그 명맥을 유지해 왔다. 최초의 OOP 언어는 1967년의 Simula67에서부터 시작된다. 그 다음 1980 Smalltalk-80이 나왔는데, Simula67은 당시 Fortran에 밀려서 프로그래머들에게는 눈에 띄지도 않았고 단지 대학이나 연구기관에서 OOP를 연구할 목적으로 주로 사용했다. 하지만 Smalltalk의 경우에는 생각보다 많은 사람들이 사용하였고, 지금도 기억하고 있는 사람들이 많다. 현재 주목 받는 언어인 자바나 C++보다는 Smalltalk에 훨씬 가까운 언어이다. 또한 유명한 여성 프로그래머의 이름을 딴 Ada(에이다)라는 언어도 OOP 언어이다.

이후에는 OOP 전용의 언어보다는 기존 언어에 OOP 개념을 집어넣은 언어들이 많이 나왔다. 인공지능용 언어인 LISP도 지금은 OOP 개념을 집어넣은 언어들이 많이 나왔다. 인공지능용 언어인 LISP도 지금은 OOP 개념을 확장하여 ObjectLISP가 되었으며, 여러분이 잘 아는 Delphi에서 사용하는 언어도 그냥 파스칼이 아니라 ObjectPASCAL이다. 또 포트란도 ObjectFORTRAN이 되었다. 하지만 필자는 뭐니뭐니해도 현재는 C++를 잘 하는 것이 가장 중요한 시점이라고 생각한다.

객체(Object)란 무엇인가?

OOP
의 핵심적인 용어는 '객체'이다. OOP는 쉽게 말하면 모든 것을 객체로 본다는 관점이다. , 윈도우도 객체이고, 버튼도 객체이다. 글자도 객체이고, 사운도도 객체인 것이다. 객체는 우리가 무엇을 생각할 때 '개념적인 최소단위'라고 정의한다. 그러므로 일반적으로 우리가 단어를 붙일 수 있는 것은 거의 대부분 객체라고 할 수 있다. 왜냐하면 언어에서 개념적인 최소단위는, 즉 독립적인 의미를 가지고 있는 최소단위는 음소나 글자 하나가 아닌 '단어'이기 때문이다.

그렇다면 전산학의 입장에서 왜 이러한 객체지향 관점이 주목을 받게 된 것일까? 여러 가지 이유가 있지만, 가장 중요한 것은 뭐니뭐니해도 '소프트웨어의 개발효율과 재사용'에 있다. , 하드웨어를 다뤄본 분들은 알겠지만, 회로를 설계할 때 가능하면 이미 만들어져 있는 chip(IC : Integrated Circuit)을 잘 골라서 군데군데 박아놓고, 주로 그것들의 연결(인터페이스)에 주목을 한다. 왜냐하면 회로를 만들 때마다 RLC(저항, 코일, 콘덴서)와 다이오드(가장 기본적인 반도체 소자)만으로 처음부터 일일이 만들려고 하면, 아무리 실력이 있는 사람이라도 라디오 하나, 전자시계 하나도 제대로 만들어 내기 힘들 뿐만 아니라 만드는 데에도 너무 오래 걸리고, 디버깅도 잘 안 되
는 등 문제가 이만저만하지 않을 것이다.

우리가 IC를 한 번 만들기는 어렵지만, 일단 잘 만들어 놓기만 하면 여기저기에 쓰이듯이, 거대한 프로젝트도 항상 바닥에서부터 장기계획으로 만들려 하지 말고, 이미 만들어져 있는 객체들의 조합으로 만들자는 것이다. 물론, 아직 만들어지지는 않았지만 필요한 객체는 직접 만들어야 한다. 대신, 다음부터는 그 객체를 활용할 수 있다. 물론, 잘 만들었을 경우의 얘기지만 말이다.

우리가 회로를 만들 때 사용하는 IC를 일일이 분해하여 그 내부를 현미경으로 들여다보지 않듯이 객체 역시 안을 보지 말아야 한다. 이것을 정보은폐(Information Hiding)라고 하는데, 비자금을 숨기는 것처럼 사람들에게는 알려할 정보를 은폐시킨다는 것이 아니고, 보일 정보만 보이고 보이면 오히려 개발자를 혼동시킬 정보는 볼 수 없게끔 한다는 것이다. 개발자는 단지 그 객체가 어떤 기능을 가지고 있고, 어떻게 사용할 수 있는지에 대해서만 알면 된다는 것이다. 그런 것들까지 신경 쓰지 않더라도 프로그램을 만들려면 신경써야 할 것이 한 두 개가 아니라는 것이다. 이러한 소프트웨어의 모듈화는 사실 OOP가 처음은 아니며 구조적 프로그래밍에서도 강조하는 것인데,
OOP
는 아예 언어에서 이러한 것들을 지원하고 제한하여서 표준을 유지한다는 것이 차이점 중의 하나이다.

컴퓨터에 있어서의 객체는 크게 두 가지가 있다. 기본객체(primitive object)와 복합객체(complex object)이다. 객체지향의 관점에서는 정수(integer)나 실수(float)도 객체이다. 어떤 것이 객체인지의 여부는 그것이 데이터와 그것에 작용하는 연산이 함께 있으면 독립적인 객체이다. 정수(integer)의 경우에도 정수를 저장하기 위한 4바이트의 메모리와 그것에 작용을 하는 가감승제 등의 연산이 있기 때문에 객체이다. 정수나 실수와 같이 소프트웨어의 기본이 되는 객체들을 기본객체(Primitve Object)라 한다면 이러한 원시객체들을 구성요소로 하여 만들어진 보다 복잡한 객체들을 복합객체(complex object)라고 부른다.

예를 들어 복소수의 경우에는 기존의 C 언어에 없었던 데이터형이므로 복합객체(complex object)이다. 이것의 멤버 데이터는 실수부(real part)와 허수부(imaginary part)의 숫자이며 멤버함수는 복소수가 할 수 있는 연산이다. 복합객체를 발전시키면 객체를 사람의 일반적인 사고방식에 가깝게 개념적으로 설계할 수 있게 된다. 이것이 OOP의 중요한 특징 중의 하나인 추상 자료형(abstract data type)인 것이다. 예를 들어 윈도우라는 객체가 있으면, 이 객체가 구체적으로 어떻게 만들어지고 어떤 방식으로 동작하는가를 전산학적인 관점에서 일일이 검토하는 것이 아니라, 마치 윈도우가 우리의 실세계의 객체인 것처럼, 우리는 단지 윈도우 객체에게 '열려라', '닫혀라' 등의 우리 식의 메시지를 보내면 메시지를 받은 윈도우 객체는 '알아서' 그 동작을 하는 것이다.

객체들끼리는 크게 두 가지의 관계성이 있는데, 그러한 관계들로 인하여 계층적 구조를 형성하고 있다. 관계성 중의 하나는 IS_A 관계성인데, 이것은 '사자 is a 동물', '호랑이 is a 동물'과 같은 관계성을 나타내며 동물이라는 클래스는 사자와 호랑이의 공통 부모 클래스로서 사자와 호랑이에게 공통적으로 있는 성질을 가지고 있다. 이때 사자 클래스와 호랑이 클래스는 동물 클래스가 가지고 있는 모든 기능을 물려받아서 마치 자신의 것처럼 활용할 수 있는데, 이것을 OOP 용어로 상속(inheritance)이라고 한다. 이 상속성은 객체지향 설계에서 매우 중요한 역할을 하는데, 우리는 객체들끼리의 IS_A 관계성을 이용하여 우리가 만들려는 클래스를 맨땅에서부터 시작하는 것
이 아니라, 마치 부모에게 유산을 물려받아 그것을 기본으로 사업을 벌이듯이 기존의 클래스 중의 하나를 부모 클래스로 하여 상속 받아서 만들 수 있는 것이다. 여기서 클래스라는 용어가 처음 나왔는데, 객체와 클래스는 어떻게 다른 것인지를 알아보기로 하자.

광일이는 사람이다. 그리고 진호도 사람이다. , 광일이와 진호는 사람이라는 클래스에 속하는 구체적이고 개별적으로 유일하게 하나만 존재하는 객체인 것이다. '광일' '진호'는 사람이라는 클래스에 맞도록 생성된 객체를 구별해 주는 객체의 이름(Object Identifier)이다. 다시 말하면, 클래스는 붕어빵 들을 말하며 붕어빵 틀에 의해 그 모양대로 생겨나고 없어지는 붕어빵은 객체이다. 한편 바로 위에서 말한 사자와 호랑이는 객체의 이름이 아니라 동물군에 속하는 또 다른 클래스의 이름이다. 우리는 호랑이라는 클래스를 이용하여 우리가 필요한 만큼의 '호돌이', '호순이', '호순이' 객체를 생성시키고 소멸시킬 수 있는 것이다.

객체들끼리의 또 다른 관계성은 HAS_PARTS_OF이다. 하나의 '(room)'이라는 클래스를 설계한다고 생각하자. 이 때, 우리는 ''을 한 번에 만들어 내는 것보다는 이 ''이 어떤 구성요소와 어떤 더 작은 객체들의 모임인지를 생각해 보는 것이 중요하다. 일반적으로 방에는 ''이 있다. 그런데 이 ''이라는 것도 객체이다. 다시 말하면 '' has parts of ''의 관계가 있다. 또한, '' has parts of ''의 관계도 있다. 이 때, 문과 창은 방을 구성하는 부품으로서의 객체이다. 그러므로 우리는 가능하면 다른 사람이 이미 만들어놓은 문이나 창이 있는지를 살펴보고, 만일 있다면 우리가 방을 만들 때 그것을 쓸 수가 있다. 또한, 문과 창이 아직 없다면 그것을 따로 만들어서 방 이외의 객체를 만들 때 사용할 수 있을 것이다.

앞에서 거론한 바와 같이 객체는 그것의 데이터와 그 데이터에 대한 연산(method)으로 구성이 되어 있다. 여기서는 C++ 언어에서 이러한 객체를 어떻게 명세(specify)하는지 그 문법을 통하여 알아보도록 하자. 이것은 C++로 프로그램을 짤 때 항상 기본적으로 외우고 있어야 하는 것이다.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Class
객체이름 : Public 부모 객체이름
private:
프라이비트 속성의 멤버 데이터;
프라이비트 속성의 멤버함수;
public:
퍼블릭 속송의 멤버 데이터;
퍼블릭 속성의 멤버함수;
}

객체이름 :: 멤버함수{
....(
멤버함수의 기능을 코딩) ...
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
어떤 객체의 멤버 데이터나 멤버함수는 private public이나 protected 중의 하나의 속성을 가져야 하며, 이것은 클래스의 설계자가 정한다. 이것이 바로 클래스의 정보은폐(Information Hiding)를 지원하기 위해 C++에서 제공하는 키워드이다. private는 말 그대로 사적인 것이므로 자기 자신에게만 있고 아무도 접근(access)할 수 없는 멤버임을 말한다. public은 반대로 다른 객체에게 '보이고', 다른 객체가 접근할 수 있는 멤버를 말한다. 마지막으로 protected는 다른 객체에게는 private로 작동하지만 자신의 자식 객체에게는 public한 멤버를 말한다.

여기서, 다른 객체에게 '보인다'라는 말이 어떤 의미인지 짚고 넘어가자, 우리말이 원래 그러하듯이 여기서의 '보인다'라는 말은 실제로 그 함수가 프로그램의 소스에서 글자가 보이느냐 안 보이느냐를 말하는 것이 아니다. 아무리 소스상에서는 보이지만, 다른 클래스에서 그것을 콜(Call)하려고 하면, 컴파일러는 그런 함수가 어디 있느냐는 듯이 에러를 내면서 컴파일되지 않는 것을 말한다. 바로 클래스의 설계자가 그 클래스를 사용하려는 개발자에게 사용법의 제약을 일부러 준 것이다.

그렇다고 해서 클래스를 자기가 만들어 자기가 그 클래스를 사용하려 할 때 '보이지 않으니까 불편하므로' private 속성을 마구 Public으로 바꾼다면 그것은 더 이상 OOP가 아니다. C++를 써야 하는지도 모르면서 남들이 쓰니까 써야 되는 줄 알고 쓰는, 소위 개념도 없는 사람들이 그러한 행동을 하는데, 그러다 보면 성수대교처럼 프로그램이 처음에는 동작하는 듯하다가 갑자기 붕괴하면서 OS까지 다시 깔아야 되는 경우가 생길 수도 있으므로 조심하여야 한다.

DOS
에서는 프로그램을 잘 짰었는데, 윈도우 프로그래밍으로 넘어가면서 도저히 적응을 못하고 프로그래머를 포기하려는 사람들이 가장 어려워하고 이해가 되지 않는 것이 윈도우 프로그램의 Message-Driven 방식이다. 물론 DOS에서도 볼랜드 C++ 3.1을 이용하여 C++로 프로그램을 짤 수도 있었지만, 우리가 도스시절 프로그램을 설계하고 구현하던 대부분의 방식은 구조화 프로그램이다. 구조화 프로그래밍에서는 큰 프로그램을 계속 쪼개어서 작은 함수들의 조각들로 만들고, 그 조각들도 제한된 몇 가지만의 제어구조(순방향처리, 반복처리, 조건처리)만으로 구현했었다. 이 때는 프로그래머가 커다란 지도를 잘게 나눈 후, 그 조각을 돋보기로 보듯이 실행하는 순서(flow)가 정확하게 존재했었다.

이런 방식에 길들여진 기존의 프로그래머들이 윈도우 프로그램에서는 '어떤 순서로 프로그램이 돌아가는 것일까'에 지나치게 집착하다보면, 프로그램의 흐름이 도대체 한 개인지 여러 개인지, 그리고 이것이 어디로 떠났다가 어디서 돌아오는 것인지 도무지 알 수 없어서 한 방 맞은 후, 자신의 프로그램에서 어떤 기능을 어느 부분에 코딩해야 될 지에 자신 없어 한다. 또한, 그러다보니 디버깅도 어떻게 해야 할지를 모르게되고, 주위 사람들에게 너무 어렵다고 협박을 하면서 포기를 한다.

그러나 이런 문제의 답은 간단하다. '더 이상 프로그램의 흐름(flow)을 생각하지 말라.' 물론, CPU가 순차적으로 동작하는 한, 분명히 flow는 존재할 것이다. 하지만 이제 컴퓨터는 매우 거대한 체계의 소프트웨어 구조로서 움직인다. 우리는 별 생각없이 자연스럽게 모니터의 한쪽에 TV를 켜두고 워드를 치면서 통신 에뮬레이터를 작동시키지만, 바로 이러한 멀티태스킹을 구축하기 위해 OS는 매우 복잡해지고 방대해졌다. 과거에는 미니급 컴퓨터 이상의 슈퍼컴퓨터에서 쓰이던 OS 이론이 이제 윈도우에도 대부분 적용되게 되었다.

그러므로 자신이 OS나 컴파일러를 직접 만들지도 않았으면서, MFC로 만든 애플리케이션을 어떻게 어떤 순서로 돌아가는지를 일일이 자기가 짠 것만큼 속속들이 알려고 하는 것은 거의 무모한 것이다. 우리가 MFC로 윈도우 프로그램을 만든다는 것은 MFC라는 인터페이스를 사용하는 것이며, 우리는 반드시 MFC에서 정의해 놓은 정보를 가지고, MFC를 만든 사람들이 정해 놓은 대로 짜야만 하는 것이다.

안타까운 현실이지만, 날로 거대해져만 가는 소프트 산업에 의해 어쩔 수 없는 일이다. 물론, 윈도우의 내부구조와 MFC의 설계이념 등을 자세히 알 수록 우리는 맘껏 프로그램을 짤 수 있다. 단지, DOS에서처럼 만만치가 않고 참으로 많은 공부들을 깊이 있게 해야만 가능하다는 것이다.

그렇다면 더 이상 flow(코드의 실행순서)의 의미가 없어진 OOP에서 우리는 어떻게 프로그램을 코딩할 수 있을까? 해답은 '메시지'에 있다. OOP의 객체들은 메시지에 의해 반응하면서, 각자가 자기의 일을 분주하게 하고 있는 가상적인 '사회'와 같다. 우리는 OOP로 프로그램을 설계할 때 가장 먼저 그 프로그램에 어떠한 객체들이 있어야 하는지, 그 객체들은 서로 어떤 관계성을 가지는지, 각각의 객체들은 어떤 시점에서 어떤 메시지에 반응하여 어떤 동작을 해주어야 하는지에 주안점을 두어서 설계하여야 하는 것이다. 그러고 나서 우리는 이미 달리기 시작한 개썰매에 탄 주인처럼 각각 자기 나름대로 달리고 있는 개들에게 채찍이라는 메시지를 이용하여 적절한 시기에 적절한 메시지를 해당 객체에게 보내주는 방식으로 개썰매를 가려고 하는 방향으로 잘 조종할 수 있는 것이다. 결코 개 한마리가 한 발자국 움직인 다음, 어떤 개가 다음 한 발자국을 떼어야 할지를 고민하고 있어서는 안 된다.

OOP
는 이런 것들 외에도 프로그램을 보다 인간이 사고하는 방식에 가깝게 코딩하여서, 개발과 분석이 용이하도록 여러 가지를 지원한다. 예를 들면 다형성(Polymorphism)과 연산자 오버로딩(operator overloading)이 있다. 이러한 특성은 개체를 설계하는 개발자나 그 객체를 사용하려는 개발자 모두에게 프로그래밍 문제를 객체지향적이고 개념적으로 분석할 때, 의사소통이 잘 되도록 하는데 그 목적이 있다. 하지만 이러한 기능을 잘못 남발하면 오히려 서로에게 더 정신 없고 애매모호한 프로그램이 될 수도 있다. 프로그램은 뭐니뭐니해도 그 구조와 알고리즘이 깨끗하고 명확하여야 한다는 것을 명심해 두어야 한다.

 


 

2013년 12월 13일 금요일

PHP 단어 수 세기 우선순위 버전

1. index.php

<?php
include "wordCheck.php";
if (isset($_POST['content']))
{
    $wordCheck = new WordCheck;
    $content = stripslashes($_POST['content']);
    $exploded = $wordCheck->MultiExplode($content);
    $wordList = $wordCheck->GetWordList($exploded);
    $count = (count($wordList,1)/count($wordList,0))-1;
}

?>

<?php echo "Input " ?>
<form action="<?php echo $_SERVER["PHP_SELF"] ?>" method="post">
    <textarea rows="25" cols="60" name="content"></textarea>
    <input type="submit" value="Save">
</form>


<textarea rows="35" cols="60" name="result">
<?php for($i=0; $i < $count; $i++)
{
    echo "Word : " . $wordList[0][$i] . "    " .
         "Count : " . $wordList[1][$i] . "\n";
}
?></textarea>

<?php for($i=0; $i < $count; $i++)
{
    echo "<a charset=UTF-8 href=http://endic.naver.com/search.nhn?sLn=kr&searchOption=all&query="
    . $wordList[0][$i] . ">" . $wordList[0][$i] . "</a>" . "\n";
}
?>



2. wordCheck

<?php
class WordCheck
{
    var $delimiters = array('\"', '?', '<', '>', '(', ')',
                         '!', '-', '/', ',', '.', '|',
                          '=', ':', ' ', "\r\n", "\t");

    function MultiExplode($string)
    {
        $ready = str_replace($this->delimiters, $this->delimiters[0], $string);
        $launch = explode($this->delimiters[0], $ready);
        return  $launch;
    }
    function GetWordList($exploded)
    {
        $count = array();
        $word = array();
        $unique = (array_unique($exploded));
        foreach($unique as $token)
        {
            if (strcmp("\r\n", $token) == -1 || strcmp(" ", $token) == -1)
            {
                $countNum = count(array_keys($exploded, $token));
                array_push($count, $countNum);
                array_push($word, $token);
            }
        }
        array_multisort($count, SORT_DESC,SORT_NUMERIC, $word, SORT_ASC, SORT_STRING);
        return array($word, $count);
    }
}
?>



2013년 12월 10일 화요일

PHP 단어 수 세는 소스

1. index.php
  • vim /var/www/dwhan/index.php
 <?php
include "wordCheck.php";

if (isset($_POST['content']))
{    $wordCheck = new WordCheck;
    $content = stripslashes($_POST['content']);
    $exploded = $wordCheck->MultiExplode($content);
    $wordList = $wordCheck->GetWordList($exploded);}
?>
 
<?php echo "Input " ?>
<form action="<?php echo $_SERVER["PHP_SELF"] ?>" method="post">
    <textarea rows="25" cols="60" name="content"></textarea>
    <input type="submit" value="Save"></form>
 
<textarea rows="35" cols="60" name="result">
<?php foreach($wordList as $key => $value)
        {
            foreach($value as $key => $value)
            {
                echo "Word : " . $key . "  " . "Count : " . $value . "\n";
            }        }
?></textarea>
 
2. wordCheck.php
  • vim /var/www/dwhan/wordCheck.php
<?php
class WordCheck
{
    var $delimiters = array('\"', '?', '<', '>', '(', ')',
                         '!', '-', '/', ',', '.', '|', '=', ':', ' ', "\r\n", "\t");

    function MultiExplode($string)
    {
        $ready = str_replace($this->delimiters, $this->delimiters[0], $string);
        $launch = explode($this->delimiters[0], $ready);
        return  $launch;   
    }

    function GetWordList($exploded)
    {
        $word = array();       
        $unique = (array_unique($exploded));

        foreach($unique as $token)
        {
            if (strcmp("\r\n", $token) == -1 || strcmp(" ", $token) == -1)
            {
                $count = count(array_keys($exploded, $token));
                $temp = array($token => $count);  // 뽑아낸 단어와 카운트를 인덱스를 토큰으로 지정하여 배열에 저장
                array_push($word, $temp); // 생성한 배열을 추가
            }
        }
        return $word;
    }
}
?>

2013년 12월 4일 수요일

Wowza 설정

1. 최신버전 JAVA 설치
  • JAVA 홈페이지 접속 (http://java.com)
  • 운영체제 맞는 버전 다운로드 (다이렉트로 다운로드 주소를 알 수 없기 때문에 콘솔환경이라면 links 브라우저 이용)
2. WOWZA 설치
chmod 755 WowzaMediaServer-3.6.3.tar.bin && ./WowzaMediaServer-3.5.0.tar.bin
  • 라이센스와 관련한 메시지가 나타나면, 계속해서 Space Bar 를 눌러 진행
  • 라이센스에 동의하는 메시지가 나타나면, “yes” 를 입력한 후 엔터.
  • 다음와 같은 메시지가 나타나면 정상적으로 설치가 된 것 
Install Location:  /usr/local/WowzaMediaServer
  • 다음의 명령을 이용하여 Wowza 서버를 실행
cd /usr/local/WowzaMediaServer/bin && ./startup.sh
  • 다음과 같은 메시지가 나타나면, 발급받은 라이센스키를 입력
Configure logging: file:///usr/local/WowzaMediaServer/conf/log4j.properties
Please enter your License Key in this format:
XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX[-XXXXXXXXXXXX]
  • 라이센스 키를 정상적으로 입력하면 Wowza 서버 시작
3. example 파일 설치
  • examples 폴더 이동 후 installall.sh 실행 (./installall.sh 실행하면 기본 재생테스트에 필요한 파일들이 설치 됨)
cd /usr/local/WowzaMediaServer/examples && ./installall.sh 

 
4. 재생 폴더 변경
  • 기본적으로 /usr/local/Wowza/content 폴더에 위치하며 기본 폴더의 변경 위해 3군데 폴더 생성 (폴더의 이름은 같아야 함)
/usr/local/Wowza/content/원하는 폴더명
/usr/local/Wowza/applications/원하는 폴더명
/usr/local/Wowza/conf/원하는 폴더명

 
  • config 파일 복사 후 수정
/usr/local/Wowza/content 아래 Application.xml 파일 복사하여 /usr/local/Wowza/conf/생성한 폴더에 복사 후 수정

 
<Streams> 섹션의 <StreamType> 은 default로 기본 VOD 설정되어 있음
<StorageDir>의 {com.wowza.wms.context.VHostConfigHome} 삭제 후 생성한 폴더 경로 입력 (EX. content/dwhan)

 
 <Streams>
                        <StreamType>default</StreamType>
                        <StorageDir>/content/dwhan</StorageDir>
                        <KeyDir>${com.wowza.wms.context.VHostConfigHome}/keys</KeyDir>
                        <!-- LiveStreamPacketizers (separate with commas): cupertinostreamingpacketizer, smoothstreamingpacketizer, sanjosestreamingpacketizer, 
mpegdashstreamingpacketizer, cupertinostreamingrepeater, smoothstreamingrepeater, sanjosestreamingrepeater, dvrstreamingpacketizer, dvrstreamingrepeater -->
                        <LiveStreamPacketizers></LiveStreamPacketizers>
                        <!-- Properties defined here will override any properties defined in conf/Streams.xml for any streams types loaded by this application -->
                        <Properties>
                        </Properties>
         </Streams>

 
5. 재생 테스트