자료 정의어(DDL: data definition language)

  자료 정의어는 스키마를 정의하는 언어이다. 스키마 정보는 자료 사전(data dictionary, 또는 자료 목록(= data directory)이라고도 함)에 들어 있다. 스키마 정보란, 자료(보기: 아이디, 패스워드 등)에 대한 자료(보기: 아이디의 자료형은 char이고 몇자리의 char인지)인데, 이를 메타데이터(metadata)라고 보통 부른다.

  

  SQL에서 자료 정의어의 보기를 들면 다음과 같다.


  create table 유저 {순서 인덱스 char(7), 아이디 char(10), 패스워드 char(15), 보유 캐릭터 개수 int };  


   자료 조작어(DML: data manipulation language)

   자료 조작어는, 데이터베이스 안에 있는 자료를 가져오거나(retrieve), 없에거나(delete) 바꾸거나(update), 데이터 베이스에 새 자료를 넣는(insert)일을 한다.

   SQL에서 자료 조작어의 보기를 들면 다음과 같다.


select * 

from 유저

where 아이디 = ’홍길동’; 


insert into 유저

values ('9902101' ’ 흥길동’); 


delete 

from 유저 

where 아이디 = 홍길동’? 


update 유저 

set 아이디 = '장길산’ 

where 아이디 = 홍길동’ ;


  자료 조작어의 성질 : 비절차적, 집합 결과


  자료 조작어의 성질을 말할때 책에 따라서 풀이가 좀 달라서 혼란스러운데 다음과 같이 두가지 독립적인 기준에 나눌수 있으며, 그 결과 2*2의 네가지 로 나눌 수 있다.


  첫째 절차적인지 (procedural) 비절차적인지 (non - procedural)

  우리가 많이 쓰는 c 등의 고급프로그래밍 언어는 거의 모두 절차적이다.

  int a = 0; 이런 문장은 정수형 a를 선언하여 메모리 상에 올리고 거기에 0을 대입하는 절차적인 과정을 거친다.

  절차적인 자료 조작어로는, 뒤에서 배우게 될 관계 대수 (relational algebra), 그리고 계층적 모델과 네트웍 모델에서 쓰는 자료 조작어가 있다.

  비절차적 언어로는 관계 해석(relational calculus)가 있으며, 또한 관계 해석을 많이 채택한 SQL에서도 비절차적 면을 볼수 있다.(SQL은 관계 해석과 관계 대수 두가지에 바탕을 두고 있다.) 


  비절차적 언어의 특징을 살펴보면, 보기를 들어 유저, 아이디, 캐릭터라는 속성으로 이루어진 유저라는 테이블이 있을때 유저 테이블의 스키마와 인스턴스가 아래와 같다면


   유저   순서인덱스    아이디    캐릭터

0000000001   ID1          전사

0000000002   ID2          전사

0000000003   ID1          마법사

0000000004   ID2          마법사


   이테이블에서 캐릭터가 마법사인 유저의 아이디를 찾아내라고 한다면 절차적 언어에서는  FOR문등으로 반복을 돌면서 찾게 될 것이다.

  그에 비해서 비절차적 언어인 SQL을 쓴다면 어떤 철자적인 내용에 대해서는 말하지 않고 다음과 같이 쓸것이다.


  select 순서인덱스

  form 유저

  where 캐릭터 = "마법사"


  둘째, 자료 조작어의 명령 결과로 한번에 레코드가 한개(recored-at-a-time)씩 나오는지 아니면 여러개의 자료(자료의 집합)가 한꺼번에 나오는지 (set-at-a-time)에 따라서 두가지로 나뉜다.  조합해 보면 다음과 같다.


  비절차적 한개씩 (이녀석은 별로 없다고 한다)

  비절차적 자료집합 (관계 해석 SQL)

  절차적 한개씩 (계층적 모델, 네트웍모델)

  절차적 자료집합 (관계 대수)


  질의어(query language)와 자료 조작어(DML)


  질의어(쿼리)라는 낱말은 원래 뜻은 물어보다이며 데이터 베이스와 관련하여서는 이미 있는 자료나 정보를 가져오는 것이다. SQL에서 보면 select만 해당되고 insert, delete, update는 해당되지 않는다.

  이에 비해, 자료 조작어(DML)는 이미 있는 자료를 가져오는 것뿐만 아니라, 있는 자료를 지우거나 고치는 것과, 새 자료를 넣는 것까지 할수 있으므로 질의어 보다 더 넓은 개념이다. SQL에서 보면 select, insert,delete, update를 모두 포함하는 개념이다.

  그렇지만, 오늘날 실제로 질의어라는 용어를 원래의 뜻대로 있는 자료를 가져오는 것에 국한하여 쓰는 일은 아주 드물다. 거의 모든 사람들은 쿼리문을 자료 조작어와 맞바꾸어 쓸수 있는, 뜻이 같은 용어로 본다. 낱말의 원래 뜻을 생각하면 잘못된 용법이지만, 오늘날 거의 모든 사람들이 이렇게 하므로 그냥 관습을 따를 수 밖에 없다고 본다.


  데이터 베이스 관리자와 사용자

  데이터 베이스 관리자(DBA: Database Administrator)

  데이터 베이스 관리자는 데이터베이스 관리 시스템을 관리할 뿐만 아니라, 데이터베이스, 그리고 그 기관에서 개별된 응용 프로그램을 관리한다. 작은 기관의 경우에는 한사람이 관리자 일을 할 수도 있을 것이고, 큰 기관에서는 관리자의 일을 여러 사람이 맡게 된다.

  관리자는 그 밖에도 자료 접근 권한을 정하고 바꾸는 일, 무결성 제약 조건을 정하는 일을 한다.


  데이터 베이스 사용자


  데이터 베이스 사용자의 종류는 너무 많고, 또한 나누는 기준에 따라 다르지면 몇가지 종류를 보자면


  응용프로그래머 : 주어진 데이터베이스 관리시스템을 써서 그 기관에 필요한 응용프로그램을 만든다. 게임을 만드는 프로그래머도 이에 속한다. 이 경우 보통의 SQL(이른 바 상호 작용적 SQL: interactive SQL)을 바로 쓰기보다는 주로 내포된(embedded) SQL을 많이 사용한다.

  일반사용자 : 만들어진 응용프로그램을 쓰는 사람인데, 실제로 이런사람이 엄청 많다. 뭐 그냥 실생활에 쓰이는 대부분을 보면 된다. 우리 자신들 이니까.


  4GL 운영체제


  4GL(fourth generation language)

  4GL 데이터베이스를 다루기 위하여 쓰는 언어 가운데 4GL이라는 것이 있다. 

  제 1세대 언어는 1GL(first-generation language)라고 하며 기계어(machine langage)가 여기에 속한다.

  제 2세대 언어는 어셈블리 언어

  우리가 쓰는 c같은 고급언어를 3세대 언어라고 한다.

  4GL이란 3GL보다 한단계 더 높다고 보다는데, 일반적으로 데이터베이스 환경에서 양식을 만들거나 화면에 자료를 보여주는 프로그램을 쉽게 짤 수 있게 해주는 것이 4GL의 주요 기능이다. 그런데 SQL은 표준화가 잘되어있어서, SQL 프로그램이 다른 데이터베이스 관리 시스템에 옮겨가더라도 별 어려움 없이 잘 돌아간다. 하지만 4GL은 표준화가 전혀 되어 있지 않아서, 다른 데이터 베이스 관리 시스템에 옮겨가서 쓸 수가 없다는 단점이 있다.

  

  데이터 베이스 관리 자체(DBMS)  와 운영 체제(OS)

  운영 체제의 관점에서 보면 데이터베이스 관리 시스템은 어디까지나 하나의 응용프로그램이므로, 데이터베이스 관리 시스템은 운영체제 위에서 돌아간다. 위에서 돌아간다고 해서 데이터베이스 관리시스템이 운영체제를 관리한다는 것은 아니다. 운영체제가 데이터베이스 관리 시스템을 통체한다.

  일반적으로 파일을 처리하는 응용프로그램의 경우, 응용 프로그램에서 운영체제의 파일관리자를 통하여 파일을 처리하게 된다. 그런데 데이터베이스 응용프로그램은 파일의 내용을 바꾸려면, 먼저 데이터베이스 관리시스템에 이를 요청하고, 데이터베이스 시스템은 다시 운영체제의 파일 관리자를 통하여 파일을 처리하게 된다.

  

Posted by JJOREG

데이터 베이스에서 뷰란?

  뷰(=view)는 가상 테이블(=virtual relation)이라고도 한다.


자료의 추상화(data abstraction) 세 단계


  데이터베이스 관리 시스템과 사용자 사이의 상호 작용을 쉽게 풀이하기 위하여 데이터베이스의 자료를 추상화하며, 보통 다음과 같이 세 가지 수준으로 나눈다.

  하지만 이는 개념모델(reference model)이다. 즉 꼭 따라야 하는 것은 아니며 데이터 베이스의 모든 시스템이 이 모델에 의하여 구성된 것은 아니다.

  이는 마치 데이터통신에서(ISO OSI의 일곱 단계 통신모형에 맞는 통신 프로그램이 거의 없는 것이나 마찬가지이다.)


  1) 물리적 수준(physical level)

  자료가 실제로 저장되는 수준이며, 가장 아래 수준이다.


  2) 논리적 수준(logical level)

  이것은 데이터베이스 관리자(DBA : database administrator)이 처리하는 수준이다.


  3) 뷰(=가상 테이블) 수준(view level)

  일반 사용자가 쓰는 수준으로 볼 수 있다. 이런 것이다. 데이터란 결국 바이트단위로 처리를 하게 되는데. 이는 기계어로 보면 왠만해서는 알아볼 수 없다.

  하지만 문서처리 프로그램중 엑셀프로그램 처럼 도표로 사용자가 볼 수 있고 권한에 따라서 필요한 부분만 수정할 수 있다면? 이런 부분이 바로 view 수준이라고 한다.


  그런데 실제 상용 데이터베이스 관리 시스템에서 어떤 명령이 어느 수준에 해당하는지 명확하게 나누는 것은 쉽지 않다. 뷰 수준은 그런데로 쉽게 알 수 있지만 물리적 수준과 논리적 수준은 때때로 경계가 모호하다. 하지만 앞서 말했듯 위의 세가지 모델은 어디까지나 참조 모델일 뿐이므로, 구체적인 어떤 사용 데이터베이스 관리 시스템의 명령을 세단계로 나누는 문제에 너무 매달리지 말자.


자료의 독립성(data independence)


  일반적으로 자료의 독립성이란 어느 단계의 스키마를 바구었을 때, 그 위 단계의 스키마에 영향을 주지 않고 결국 응용 프로그램에 영향을 주지 않는 것을 가리킨다.

  c++로 친다면 클래스 간의 의존성 제거 객체지향적으로보면 리스코프 치환법칙과 의미가 통한다.

  자료의 독립성은 다음과 같이 두가지로 나타나게 된다.


  1) 물리적(physical) 자료 독립성

  맨 아래 단계인 물리적 스키마를 바꿔도, 그 위 단계인 논리적 단계 스키마에 영향을 주지 않는 것을 가리킨다. 당연히 논리적 스키마에 영향을 주지 않으므로 그 위 단계인 뷰 단계의 스키마에는 물론 영향을 주지 않는다.

  

  여기서 잠깐! 스키마란?

  데이터베이스 스키마(database schema)는 데이터베이스에서 자료의 구조, 자료의 표현 방법, 자료 간의 관계를 정의한 것을 말하는 전산학 용어이다. 데이터베이스 관리 시스템(DBMS)이 주어진 설정에 따라 데이터베이스 스키마를 만들어 내며, 데이터베이스 사용자가 자료를 저장, 조회, 삭제, 변경할 때 DBMS는 그것이 생성한 데이터베이스 스키마를 참조하여 명령을 수행한다.


  2) 논리적(logical) 자료 독립성.

  가운데 단계인 논리적 단계의 스키마를 바꿔도 그 윗 단계인 뷰 단계의 스키마에 영향을 주지 않는 것을 가리킨다. 뷰 단계 스키마에 영향을 주지 않기 때문에, 그 결과 응용 프로그램에도 영향을 주지 않는다.


  이때 이 두가지 독립성 단계에 대해서 제대로 설명하지 않는 부분이 많은데 그 이유는 상용 데이터 베이스 관리 시스템에서 물리적 단계와 논리적 단계를 나누기가 쉽지 않기 때문이다.

  하지만 SQL명령어 적으로 예를 들어 보겠다.


  create table 유저 {순서인덱스 cahr(7), 아이디 cahr(20)};


  위의 create table 명령은 순서인덱스와 아이디이라는 속성으로 이루어진 학생이라는 테이블을 만든다. 그 뒤 아래에 select 명령을 쓰면, 아이디가 '홍길동'이라는 유저의 이름을 보여준다.


  select *

    form 유저

    where 아이디 = '홍길동';


  자료의 독립성에 관한 구체적인 첫번째 보기는 색인(= 찾아보기, index)이다. 색인이 있으면 검색속도가 빨라지게 되는데.

  보기를 들어 유저수가 10000명인데 유저자료가 아이디 순서대로 간추려져 있다면 이름에 대한 색인이 없다고 한다면 create index 명령을 써서 이름에 대한 색인을 만들어 둔뒤 '홍길동'을 찾으면,색인이 없을 때보다 검색 속도가 훨씬 빨라진다.


  create index 이름_색인

  on 학생(이름);

  select *

  form 유저

  where 아이디 = '홍길동';

  

  그런데, 여기서 중요한 것은 색인이 새로 만들어 지더라도, 위의 select 명령을 전혀 바꾸지 않고 꼭 같은 결과를 얻을수 있지만, 색인이 있든 없든, select 명령은 바뀌지 않고 그대로 이고, 다만 실행 속도가 달라질 뿐이다.


  자료 독립성에 관한 구체적인 둘째 보기는 뷰에 관한 것이다. 보기를 들어, 아래와 같이 순서 인덱스, 아이디, 패스워드로 이루어진 유저이라는 테이블이 있고, 학생이라는 테이블에서 create view 명령을 써서, 학번과 이름만으로 이루어진 학생_view라는 뷰를 정의했다고 하자


  create table 유저 {순서 인덱스 char(7), 아이디 char(10), 패스워드 char(15)};

  create view 유저_view as

   select 순서 인덱스, 아이디

     from 유저;


  이렇게 하면 응용 프로그램에서는 유저_view라는 뷰를 다음과 같이 쓸 수 있다.

  

  select *

    from dbwj_view

    where 순서인덱스 = '9902101';


  그런데 학생에 휴대전화라는 속성이 하나 더 들어가서 유저의 스키마가 다음과 같이 바뀌었다고 하자.

  

  유저 {순서 인덱스 char(7), 아이디 char(10), 패스워드 char(15), 휴대전화 char(15)};

  

  유저의 스키마가 이렇게 바뀌더라도 결국 유저_view를 정의하는 create view 명령을 바꿀 필요가 없으며, 또한 유저_view를 쓰는 응용프로그램에서 select 문장을 전혀 바꾸지 않아도 결과는 제대로 나온다. 유저의 스키마가 바뀌었지만, 유저_view의 정의를 바꿀 필요가 없으며, 유저_view 뷰를 쓰는 응용프로그램에서 SQL문장을 전혀 바꿀 필요가 없다.

  이를 고급프로그래밍 언어 C++에서 처리한다고 생각해보자.


found=0 ; 

for 0=1; (= num_records ; i++) { 

read from 유저_view 순서인덱스 , 아이디) ; 

if (아이디 = 홍길동’) { 

printf (학번, 01 름) ; found++ ; 

} // endif 

} // end for 

if (tound == 0) 

  printf 홍길동 학생이 없습니다 ) ;


식으로 짜며 당연히 다형성이나 그때그때 필요한 코드를 또다시 짜야만 할것이다.

물론 이런 것을 감안하고 프로그래밍 할 수는 있지만 그것은 이미 존재하는 데이터 베이스 시스템과 같은 역할을 하는 파일입출력 프로그램을 고급언어로 다시 짠다는 것인데 엄청난 노력과 시간이 들어가게 될 것이다.


스키마(schema)와 인스턴스(instance)?


  데이터 베이스와 관련하여 스키마와 인스턴스는 구별되어야 하는데 관계형 데이터 베이스의 경우에는 관계(= 테이블, relation)와 데이터베이스 각각에서 스키마와 인스턴스 개념이 적용된다. 다시 말하여 테이블의 스키마와 테이블의 인스턴스가 존재하며 또한 데이터 베이스의 스키마와 데이터베이스의 인스턴스라는 개념이 존재한다는 것이다.


  관계형 데이터베이스 환경에서 관계의 스키마와 관계의 인스턴스를 비교해보자. 아홉 자리를 차지하는 순번 인덱스이라는 속성(attribute), 스무 자리를 차지하는 아이디이라는 속성, 그리고 열 다섯 자리를 차지하는 패스워드라는 속성으로 이루어진 학생이라는 관계를 만드는 SQL 문장 create table가 아래에 나와있다.


  create table 유저 {순서 인덱스 char(7), 아이디 char(10), 패스워드 char(15)};  


  이 문장은 학생이라는 테이블에 어떤 속성(순서 인덱스, 이름, 집전화)가 있으며, 각 속성의 자료형(data type)가 무엇인지만 나타낸다. 다시 말하면 테이블의 틀(=뼈대)을 나타낼 뿐, 그 테이블 안에 어떤 자료가 실제로 들어있고 어떤 식으로 데이터베이스의 로직이 이루어지는지는 알수가 없다.

  이처럼 테이블에 있어서 속성 이름과 자료형 등에 관하여 규정하는 것을 관계(=관계)의 스키마라고 한다. 위의 create table라는 SQL 명령은 학생이라는 테이블(=관계)의 스키마를 만드는 명령이다.

  위에 설명한 단어의 원론적인 설명과 다르게 데이터베이스에서 스키마(SCHEMA)는, 틀, 뼈대 등의 뜻이 있으며 보통 한글로 옮기지 않고 스키마라는 용어를 그대로 사용한다.

  데이터 베이스는 일반적으로 도표형식으로 내용을 볼 수 있는데.


  유저   순서인덱스    아이디    패스워드

0000000001   ID1        23451123

00000000012   ID2       123456

  

  이런식으로 어떤 특정 시점에 테이블 안에 있는 구체적인 값의 집합을 관계(=테이블)의 인스턴스라고 한다.


  그런데 일반적으로 테이블의 스키마는 처음 만들 때 잘 생각해서 만들기 때문에, 일단 스키마를 한번 만들면 잘 바꾸지 않는다. 거기에 비해서 테이블의 인스턴스는 상대적으로 스키마보다는 많이 바귀게 된다.


일단 스키마가 바뀌는 경우를 보도록 하자. 


• 현재 있는 학번, 이름, 집전화 속성 가운데 어떤 속성을 빼기 . 

보기 . 패스워드를 뺀다


  create table 유저 {순서 인덱스 char(7), 아이디 char(10)};  


·현재 없는 속성을 더 넣기 . 

보기 : 보유 캐릭터 개수를 더 넣는다


  create table 유저 {순서 인덱스 char(7), 아이디 char(10), 패스워드 char(15), 보유 캐릭터 개수 int };  


휴대전화 char(15)); 


• 속성의 자료형을 바꾼다, 

보기: 패스우드의 자료형을 char(15) 에서 char(20) 로 바꾸었다. 


  create table 유저 {순서 인덱스 char(7), 아이디 char(10), 패스워드 char(20), 보유 캐릭터 개수 int };  


  당연히 데이터 베이스의 테이블이 많아질수록 수많은 유저들의 정보가 통채로 입력되므로 그에 맞는 정보를 입력해줘야 한다. 유저수가 많으면 많을 수록 보통 번거로운 것이 아닐 것이다. 거기에 비해서 테이블의 인스턴스는 상대적으로 많이 바뀌지 않는다. 인스턴스가 바뀌는 경우에 대해서 예를 들어본다면


  유저가 한명 추가되어 맨 마지막줄에 새로운 유저가 들어오는 경우.

  혹은 한명의 유저의 패스워드가 변경된 경우.

  이외 등등등.


  과 같은 경우 인스턴스가 바뀌었다고 하는데. 일반적으로 테스블의 한 행이 바뀌거나, 추가되거나, 삭제되면 인스턴스가 바뀐다고 하며 예상해봐서 알겠지만 당연히 인스턴스는 자주 바뀐다.


  자료 모델?


  데이터베이스에서 자료를 나타내는 방식은 여러가지가 있으며, 책에 따라 나누는 기준이나 방법도 다르다. 

  어떻게 나누냐는 덮어 두고 실제 쓰여졌던 데이터 베이스의 모델들에 대해서 알아보겠다.


  개체 - 관계모델(E-R : entity - relationship model)

  개체 - 관계 모델은 데이터베이스 설계(data base design) 때 많이 쓰인다. 그렇지만 개체 - 관계 모델에 따른 데이터 베이스 관리 시스템 프로그램이 개발되어 있지 않기 때문에, 실제 자료를 처리하기 위하여 우리가 개체 - 관계 모델을 쓰지는 않는다.

   개체 관계 모델은 실제 세계에 대한 인식을 바탕으로 한다 객체지향프로그래밍과 닮은 방향성을 가지고 있어 보인다. 이 모델은 첫째, 개체(entity), 둘째 개체와 개체 사이의 관계(relationship), 이 두가지를 기본으로 하고 있어서 개체 - 관계 모델이라고 부른다.

  개체란, 학생, 과목, 은행 계정, 회사 등과같이 실제 세상에 있는 객체를 가리키며, 각 객체는 다른 객체와 구별된다. 개체는 하나 또는 여러개의 속성으로 나타내게 된다. 유저를 패스워드 순서 인덱스 아이디라고 나눈 것과 같다.

  이에 쓰이는 용어는 개체 집합, 관계 집합, 개체 사이의 사상(=매핑) 크기(mapping cardinality) 제약, 개체 - 관계 모델 그림 (diagram) 등이 있다.

  

  객체지향 모델(OO model, object - oriented model)

  객체지향 모델은 개체-관계 모델을 수용하고 거기에 실행할 수 있는 프로그램까지 모두 포함한다.


  관계형 모델 (relational model)


  관계형 모델은 오늘날 가장 널리 쓰이고 있는 관계형 데이터베이스의 바탕이 되는 모델이다.

  자료(data)를 나타낼 때, 그리고 자료사이의 관계(relationship)를 나타낼 때 모두 관계(relation, 또는 테이블 : table, 표)를 쓰기 때문에, 관계형 모델이라고 부른다. 관계형 데이터베이스는 1970 년대에 연구가 시작되어 오늘날 가장 널리 쓰고 있다.


  네트웍 모델(network model)

  관계형 모델이 나오기 전에, 네트웍 모델에 바탕을 둔 사용 프로그램을 1960년대 후반부터 썼지만, 요즘은 이 모델을 사용하여 제작되는 데이터 베이스는 거의 없다.


  계층적 모델(hierarchical model)

  관계형 모델이 나오기 전에 계층적 모델에 바탕을 둔 사용 프로그램을 1960년대 후반부터 썼지만, 요즘 새로만들 때 역시나 이 모델을 쓰는 곳은 거의 없다.












Posted by JJOREG

데이터 베이스(DATABASE)란?

  자료를 많이! 모은것!

  하지만 자료라고 해서 아무런 연관없는 자료를 그냥 모으면 그건 유용하지 않다.

  데이터 베이스에 있는 자료는 서로 연관성이 있는 자료들이어야 한다. 

  게임이라면 플레이어 데이터 플레이어 아이템 유저 패스워드 같은 식으로 데이터를 연관시켜 모아놓은 것을 의미한다.


데이터 베이스 관리시스템(DBMS : DATABASE MANAGEMENT SYSTEM)

  데이터 베이스와 더불어 많이 쓰이는 용어로 데이터 베이스 관리 시스템이라는 용어가 있다. 데이터베이스와 데이터 베이스 관리 시스템은 다른 개념을 가리킨다.

  DB는 말그대로 데이터의 집합 DBMS는 그것을 편하게 관리하기 위한 시스템이다.


  심플하게 설명하면다음과 같다.

  DB는 창고다. 

  DBMS는 그곳에서 일하는 사람들

  창고는 그 자체로 그냥 물건을 보관하고 물건을 정리하고 빼고 추가하고 하는 일을 하는 것은 창고에서 일하는 사람들이 하는 일이다.


응용(또는 사용자) 프로그램(DBMS : DATABASE MANAGEMENT SYSTEM)

  그런데 각 기관에서 데이터베이스를 관리하려면 데이터베이스 관리 시스템에 있는 프로그램을 활용하여, 그 프로그램등에 맞춰서 또다른 관리 프로그램을 만들어야 한다.

  게임을 생각해보면 유저 패스워드가 있고 그 데이터를 넣고 뺄 수 있는 DBMS가 있다고 해서 유저패스워드를 통한 로그인 시스템까지 지원해주는 것은 아니다.

  그것은 또 우리가 만들어야 한다. 이를 사용자 프로그램이라고 한다.


데이터 베이스 시스템이 파일관리보다 좋은 점.

  컴퓨터가 처음 나왔을 때는 운영체제 개념이 나오면서 파일 체제 개념도 따라서 나오게 되었다. 그런데 파일체제 많으로는 복잡한 일을 하는데 어려움이 있었다.

  그런 상황에서 거대한 데이터를 파일처리 시스템만으로 관리하지 못하므로 그를 지원하는 기능을 갖춘 DBMS가 1960대 부터 등장하기 시작했다.

  오늘날 많이 쓰고 있는 관계형(relational) 데이터베이스는 1970년대부터 나오기 시작하였다.

  그럼 파일 처리와 데이터베이스 시스템의 차이에 대해서 본격적으로 알아보자.


  1) 자료의 중복(data redundancy)와 자료의 불일치(data inconsistency)

  파일 처리 접근 방식을 쓰면, 꼭 같은 정보가 여러군데 되불이 될 수 있다. 보기를 들어 게임에서 아이템데이터가 변경되었다고 치자. 그런데 유저 아이템데이터는 유저의 세이브파일에도 들어 있고 게임의 로직 아이템파일에도 들어있으며, 각 NPC데이터 파일에도 들어있다. 그럼 결국 세가지 파일을 다 바꿔야 할것이다. 만약 하나라도 이 데이터가 바뀌게 된다면 세개의 파일을 모두 바꿔줘야 한다. 혹은 그러다 어떤 파일을 바꾸지 못하는 경우가 생기는데 이런경우 자료 불일치라고 한다.

  또한 파일로 관리할시 이렇게 세개의 파일이 모두 아이템 데이터를 가지는 경우가 생기는데 이는 같은 자료를 중복적으로 가지게 되는 경우이다.


  2) 자료처리의 불편함.

  파일 처리 접근 방식은 보통 고급언어에서 응용프로그램을 짜야하는데 이는 고급언어에 대한 훈련이 필요하다. 그런데 데이터베이스는 거진 공통적인 명령을 사용하고 고급 프로그래밍 언어보다 데이터를 처리하는데 필수적인 기능만을 모아놓았다. 프로그래밍언어로 파일안의 데이터를 처리하기 위한 명령어는 복잡하거나 상황이나 언어 플랫폼에 따라서 달라지는 반면 데이터베이스는 훨씬 편하게 사용이 가능하다.


  3) 자료의 고립(data isolation) 문제

  게임 아이템을 모아놓은 아이템데이터 NPC의 능력을 모아놓은 파일 월드세팅 파일 등이 따로 존재하는데 이를 모아서 세이브파일을 만든다고 치면 같은 자료가 3개의 파일에 따로 생기는 것이다. 그 결과 자료 불일치가 생기는 경우가 생긴다.

  
  4) 자료의 무결성(data integrity)

  자료의 무결성이란 자료에 잘못이 없어야 한다는 것을 말하는데, 자료의 불일치를 포함하여 여러가지 경우에 자료의 무결성이 깨질 수 있다.

  책에 따라서 자료의 불일치와 자료의 무결성에 풀이가 다를수 있는데 일반적으로 자료의 불일치는 자료의 무결성을 깨게 된다. 하지만 자료의 불일치가 아니더라도 자료의 무결성을 깨는 경우가 많다. 

  예를 들어 자료의 불일치와 다르게 게임의 퀘스트데이터파일은 한군데에만 저장되어 있더라도 그것을 처리하는 응용프로그램의 로직이 내부응용프로그램에서 다섯군대가 있다고 친다면 그 로직들마다 자료의 무결성을 보장하는 코드를 짜야 한다 또한 퀘스트파일이 변경된다면 그것을 처리하던 다섯개의 로직에서 그에 대한 예외처리를 모조리 해줘야 한다.

  예를 들면 이런것이다. 퀘스트 파일안에 퀘스트가 해결되었다면 0 퀘스트가 진행중이라면 1 퀘스트를 완료했다면 2라고 정했다. 그런데 갑자기 분기 퀘스트가 생기면서 1000의 자리는 퀘스트 실행중 뒤의 3자리를 분기가 생기는 퀘스트의 번호를 표기하기로 했다 1001 이런식으로 말이다. 이제부터 퀘스트 내부내용 데이터는 무조건 4자리의 정수여야 한다.

  그렇다면 결국 다섯개의 로직을 모두 그에 맞춰서 변경해야 한다 하지만 데이터 베이스에서는 무를 위한 제약을 한곳에서만 처리해주면 된다.


  5) 원자성(atomicity)

  플레이어가 NPC와 거래를 하면 게임은 다음과 같은 처리를 거친다.

  0. 플레이어의 아이템을 건네줄 수 있는지 확인

  1. 플레이어의 아이템 데이터를 삭제.

  2. 플레이어의 아이템 데이터 저장.

  3. NPC의 아이템 데이터 를 수정.

  4. NPC의 아이템 데이터 저장.

  그런데 게임 도중 3번 까지만 처리하고 갑자기 정전이 되어 게임이 종료가 됬다고 치자.

  다시 와보니 플레이어의 아이템만 사라지고 NPC는 아무런 변화가 없다. 퀘스트 아이템 이었는데!

  하지만 데이터 베이스에서는 트레젝션(=거래, transaction)이라는 개념을 도입하여 다음과 같은 과정이 생기지 않도록 한다.


  6) 동시접근 문제(concurrent acces anomalies)

  어떤 파일을 동시에 2개의 게임 쓰레드에서 수정하려고 한다면 파일 처리 방식에서는 자료의 값이 잘못 될수가 있다.

  하지만 데이터 베이스에서는 동시 접근 제어(concurrency control) 기능이 있어서, 동시접근 하면 순서를 지켜서 처리하도록 보장한다.


  7) 보안문제(security problems)

  파일처리 접근 방식에서는 자료에 대한 보안에 어려움이 있다 수많은 에디터를 통해서 파일을 에디팅하는 모습을 볼 수 있을 것이다. 하지만 서버와 DB를 통한 관리는 자료를 모두 한군데에 저장하고 사용자의 권한등을 자세히 정함으로서 자료의 보안을 쉽게 유지할 수 있다.

Posted by JJOREG

  프로그래밍 설계적인 부분이지만 어찌보면 기획적인 부분과도 연계된다.

  예를 들자면 이런 것이다.


  게임을 개발하는데 아이템 인벤토리 기능을 만들게 되었다.

  그럼 다음과 같은 스토리를 생각해야 합니다.


  사용자 스토리


  1. 사용자가 인벤토리를 열었을때 정수 X 정수 만큼의 아이템아이콘이 뜬다.

  2. 사용자가 인벤토리에서 아이콘을 클릭해서 빈공간으로 옮겨놓으면 순서에 상관없이 옮겨진다.

  3. 사용자가 아이템아이콘을 클릭하여 다른 아이콘으로 옮겨넣으면 인벤토리 안에서 아이템의 순서가 변경된다.

  4. 사용자가 정렬 기능을 누르면 아이템의 이름순으로 아이템이 정렬 된다.

  5. 사용자가 인벤 바깥으로 아이템아이콘을 놓으면 아이템 버리기 창이 나온다.

  6. 이외 등등....


  말그대로 사용자의 입장에서 인벤토리를 어떻게 사용할가에 대한 스토리를 작성하면 되는 것이죠.


  이런 사용자 스토리를 정할때 권장되는 개념적인 조건들이 몇가지 있습니다.

  1. 독립적인 Independent

  2. 절충 가능한 Negotiable

  3. 가치 있는 Valuable

  4. 예상 가능한 Estimable

  5. 간단한 Small

  6. 테스트 가능한 Testable

  첫글자만 따보면


  INVEST -> 투자가 됩니다.


  유즈 케이스는 액터가 달성하고자 하는 목적을 설명하는 내용을 담는 것을 말합니다. 

  액터는 시스템 외부에 존재하는 엔티티로 사람이나 장치 또는 다른 소프트웨어와 같이 상호작용을 시작하는 단위를 의미합니다.


  1. 사용자가 인벤토리 버튼을 누른다.

  2. 사용자의 아이템데이터를 기반으로 인벤토리 UI에 아이템이 배열된 상태로 디스플레이 된다.

  3. 사용자가 아이콘을 조작할 수 있다.

  4. 아이콘의 조작에 따라서 몇가지 아이템데이터의 이동 삭제 분류 등이 일어난다.

  5. 인벤토리 시스템은 자신을 통해서 펼쳐지는 동작을 서버에 보고하여 플레이어 아이템의 변경을 통보한다.


  이렇게 간단하게 표현할수도 있고 UML 유즈 케이스 다이어 그램 처럼 시각적인 표현을 사용할수도 있습니다.

  유즈케이스 템플릿등으로 표현할수도 있습니다. 유즈캐케이스 템플릿은 이렇습니다.


  이름 : 인벤토리 시스템

  버전 : 1.0

  설명 : 인벤토리를 통해서 사용자가 자신의 아이템을 조작할수 있다.

  목표 : 아이템을 버리거나 아이템 교체 아이템 정렬 등의 기능을 수행한다.

  결과 소유자

  1. 유저들은 자신이 현재 소유하거나 획득한 아이템을 볼 수 있다.

  2. 쓸모없는 아이템을 버리거나 우선순위에 따라 재배열 할수 있다.

  기본 과정

  1. 인벤토리를 통해서 아이템아이콘들을 인벤토리에 담아서 보여준다.

  2. 아이템 아이콘을 클릭 & 드래그하여 인벤토리 내부에서 조작할수있다.

  확장

  a. 아이템 아이콘을 서로 교체하면 순서가 변경된다.

    a-1. 빈공간은 빈공간 아이템아이콘으로 판단하고 서로 교체된다.

    a-2. 아이템 아이콘끼리의 교환이 있을 수 있다.

  b. 아이템 아이콘을 인벤 토리 바깥에 드랍하면 아이템을 버리게 된다

    b-1. 아이템을 실제로 버리겠냐는 메세지를 출력한다.

    b-2. 아이템의 종류에 따라서 버릴수 없는 아이템이 존재하면 아이템을 버릴수 없다는 메세지를 출력한다.

  트리거 

    인벤토리 열기 키를 누른다.

  후속조건

    없음.

   

'게임개발공부 > 프로그래밍의 의견들' 카테고리의 다른 글

프로그래밍 설계상의 부채  (0) 2014.07.29
밸런싱 관련 의견.  (0) 2014.01.11
소프트웨어 개발 프로세스 모델.  (0) 2014.01.09
의견 1  (0) 2013.11.27
Posted by JJOREG

처음 코드를 작성하는 것은 빚을 지는 것과 같다. 그리고 코드를 개선하는 것은 빚을 갚는 활동이다. 

약간의 빚을 지고 있는 동안에는 빚을 갚기 위한 개발이 가속화된다.

진정한 위험은 채무가 상황되지 않을 때 발생한다. 올바르지 않는 코드에 시간을 쏟는 일은 빚에 이자를 더하는 것이다.

완성도 낮은 코드로 인해 전체 엔지니어링 조직은 빚더미에 쌓인다.


문제는 거의 언제나 항상 제품 출시일 때문에 발생한다. 

다시 돌아가서 문제를 해결할 시간이 없다는 말이 있듯이 출시를 위해서 당분간 필요한 코드를 이리저리 조금씩 붙여 나가다가 어늗덧 감당할수 없게 된다.


프로그램이 빚더미에 앉았을 때 다음과 같은 징후가 발견된다.


취약성 

시스템의 내부로직과 의존할 뿐 누가 봐도 관련 없어 보이는 부분의 상세 구현 내용이 노출되거나 예상치 못한 부작용이 발생할 때 취약점이 느러나며 그 결과 코드를 변경할 때는 연관성이 없어 보이는 코드에서 사이드 이펙트가 발생한다.


경직성

유연하지 못한 소프트웨어는 변화에 큰 걸림돌이다. 실제로 잘못된 설계로 인해 작은 코드 변경에도 많은 노력이 필요하며, 보통은 비싼 비용이나 많은 시간, 위험 부담이 높은 리팩토링 등이 발생하기 때문에 새로운 변경을 위한 노력은 한없이 늦춰진다.


부동성

유능한 엔지니어는 소프트웨어를 안정적이고 유지보수도 쉽게 만들기 위해서 코드를 재사용 할수 있는 부분들을 먼저 찾는다. 하지만 이러한 노력도 특정 상황에만 해당되서 그 외에 재사용 할 수 없는 코드를 만나면 그 노력은 무용지물이 되고 만다. 주변 코드와 딱 달라 붙어서 아주 밀접한 관계를 맺는 코드를 구현한다거나 아니면 특정 도메인에 한정된 로직을 하드코딩하는 경우가 여기에 속한다.


비 이동성

팀원 중 딱 한명의 엔지니어만이 시스템의 특정 부분을 감당 할 수 있는 경우를 일컬어 비 이동성이라고 한다. 어떤 업무를 담당하는 사람은 그 기능을 처음 개발한 개발자이거나 불행히도 그 코드를 좀더 개선하고자 시도했던 사람 일수도 있다. 수많은 대규모 프로젝트에서는 모든 엔지니어가 프로젝트 전체를 구체적으로 이해한다는 것은 불가능 하지만 그렇다고 다른 개발자가 쉽게 코드를 이해하지 못하거나 효과적으로 요구사항을 반영하지 못하도록 영역을 나누는 것도 프로젝트에 결코 도움이 되지 않는다.

'게임개발공부 > 프로그래밍의 의견들' 카테고리의 다른 글

사용자 스토리 & 유즈 케이스  (0) 2014.07.30
밸런싱 관련 의견.  (0) 2014.01.11
소프트웨어 개발 프로세스 모델.  (0) 2014.01.09
의견 1  (0) 2013.11.27
Posted by JJOREG
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <d3d9.h>
#include <d3dx9.h>
#include <algorithm>
#include <iostream>
 
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
 
using namespace std;
 
float myVec3Length(D3DXVECTOR3* pSrcVec)
{
    float TempLength = 0.0f;
    //pSrcVec->
 
    TempLength = sqrt(pSrcVec->x * pSrcVec->x + pSrcVec->y * pSrcVec->y + pSrcVec->z * pSrcVec->z);
 
    return TempLength;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    D3DXVECTOR3 LenVector = D3DXVECTOR3(1, 2, 3);
 
    cout << LenVector.x << LenVector.y << LenVector.z << endl;
    cout << D3DXVec3Length(&LenVector) << endl;
    cout << myVec3Length(&LenVector) << endl;
 
    return 0;
}

 

벡터계산중 길이와 정규화 함수를 만들어 보았다.

 

 

Posted by JJOREG

제곱근에 대한 이해.

캐릭터와 캐릭터 사이의 거리를 구할때나 피타고라스의 정리의 루트를 제거하기 위해서 정말 많은 제곱근 함수를 사용합니다.

그러니 직접 구현해 보겠습니다.

 

일단 바빌로니아 법을 통해서 제곱근을 구하는 방식에 대해서 알아보겠습니다.

 

바빌로니아 법의 제곱근 구하는 공식 an+1 = (1/2) *(an + k / an)

'게임개발공부 > 직접 구현해 보겠습니다' 카테고리의 다른 글

STR 함수 구현  (0) 2014.07.09
Posted by JJOREG

strcmp와 strlen을 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// STRFUNC.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
 
#include "stdafx.h"
#include <iostream>
 
using namespace std;
 
int mystrlen(char* txt)
{
    int count = 0;
 
    while( *(unsigned char *) txt)
    { 
        ++txt;
        ++count; 
    }
 
    return count;
}
 
int mymystrcmp(const char *src, const char *dest)
{
  int ret = 0;
  while (!(ret = *(unsigned char *) src - *(unsigned char *) dest) && *dest) 
  { 
      ++src, ++dest; 
  }
 
  if (ret < 0)
    ret = -1;
  else if (ret > 0)
    ret = 1 ;
 
  return ret;
}
 
 
class CLASSA
{
public:
    int a;
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    char* txt0 = "1234abcaABCD";
    char* txt1 = "1234abcaABCD";
    char* txt2 = "1234abcf";
    char* txt3 = "1234,abcd,ABCD ";
    char* txt4 = "1234abcaABCDc";
 
    const int a = 0;
 
    int max = strlen(txt0);
    cout << max << endl;
    max = mystrlen(txt0);
    cout << max << endl;
 
    int cmp = strcmp(txt0, txt1);
    cout << "같다 " << cmp << endl;
    cmp = strcmp(txt0, txt2);
    cout << "짧다 " << cmp << endl;
    cmp = strcmp(txt0, txt3);
    cout << "길다 " << cmp << endl;
    cmp = strcmp(txt0, txt4);
    cout << "길이는 같다 " << cmp << endl;
 
    cmp = mymystrcmp(txt0, txt1); 
    cout << "같다 " << cmp << endl; 
    cmp = mymystrcmp(txt0, txt2); 
    cout << "짧다 " << cmp << endl;
    cmp = mymystrcmp(txt0, txt3); 
    cout << "길다 " << cmp << endl;
    cmp = mymystrcmp(txt0, txt4); 
    cout << "길이는 같다 " << cmp << endl;
 
    return 0;
}
 
 


'게임개발공부 > 직접 구현해 보겠습니다' 카테고리의 다른 글

sqrt 제곱근 구하기.  (0) 2014.07.10
Posted by JJOREG

AGP메모리


물음들 : 로컬(비디오) 메모리는 쓰기 속도가 느려서 잦은 갱신에는 적합하지 않고, 시스템 메모리는 그래픽카드쪽에서 읽는게 느려서 문제입니다. 그걸 해결하기 위한게 AGP메모리입니다.


꼭 그렇지는 않습니다. 사실 로컬(비디오) 메모리로 데이터의 Burst 전송이 AGP를 통해 필요할때마다 께작께작 가져가는 데이터보다 더 효율적이리라 추측하고 있습니다. 일단 같은 AGP를 통해 전송되고 한번에 많은 데이터를 보낼경우 주소나 정보를 Burst 해서 보낼 수 있으니까요. 그렇지만 한번 쓰고 버릴 Dynamic 데이터들을 비디오 카드로 전송해서 복사본을 만든다음 쓰는 것이 비효율적이기 때문에 AGP메모리가 사용됩니다. 


참고로 시스템 메모리는 그래픽 카드에서 바로 접근이 불가능합니다. 대부분 H/W들이 그렇지만 I/O 버스와 메모리 버스가 100% 맵핑되는 경우가 없고 데이터 전송에는 DMA에 그외 비슷한 특별한 조치가 필요한 것이죠. AGP 메모리가 그런 특별한 조치중 한가지로 시스템에서 허용한 메모리에 대해 CPU의 도움 없이 그래픽 카드가 멋대로(임의로?) 데이터를 읽어올 수 있는 획기적인(은 아닌것 같지만) 구성입니다. 시스템 메모리의 데이터를 특별한 방법을 사용하지 않고 그래픽 카드로 전송하려면 CPU의 보조가 필수적입니다. 


물음들 : AGP메모리는 일반 램에 영역을 잡아주는 것으로, CPU에서 쓰기속도와 그래픽카드쪽에서 읽기 속도(로컬 메모리보단 약간 느립니다.)가 빠릅니다. 대신 CPU에서 읽기속도는 느리므로 읽는 처리시에는 시스템 메모리가 좋겠지요.


하드웨어에 따라 다르지만 AGP 메모리보다 로컬(비디오) 메모리가 '매우' 빠릅니다. AGP 2X가 533MB/s 정도이고 8X가 대략 2GB/s 정도인데 GeForce 6800 Ultra 의 경우(사악한 비교대상입니다.) 33.6GB/s 의 내부 전송률을 갖고 있습니다. 뭐 하급 기종으로 가면서 절반, 또 절반씩 깍이는 속도이긴 하지만 절반이라 하더라도 AGP 8X의 무려 8배에 달하는 속도를 갖고 있습니다. 게다가!!! AGP 메모리는 시스템 메모리이기 때문에 CPU의 작업률이 올라가면 덩달아 AGP의 효율도 떨어지게 됩니다. 


그리고 AGP 메모리는 캐쉬가 되지 않는 메모리입니다. 간단히 말해서 CPU 캐쉬가 작동하지 않고 작은 메모리 단위로 여러번 읽어올 경우(C/C++코드를 생각하면 곤란하고 어셈 코드단위로 생각하세요.) 캐쉬가 작동하지 않기 때문에 물리적(전기적)으로 메모리에 여러번 접근을 하게 됩니다. 캐쉬를 쓰고 있을때는 크게 느껴지지 않지만 물리적인 메모리에서 데이터를 가져오는 시간은 수십 클럭 이상이 걸리기 때문에 4바이트 또는 12바이트 단위로 데이터에 접근할 경우 4바이트당 수십 클럭을 소모하게 됩니다. PCI도 크게 다르지 않은데 DDraw를 쓰면서 Surface 데이터를 바로 읽어서 알파 블렌딩을 해보신 분들은 무슨 뜻인지 금방 이해 하시리라 생각됩니다.


(메모리 구입시 4-4-4-12 같은 숫자가 바로 이 접근시 걸리는 시간입니다. 최악의 경우 '전부 더한다'정도의 메모리 클럭을 먹는다고 생각하시면 됩니다. CPU는 메모리 버스 클럭의 수배에서 수십배의 속도를 갖고 있으니 최악의 경우 4바이트 접근에 수백 CPU 클럭이 사용될 수도 있습니다.) 


p.s.AGP로 데이터 쓰기 작업에는 WC 버퍼라고 하는 녀석이 쓰여서 쓰기 속도 저하를 상당히 막아주고 있죠. 작은 쓰기 전용 캐쉬 같은거죠.

Posted by JJOREG

다음의 코드를 보자



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
 
int main (void)
{
 
 const int b = 100;
 
 printf("%d\n", b);
 
 int* temp = const_cast<int*>(&b);
 
 *temp = 200;
 
 int* temp2 = temp;
 
 printf("%d\n", b);
 printf("%d\n", *temp);
 printf("%d\n", *temp2);
 
 int* temp3 = const_cast<int*>(&b);
 
 printf("%d\n", *temp3);
 
    return 0;
 
}

const_cast는 참조형의 const나 휘발성을 제거해주는 캐스트방식이다. 즉 위의 const int b는 값형이므로 언뜻보면 캐스트가 안될 수 있지만.
실제 출력되는 값은 temp2의 값이 200으로 변환되어서 컴파일까지 잘 된다.
이게 왜 되는 것인가? const int b의 값을 바꾸는게 되는것인가?
이유는 컴파일러에 있다고 본다. const int b라고 되어있는 부분은 컴파일 시점에서 const int b가 되는 것이 아니라. 100으로 치환되기 때문에 값의 변경과 상관 없이 100의 상수값으로 변경된 것이고 그렇기 때문에 후에 변경하는 값은 b의 값을 아무리 출력해도 100이라는 상수값으로 대체되었기 때문에 100으로 출력되는 것으로 보인다.


Posted by JJOREG