반복 행동의 이해. loop, while, foreach

반복 행동의 이해. loop, while, foreach

코딩이라는 것을 처음 접하면 만나게 되는 것이 바로 어떤 행동을 여러 번 동작하게 만드는 반복문을 배우게 된다.

인터넷에 나오는 문서들을 따라서 치다 보면, 자연스럽게 이해가 가기도 하고 그렇지 않으면, 100 번이고 1000번이고 다양한 문제들을 풀어가면서 이해하는 방법을 추구하는 곳도 있다.
물론 틀린 방법은 아니지만 이와 같은 방법이 효율이 높지 않다.

굳이 위와 같이 어렵게 접근하지 않고기초적인 항목들을 생각해 본다면, 1~2번만 해도 충분히 이해가 가능한 것이 프로그래밍 언어다.
물론, 빠르게 잘 사용하려면 반복 연습을 통하면 되겠으나, 이해를 바탕으로 100번의 연습과 오직 느낌으로 100번 시도하는 것은 효율이 다르다.

프로그래밍을 하고 싶다면 기본, 기초에 접근하려 노력해야 한다.
더 이상 분해나 쪼갤 수 없을 때까지, 혹은 더 이상 생각해 낼 수 없을 때 까지 생각의 연결 고리를  찾아가야 한다.
그래야만 몇 년 후에 만나게 될 벽을 넘어설 수 있다.

어떤 것을 이해하려면 "정의-Definition" 또는 "선언-Declaration" 을 찾아내는 과정이 필요하다.
하지만 익숙하지 않다면 쉽게 생각해낼 수 있는 단순한 사례를 들어 생각해 보는 연습을 해 보는 것이 쉽다.


사례, Case

트럭에 짐을 10개 싣는 목표를 세워보자.
매우 쉬워 보이는 예시다.
한눈에 봐도 너무 쉬워 보이지만, 이 행동을 자세히 들여다 보면 그리 쉽지 않은 여정이 될 것임을 약속한다.

당신이 짐을 직접 트럭에 실어 보자.
짐 1개를 잡은 다음에 트럭에 싣자.
이제 9번만 더 하면 될 거 같다.
끝.
여기서 당신이 한 행동을 좀 더 자세히 살펴보면 아래와 같다.

  • 바닥에 있는 짐을 1개 손으로 잡는다
  • 짐을 들어, 트럭에 내려 놓는다.
  • 바닥에 있는 짐은 1 개가 줄었다. 트럭에는 1개의 짐이 늘어 났다.
  • 당신은 1개를 옮겼다는 기억을 했다. 
  • 이제 9개만 더 하면 끝이라는 생각을 했다.
  • 그리고 다시 처음부터 이를 반복한다.

연습, Practice

위의 사례에서 보통 우리 일상생활에서 간과했던 것들을 발견했다.
기억이라는 무의식적으로 다루고 있던 임시 저장소의 역할이다.
현대 시대의 프로그래밍이란 존재하지만 우리가 느끼지 못했던 사항들을 인지해야 한다.
그리고 당신이 대단한 무엇을 만들고자 꿈에 부풀어 해보자 한 것이라면 생각보다 많은 것을 인지하고 조정해야 한다.

질의와 응답을 통해 인지의 영역을 넓혀 보자.

  • 우리가 옮기고자 하는 짐은 어떻게 있는가?
    - 우리가 원하는 대상이 어떠한 형태로 어디에, 얼마나 있는가?
    - 짐은 바닥에 존재. 바닥은 일정한 저장 공간
    - 옮기기 위한 짐은 몇 개나 있는가? 모자라지는 않는가?
  • 짐을 어디에 옮겨야 하는가?
    - 트럭이라는 공간
  • 짐은 어떻게 옮기는가?
    - 손으로 집어서 바닥에서 트럭으로, 아래에서 위로 이동 시킨다.
    - 바닥 > 손 > 트럭으로 공간 이동을 한다.
  • 짐을 얼마나 옮겨야 하나?
    - 총 10개의 짐을 옮길 것이다.
    - 1번에 1개의 짐을 옮길 수 있다.
    - 그래서 총 10회 짐을 옮겨야 한다.
  • 짐을 싣는 행동 중에는 어떤 생각을 해야 하나?
    - 언제까지 옮겨야 하지? , 언제 끝나지?
    - 언제부터 옮겨야 하지?
    - 얼마나 옮겼더라? 

이 단계에서 인지도 중요하지만 한계를 생각하는 것도 나중에 큰 도움이 된다.
물론 지금은 필요 없다. 굳이 한계 또는 제약들을 생각, 즉 선언(Declaration) 해 본다면 아래와 같다.

  • 짐 모양은? 원형? 마름모꼴 막대기 모양... 
    선언 : 그냥 손으로 옮기는데 문제가 없다고 정하자.
  • 짐 무게는? 
    선언 : 손으로 들 수 있다.
  • 바닥의 짐과 트럭에는 접근할 수 있는가?
    선언 : 손을 뻗으면 닿는 곳에 짐과 트럭이 존재한다.
  • 옮기는데 시간은 ?
    선언 : 손으로 잡고 들고 놓고 하는 모든 행동은 시간이 0초 걸린다.
  • 트럭에 공간은 충분한가?
    선언 : 트럭에는 무한한 공간이 있다.
  • 몇 개나 옮겼는지 기억하는 시간과 여유는 충분한가?
    선언 : 당신의 머리는 숫자를 생각하고 기억하기에 충분한 지능이 있고, 자연수 숫자 체계의 기본을 이해하고 있다. 

구현/실현, Implementation

질의 응답을 통해 얻어낸 지식을 바탕으로 반복문을 프로그래머 답게 만들어 볼 수 있다. 그리고 한계와 제약은 우리가 스스로 정했으니 배제할 수 있다.

동, 서양 미 유럽 국가에서는 프로그래밍의 코드를 표현하는 순서를 인지해야 한다. 예를 들어, 일본의 고 서적은 우측에서 좌측 그리고 위에서 아래로 서술 된다. 이는 우리가 내용을 보고 이해하는 방향과 차이가 있다. 코드는 왼쪽에서 우측, 위에서 아래로 서술 되며 진행 방향도 이에 따른다.

[ 트럭에 짐 옮기기 행동 ]

순서 분류 구체적인 행동
1 조건(상태) 확인 바닥에 옮길 짐이 있다.
2 행동 바닥에서 짐을 뺀다, 짐을 바닥에서 손으로 이동시킨다
3 행동 트럭에 짐을 싣는다, 손에서 트럭으로 짐이 이동한다
4 행동 1개 옮겼다고 생각하기 시작한다, 머리 속에 숫자 하나를 넣고 옮길 때마다 1씩 더해 나간다
5 조건(상태) 확인 10개를 옮겼는가?
6 조건 + 행동 아직 10개를 옮기지 않았다면, 1번으로 행동을 시작하자.
7 조건 + 행동 10개를 다 옮겼다면, 행동을 종료하자.

정의와 선언, Definition & Declaration

간단한 인지 과정과 구현을 통해 반복의 과정이 어떻게 진행되는지 이해했는가?
여기서 멈추지 않고 아래와 같이 구체적인 서술을 통해, 프로그래밍을 하기 전에 확립해야 하는 요소를 생각해야 한다. 

  • 행동은 반복될 수 있다.
  • 행동은 여러가지의 기초 행동을 묶음을 의미하기도 한다. 즉 1개 또는 N 개의 기초 행동 또는 복합적인 행동들의 묶음이다. 
  • 반복은 횟수가 존재한다. 1번, 2번, ..., N번 만큼 우리가 의도하는 회수를 내포한다.
    자연수 숫자 체계를 활용한다
  • 행동은 우리가 원하는 바에 따라 항상 같거나 다르게 만들 수 있다.
  • 행동에는 어떠한 대상이 존재할 수 있다.
    예를 들어 숫자를 세는 행동을 한다면, 대상은 숫자다.
  • 행동의 이전과 이후에는 결과, 즉 상태가 존재한다.
  • 상태가 존재하려면 유지하기 위한 공간이 존재한다. 공간은 필요한 만큼 안정성을 가져야 한다.
    썩은 상태의 사과는 썩다 상태와 사과 공간이 동시에 존재한다.
  • 상태는 행동이 반복되면 변화가 일어날 수 있다.
  • 변화가 반복 하여 완료된 상태가 우리의 결과라고 볼 수 있다.
  • 상태는 행동이 반복하기 전과 후로 나뉠 수 있다. 아무런 행동도 하지 않은 상태를 초기 상태라고 이야기할 수 있다.
  • 조건은 어떤 상태를 우리가 원하는 결과와 비교하는 판단의 기준이다

표현/코딩, Coding

언급했던 내용들을 프로그래밍 언어의 형식을 이용해 순서에 따라 나열을 하면 끝이 난다.
필요한 요소들을 분류하자.
프로그래밍 언어는 영문자와 기호로 표현한다.
모든 문자열이나 행동은 시작/종료, 처음/끝이 필요하다.
인간들 사이의 대화가 언제 시작하고 끝이 나는지 생각해보면 쉽다.

즉, 범위라는 개념이 우리의 무 의식에서 작동하는 것을 생각해낸다.
최소한의 행동들의 구분은 ; (Semi-colon) 으로 구분하고, 그 행동들의 묶음을 { ... } 으로 표현이 가능하다.
이는 프로그래밍 언어마다 전부 다르다.
하지만 어떤 언어든, 범위 개념은 필요하다.

  • 공간 : 바닥, 손, 트럭
    land, hand, truck, [ ... ] ( 공간 의미 자체를 표현 )
  • 대상 : 옮기는 짐, 기억하는 숫자 (자연수)
    box, moveCount
  • 행동 : 짐을 공간 사이에서 이동하는 행위, 숫자를 세는 행위, 더 이상의 진행 중단하고 범위를 벗어나는 행위.
    <- ( Assign ), + ( Count Up ), LOOP { ... 반복 행동 ... }, BREAK
  • 조건 : 옮긴 짐의 숫자와 원하는 이동 숫자와의 비교
    10, == ( Is Equal ), IF ( 만약, Condition .. )
  • 상태 : 짐을 옮기기 시작/도중/완료 후의 대상들의 상황
    시간이 지남에 따른 공간, 대상들의 모든 상황을 추상적으로 표현

[ 추상적인 프로그래밍 언어, PSuedo Code ]

  
// 초기 상태
// 바닥이라는 공간에, 짐(box) 가 10개가 존재.
land <- ['box','box','box','box','box','box','box','box','box','box'];
truck <- []; // 트럭이라는 공간 존재, 그 공간은 비어 있다.
hand <- []; // 손이라는 공간, 마찬가지로 비어 있다.

// 머리속에 옮긴 짐의 개수를 생각해놔야 한다.
moveCount <- 0; // 아직 짐을 옮긴 적이 없다.

// 준비가 끝났다. 짐을 옮기자.
LOOP {
  // 바닥에서 손으로 1개의 짐을 옮겨야 한다.
  // 상상을 해보자. 짐을 던지든 어떤 방식이든, 짐은 바닥에서 손으
  // 이동시간이 0초로 우리가 선언했기 때문이다.
  hand <- land.get(1);
  truck <- land.get(1);
  // .get(1) 이라는 표현은 빠질 수가 없다. 짐을 1개씩 빼서 이동한다.
  
  // 짐을 옮겼으므로, 머리속의 숫자를 증가시키자.
  // 숫자를 증가시킬때 어떻게 증가 시키는가? 기존에 기억하던 숫자
  moveCount <- moveCount + 1;
  
  // 짐을 얼마나 옮겼는가? 다 행위를 언제 끝낼지 우리는 항상 확인
  // 조건을 판단하고, 원하는 행위를 서술한다.
  IF ( moveCount == 10 ) {
    STOP; // 이 문장을 만나면, 더 이상 아래의 코드(행위)는 보지 않는다
  }

  // 조건이 불일치 한다면 이곳까지 (위->아래 이므로) 왔다.
  // LOOP 범위에서 약속은 다시 범위의 처음으로 돌아가서 같은 행동
}
  
// 위의 LOOP 의 범위를 벗어나서 이곳에 도착했다면, 프로세스는 종료한다