Study- MSC/Computer2010. 9. 18. 00:08

최근 프로젝트 관리에 대한 지식의 필요성을 많이 느꼈다.
그래서 어떻게 공부해야 할까 조언을 구하려고 채흥석 교수님께 메일을 보냈다.


그리고 그 답변



오타도 있는데, 수정하지 않았다.
잘 모르겠지만 뭔가 방향을 잡을 수 있을것 같다. 오늘 단번에 리팩토링 관련 책을 빌려서 읽고 있다. 

대단한건 새벽 두시 반에 보냈는데, 답변이 온 시각이 세시 반 조금 안되어서였다. 그때까지 작업하고 계신건가..

아무튼 제대로 공부해 보자. 
Posted by 머리
Study- MSC/Computer2010. 8. 7. 02:57
Posted by 머리
Study- MSC/Computer2010. 7. 25. 23:45
Posted by 머리
Study- MSC/Computer2010. 7. 19. 16:49
Operating System Concepts- Chapter9. Virtual Memory

Posted by 머리
Study- MSC/Computer2010. 7. 17. 02:12
Operating System Concepts. Chapter 8 - Memory Management
Posted by 머리
Study- MSC/Computer2010. 6. 21. 19:43
Operating System Concepts - Chapter3. Process Concepts
Posted by 머리
Study- MSC/Computer2008. 12. 21. 18:29
  자, 하나의 CyberSociety를 만든다고 하자. 뭐 도시든 농촌이든 어디든 상관없지만 그냥 도시로 한정지어보자. 수많은 것들이 있을 것이다. 건물, 자동차, 기계 기타 등등.. 결국 도시의 대부분의 것들은 인간이 만든 것이니 가상으로 구현이 가능할 것이다.(Emulation) 현실에선 불가능할지 몰라도 라플라스의 괴물 등의 이론을 컴퓨터 상에서는 어느정도의 구현을 할 수 있을 테니까.

  문제는 그 가상의 도시에서 살고 있는 인간을 어떻게 만들어 볼까 하는 것일 것이다. 사실성 있게 구현하고자 한다면 단순한 패턴의 반복으로 움직이는 가상의 인간은 재미가 없겠지. 각종 상황에 대해 보고,판단하고,행동해야 할 것이다.

1. 본다
  우선 인간은 모든 행동을 '본다'에서부터 시작해야 할 것이다. 뭐 그냥 바로 판단후에 행동할 수도 있겠지만 대부분은 본다에서 시작할 것이다. 보는 행동을 통해서 다음 행동에 대한 판단을 위한 정보를 얻고 필요하다면 기억도 할 것이다.

2. 판단한다
  정보를 얻었으면 다음 행동을 어떻게 해야 할지 생각을 해야 할 것이다. 이 판단은 기존에 비슷한 상황에 대한 기억이나 학습한 내용을 참고하거나 새로운 상황이면 찍던지(?) 다른 방법을 취하도록 해야 할 것이다. 판단이 내려졌으면 행동에 옮기게 할 것이다.

4. 행동한다.
  판단까지 내려졌으면 그 판단대로 행동을 할 것이다. 여기서 '행동'이란 단순한 움직임뿐만 아닌 광범위한 의미의 '행동'을 의미한다. 영어로 말하자면 Do? 위치의 이동이나, 운동상태의 변화(걷기->달리기), 목소리의 변화(침묵->소리지름) 기타 등등.. 이런 것들에 대한 범위를 정하자면 너무나도 힘들겠지만 구현을 하기 위해서는 어느 정도 이상의 범위는 포함해 주어야 할 것이다.

  이런 행동까지 하게 되면 그 결과에 대해 다시 보고 판단하고 (필요하면 기억하고) 또 다음 행동을 할 수도 있을 것이다. 마치 피드백작용이 일어나듯이.
 
  아주 간단하고 일부분의 구현에 대한 생각을 적어 보았는데도 꽤 쓸게 많아졌다. 음.. 과연 실제로 구현해보고자 한다면 어떻게 될까? 재밌겠는데?
Posted by 머리
Study- MSC/Computer2008. 10. 24. 19:48
  이번 포스팅에서는 동적할당을 객체의 생성쪽으로 확장해 보고자 한다. 먼저 말해두지만 이 포스팅은 포인터나 객체, 클래스를 설명하기 위한 포스팅이 아니다. 어디까지나 이런 사항에 대한 기본적인 지식은 알고 있다고 가정하고 진행하겠다. 우선 C++에서 Example이라는 클래스가 있고, 그것에 대한 객체를 생성해 보자.

Example ex;

  자. ex라는 객체가 생성되었다. 아마 특별한 문제 없이 제대로 돌아갈 것이다. 그리고 파괴도 잘 될 것이다. 하지만 이런 방식의 객체 생성은 권하고 싶지 않다. 대신 이런 객체의 생성을 권한다.

Example* pEx = new Example();

  위 방식은  Example라는 클래스 형식으로 메모리 공간에 할당을 한 후 그 주소를 pEx 포인터 변수에 넣어서 사용하게 하는 방식이다. 앞선 포스팅에서, 메모리의 어딘가에(HEAP) 공간을 할당한다고 했는데 위 방식도 바로 이런 방식이다. 이렇게 해 놓으면 이어서 이렇게도 가능하다

Example *pEx = new Example();
pEx = new Example();

  잘 이해가 가지 않을것이다. 무슨 이야기냐면 한 객체를 메모리에 생성하여 한 포인터에 주소를 기억시켰는데, 그 포인터를 재사용하여 또다른 객체를 또 생성하여 그 주소를 넣을 수 있다는 이야기이다. 물론 위 코드는 첫 객체의 해제에서 문제가 발생하지만 이런식으로 좀 더 코드에 유연성을 줄 수 있다. 그렇지 않으면 Example ex1,ex2; 등의 방식으로 객체를 생성해야 하는 문제가 발생한다.
  앞서 말한 유연성 외에도 이런 방식의 동적 할당을 통한 객체 생성은 맨 처음 말한 동적할당의 장점을 최대한 살릴 수가 있게 된다. 객체는 일반 변수보다 여기 저기서 사용될 가능성이 많다. 무슨 말이냐면 지역 변수 이상의 용도로 사용될 가능성이 많다는 이야기이다. 만약에 게임을 만들때 적을 표현하는 클래스가 있고 그 객체를 생성한다고 하면 상황에 따라 계속해서 적을 만들어 내야 하므로 동적 할당이 필요 할 수 밖에 없다.(int형으로 적을 표현할수는 없지 않은가?)
  이제까지는 객체를 동적할당 할 때 포인터를 이용하였다. 그 이유는 C++은 기본적으로 Call by Value 방식이기 때문이기 때문인데 이는 변수 및 객체의 사용을 한정적인 위치에서만 사용할 수 밖에 없게 만든다. 이 틀을 극복하기 위해서 메모리상의 주소로 읽기 위한 포인터가 사용되는데, 여기서 한단계 더 나가서 레퍼런스라는 개념이 나온다. 적어도 여기서는 Call by Reference와 Call by Address의 개념을 다르게 두자. Call by Address는 결론적으로는 포인터의 값을 이용한 Call by Value로 볼 수 있다. 엄밀하게 말하면 Call by Reference와는 다르다.(물론 내부적으로 이놈도 포인터를 쓰긴 쓴다.)
  말이 샜는데, C++ 이후의 객체 지향 언어는 기본 참조 방식을 Call by Value가 아니라 Call by Reference를 채택한 경우가 많다. JAVA가 그렇고, C#이 그러며, 심지어 Visual Basic도 Call by Reference가 기본이다.
  무슨 말이냐면 만약에

Example ex;

라는 코드가 있으면 C++에서는 ex가 객체 그 자체이지만 JAVA나 C#등에서는 저것은 그냥 참조를 위한 레퍼런스에 불과하지 객체 자체는 아니다. 즉 아무것도 못한다. 레퍼런스는 포인터처럼 메모리 상의 어떤 것을 가리켜야 그 의미가 있다. 즉

Example ex = new Example();

  와 같이 객체를 생성하고 그것을 참조하여야 한다.
  말이 많았다. 정작 하고 싶은 말은 '동적할당은 메모리 어딘가에 공간을 할당하고 포인터를 이용하여 그것을 참조한다, 그리고 이는 객체에서도 마찬가지이며 좀더 나아가 레퍼런스는 참조 없이는 아무런 의미가 없다'였는데 이것을 표현하기 위해 쓸데없는 말이 너무 많았던 것 같다.
  아무쪼록 이 글을 읽고 뭔가 '아!'하고 깨달음(?)을 얻는 프로그래머 지망생이 있으면 좋겠다. 그렇게 기원하면서 이상 3회에 걸친 포스팅을 마치고자 한다.
Posted by 머리
Study- MSC/Computer2008. 10. 22. 19:52
  앞선 포스팅에서 잠깐 배열의 고정성을 대체하는 방법으로 동적 할당이 있다는 이야기를 하였다. 이번 포스팅에서는 동적할당을 어떤식으로 사용하게 되는가에 대해서 이야기할 것인데, 그 전에 잠깐 포인터에 대하여 짚고 넘어가자.
  포인터는 크게 두 가지의 의미를 가지고 있다. 첫째, 메모리 주소 그 자체. 둘째, 그 메모리 주소를 가리키는 포인터 변수. 결국은 같은 용도이다. 일반적으로 int a와 같은 방식으로 변수를 선언하면 그 메모리 주소에 대해서는 관심을 가질 필요가 없다. 그냥 변수 이름만 알고 있으면 얼마든지 그 공간에 접근 할 수 있기 때문이다. 하지만 변수의 지역성 등의 문제로 외부 블록에서 한 변수의 공간에 접근하고 싶다면 그 공간의 주소, 즉 포인터를 사용할 수 밖에 없다.(이는 포인터의 사용의 한 예에 불과하다.) 이렇게 어느 메모리의 주소를 얻고 사용할 필요가 있게 된다면 포인터 변수를 이용해서 원하는 곳의 포인터를 얻어서 사용 할 수 있다.(포인터에 관한 자세한 설명은 하지 않겠다. 문법책을 참고하자.)
  자, 위에서 중요한 말을 하였다. '어느 메모리의 주소를 얻고 사용하려면 포인터 변수가 필요하다.' 그런데 분명 일반적인 변수를 생성하면 그 주소에는 관심이 없어도 된다고 하였는데 왜 굳이 주소가 필요한 것일까? 맞는 말이다. 분명 그렇게 따지만 필요할 경우는 외부 블록에서의 필요성을 제외하면 굳이 필요가 없다. 이런 방식이 가능한 이유는 일반적인 변수를 만들 때에는 어느 상황에서든 항상 일정한 '규칙에 맞게' 메모리 주소에 접근하기 때문에 그 규칙만 알면 접근이 가능하기 때문이다.(Stack 이야기를 하는 것이다.) 예를 들어 a라는 주소를 가진 곳에서부터 시작해서 10개의 정수형 배열을 만든다면 a부터 a + sizeof(int)*10 까지 메모리 공간을 주어주면 된다. 우리가 '그 크기'와 '언제 변수를 선언하는지' 알기 때문에 이런 식이 가능한 것이다.
  그러나 '언제' 변수를 만들지 모르고 '얼마나'크기를 설정 할 지 모른다면? 이런 경우에는 어쩔수 없이 메모리 중 빈 공간에(HEAP) 메모리를 할당 할 수 밖에 없다. 그런데 문제는 메모리 공간을 할당해 놓고 어디다 해 놓았는지 모른다는 것이다. 이럴 때 포인터를 이용 할 수 있다. 말이 조금 복잡해졌다. 다음 코드를 분석하면서 한번 정리해 보자.

int score[10];
printf("10명의 점수를 입력해 주세요 : ");
for(int i = 0 ; i < 9 ; i++) scanf("%d",&score[i]);

  자 위 코드는 '10개'라는 고정된 점수를 저장하는 변수를 배열로 만들어 놓고 10번 점수를 입력받는 것이다. 이런 경우에는 10개 이상으로는 받을 수 없게 되고 10개보다 적은 갯수를 받게 되면 나머지 공간은 낭비하게 된다. 우리는 이런 경우를 별로 원하지 않을 것이다. '몇 개를 입력받을지 입력받고 그 갯수만큼만 받는 것은 어떨까?' 다음 코드를 보자.

int num;
int *score;
printf("몇 명을 입력받으시겠습니까? : ");
scanf("%d",&num);
score = malloc(sizeof(int) * num);
printf("%d명의 점수를 입력해 주세요 : ",num);
for(int i = 0 ; i < num ; i++) scanf("%d",&score[i]);

  달라진 것은 몇명을 받을 것인지 저장하는 num변수를 만들고, 그 num만큼 공간을 할당한 후 그 공간만큼만 입력을 받은 것이다. 중요한 것은 malloc라는 함수로 원하는 크기만큼 메모리를 할당받았다는 것이다. 그런데 문제는 이 malloc으로 할당한것은 좋은데 어디다가 해 놓았는지 모른다. 그래서 malloc 함수는 할당 한 후 그 메모리 주소를 리턴하고, score라는 포인터 변수는 그 변수를 받는다. 
  이렇게 생각하자. 동적할당을 했다면 메모리 어딘가의 빈 곳(실제로는 방식이 있지만 이 포스팅의 범위를 벗어나므로 언급하지 않겠다.)에다가 할당해 버린다. 그 곳이 어디인지 즉 어느 메모리 주소인지는 알 수 없다. 다만 할당하는 순간에는 어디인지 알 수 있기 때문에 그 주소를 변수에다 넣게 되는 것이다. 이 변수가 바로 '포인터'변수이다. 포인터는 아까 메모리 주소라고도 이야기 했다. 이것은 일반 변수가 아닌 포인터 변수에만 넣을 수 있기 때문에 score라는 포인터 변수가 필요한 것이다.
  조금 이해가 가는가? score = malloc(sizeof(int) * num);에서 score = malloc();라는 부분을 잘 관찰하자. malloc로 어딘가에 메모리를 잡아 놓고 그 주소를 score에다가 넣어 놓았다. 이렇게 해 놓지 않으면 그 이후에는 절대 어디다 잡아 놓았는지 알 수 없다.
  말이 복잡해졌다. 언제 시간 내서 다시 한번 더 이해하기 쉽도록 포스팅을 수정해 보아야 겠다.(원래 진리일수록 간단할텐데 말이다.) 다음 포스팅에서는 이 동적할당의 개념을 확장시켜서 레퍼런스와 객체의 생성에 대해서 이야기 해 보겠다.
Posted by 머리
Study- MSC/Computer2008. 10. 21. 19:55
  C하면 포인터가 문제라고 한다. 사실 난 포인터를 배울 때 다른 부분에 비해 고생은 했지만 그렇다고 그렇게 힘들게 느끼진 않았다. 다만, 많이 헷갈렸던 부분은 바로 동적 할당이라는 부분이였다. 처음에 동적할당 자체를 공부하고 활용할때는 그리 어렵지 않았는데, 객체지향이라는 개념을 공부하기 시작하면서 혼란스러워지기 시작했다. 그동안 인식하고 있던 개념 자체가 흔들렸었던 것 같다.
  그 이후에 어느정도 안정(?)을 찾으면서 생각하길 이 동적할당과 관련된 부분을 이해하면 포인터도 큰 고비는 넘길 수 있겠고 객체의 사용에서도 많은 도움이 될 것이라고 생각했다.
  그래서 2~3개의 포스팅(또는 더 많이)을 통해서 이 동적 할당과 관련된 부분을 한번 이야기 해보자 한다.
  그 첫번째 포스팅으로, 메모리의 사용에 관한 간단한 이야기를 해보자 한다. 메모리, 간단히 '기억하는 공간'이다. 무엇을? 그 무엇이든. 예를 들어 정수 하나를 기억하는 공간을 만들고 싶다. 그러면 'int a'라고 a라는 정수형 변수를 만들면 된다. 다른 것 없다. 그리고 이 a라는 이름을 가진 공간은 '메모리 어딘가'에 sizeof(int)만큼 차지하고 있을 것이다. 
  이 '메모리 어딘가'를 어떻게 알까? 바로 메모리 주소로 알 수 있다. 그런데 이 메모리 주소를 우리가 일일히 기억하고 있어야 할까? 그럴 필요 없다. 다만 우리는 그 주소 대신 a라는 이름을 알고 있기 때문이다. a라는 별명의 주소에 있는 공간에 '4'라는 데이터를 넣고 싶다면 그냥 a = 4라고 해 주면 되고 읽고 싶으면 a라는 공간에서 꺼내 읽으면 된다.
  그리고 배열이라는 것이 있다.(배열에 관한 설명은 하지 않겠다.)이 배열은 메모리에 연속된 공간을 할당해서 데이터를 구조적으로 관리 할 수 있게 된다. 하지만 배열의 단점은 그 크기가 항상 고정되어 있다는 것이다. 학생의 성적을 관리 하는 프로그램을 만들기 위해 학생 수만큼 변수를 만들고 싶은데 그 수가 일정하지 않다면? 이런 방식에서는 배열은 좋은 방법이 아니다. 
  그럼 배열을 대체할 다른 메모리 사용 방식은 뭐가 있을까? 바로 동적 할당을 이용하는 것이다. 이 동적 할당에 관한 이야기는 다음 포스팅에서 포인터의 사용과 함께 같이 언급해 보겠다.
Posted by 머리