메가테라 3주차 강의 요약

샨티(shanti)·2022년 5월 23일
0

TIL

목록 보기
135/145
post-thumbnail

메가테라는 매 주 금요일 오후 6시에 주말동안 들어야 할 아샬님의 강의를 오픈합니다.
주말 내도록 강의를 충분히 듣고, 필기&질문 목록을 만들고 난 뒤에
이어지는 월~금요일동안 주어진 과제를 수행하는 플립드 러닝(flipped learning) 방법으로 공부합니다.


강의 요약이 아니라 푸닥거리&아이고 곡소리만 나는 글이 될 것 같은 너낌..

코딩도 어렵긴 하지만 '사고하는 방식'의 개선을 요하는 메가테라 과정.
트레이너분들께도 간간히 어렵다고 이야기했던 것 중에 하나가 '정답이 없는 문제를 푼다는 점'이었는데!!
역시나 어렵다. 정답이 없는 문제를 푼다는 건...

아샬님도 강의에서 이야기하셨지만, 정답은 없으나 더 나은 방법은 있다! 그렇기 때문에 다양하게 실험하고, 어떤 방법이 더 나을지를 고민하고 해보라고 하신다.

단계를 나눠보자.

  1. 정답은 없다!
  2. 하지만 더 나은 방법은 분명히 있다!
  3. 그러므로 실험해보고 바꿔도 보자!
  4. 때로는 금기(ex. for 문의 초기값은 i로 사용하는 관례, 그리고 j까지만 사용하자는 무언의 약속)를 깨보기도 하고!
  5. 그리고 더 나은 최선이라고 생각했던 것을 동료들과 나눠보고 토론하자!

이제 남은 시간동안 위 프로세스를 무한히 반복하면 된다.
내가 코딩을 못하는 건 매.일. 하지 않아서라는 점을 기억하자.
좋은 프로세스를 난이도를 높여 매일 하는 것이 중요하다. 매일!

사실 이번 3주차 강의에는 수많은 새로운 개념들이 등장했다.
언뜻 떠올려봐도 for문, 배열, HTML, CSS 등등...
주말 내도록 씨름해도 모두 해결될만한 주제들이 아니었기 때문에 이번 강의 요약에서는 갠적으로 유독 힘들고도 어려웠던 JAVA의 if문, while문, for문을 정리하며 공부해보고자 한다.




0. Control Flow Statements

자바 공식 튜토리얼에 보면 if, while, for문 등이 포함되어 있는 섹션이 바로 Control Flow Statements이다. 말 그대로 흐름을 제어하는 문(statements) 라고 이해할 수 있겠다.
컴퓨터를 위한 글(코드) 뿐만 아니라 사람을 위한 글(ㅎㅎ)에도 순서가 있다. 물론 코드만큼 엄격하지는 않지만, '시적 허용'과 같이 아주 특수한 경우를 제외하고는 예측할 수 있는 흐름이라는 것이 있다. 우리가 종종 사용하는 단어인 '기-승-전-결' 역시 글의 큰 흐름을 나타내는 말이기도 하다.

컴퓨터는 자신이 알아들을 수 있는 글, 즉 코드의 흐름을 굉장히 중요히 여긴다. 지금 배우고 있는 JAVA 보다 이번주에 맛보기로 살짝 발가락 담가보았던 HTML이 덜 엄격한 편이지만, 어찌되었던 컴퓨터와 소통하기 위해 써야하는 코드에서는 '시적 허용'과 같은 다소 역전적이거나 생략되는 흐름들은 거의 없다고 보면 될 것이다.

그렇담 이 엄격함을 요구하는 코딩에서 '흐름 제어'가 웬말이냐?
조금 거칠게 일반화하여 이야기하면, 1 > 2 > 3 > 4 순서로 진행되어야 하는 과정에서 특정 조건을 만족시킨다면 2라는 순서를 제외하고 1 > 3 > 4의 흐름으로 실행한다던지, 또는 특정 조건을 만족시킬 때까지 2와 3의 과정을 반복시켜 1 > 2 > 3 > 2 > 3 > 2 > 3 > 4의 흐름으로 실행한다던지... 이와 같이 1부터 5까지의 순서로 차례 차례 실행되는 flow를 제어하는 것이 Control Flow Statements이다.

아래에서 이야기하려는 if, while, for문이 바로 흐름제어문의 종류인데, 이외에도 여러 종류가 있겠지만 지금까지 배웠던 내용에 한정지어 이 세가지를 비교하고 자세히 알아보려 한다.




1. if

if는 JAVA의 control flow statements들 중 대장이라 불린다고 한다 ㅎㅎ. 귀엽다... 대장... 근데 대장이랑 너님 형제들.. 넘 어려워여...
'만약에!!' 라는 영어단어 뜻을 통해서도 눈치챌 수 있겠지만, if문은 사용자(코딩 쓰는사람? 바로 나?)가 적어넣은 조건을 만족시키면(또는 만족시켜야만) 실행된다.

if문은 이렇게 생겼다.

if (조건) {
// 조건에 해당될 때(조건이 참일 때) 실행시키고자 하는 statement;
}

지난번 2주차 강의 요약 글의 4번 조건문에서도 언급한 '숫자 계산 프로그램'을 약식으로 바꾸어 예시로 활용해보자. 요구사항은 아래와 같다.

  • 숫자 두 개를 입력받는다.
  • 숫자 두 개의 합을 입력하라고 요구한다.
  • 입력받은 두 숫자의 합이 실제 두 숫자의 합과 같다면 "You're right!" 메시지를 출력한다.
import java.util.Scanner;

public class MathTest {
    public static void main(String[] args) {
        // 0. 입력 준비
        Scanner scanner = new Scanner(System.in);

        // 1. 두 숫자 입력받기
        System.out.print("Input 2 numbers = ");
        int x = scanner.nextInt();
        int y = scanner.nextInt();

        // 2. 두 숫자의 합 입력받기
        System.out.print(x + " + " + y + " = ? ");
        int sum = scanner.nextInt();

        // 3. 조건에 부합하는지 확인 후 출력
        if (sum == x + y) {
            System.out.println("You're right!");
        }
    }
}

가장 마지막 문단인 '조건에 부합하는지 확인 후 출력'if문이 있다. 사용자가 2개의 숫자를 입력하고 그다음 숫자 둘의 합을 입력해넣으면 컴퓨터는 사용자가 입력한 합(sum)과 실제 합(x + y)이 같은지 판별한 후, 두 값이 같을 경우(if문 괄호 안의 내용이 참! true) 중괄호{} 안의 내용을 실행하는 것이다.

사실 여기에 '오답일 경우'라는 조건이 추가된다면 control flow statements의 의미를 더 정확히 확인할 수 있게 된다.

        // 3-1. 정답일 경우
        if (sum == x + y) {
            System.out.println("You're right!");
        }

		// 3-2. 오답일 경우
		if (sum != x + y) {
          	System.out.println("Stupid!");
        }   

사용자가 입력한 합계(sum)와 실제 두 수의 합이 같다면 3-1의 조건을 충족하게 되며 "You're right!" 이라는 문구가 출력될 것이다. 문구 출력 후 코드 작성 흐름에 따라 3-2가 이어져서 실행되어야 할 것 같지만, 사용자가 입력한 합계와 두 수의 합이 같으므로 3-2 if문 안에 있는 조건을 충족시키지 못하게 되면서 실행되지 않는, 소위 쌩- 무시하고 지나가는 상황이 발생하는 것이다.

그럼 반대로, 사용자가 입력한 합계(sum)가 실제 두 수의 합과 다르다면? 즉 틀린 값을 넣었다면?
코드 작성 흐름에 따라 3-1을 실행한 후 3-2를 실행해야 하는 것이 순리이지만, 3-1 if문 안에 있는 조건을 충족시키지 못하면서 그에 따르는 중괄호{} 내의 내용이 실행되지 않고 3-2로 뛰어넘어 가는 것이다. 사용자가 오답을 입력했을 때 3-2의 조건을 충족시키므로 다소 무례한 "Stupid!" 라는 메시지가 출력되고 프로그램이 종료된다.

중첩되는 if문, if-else 문도 있는데 이 내용은 추후 강의에서 다루게 되면 예시를 통해 덧붙이겠다.




2. while

알고나면 별 것 아닐 것 같은데, 나는 while문과 for문이 징글맞게도 어렵다.
우선 흐름제어문이 여러 개 나타나거나, 또는 2-depth 정도로 중첩되면 갑자기 머리가 새하얘진다... 지끈지끈.
나를 고생스럽게 만드는 이 while문을 좀 정리해두면 그나마 낫지 않을까 싶다.

while (true) {
// 실행시키고자 하는 statement;
}

언뜻 보기에는 if문과 크게 다를 바 없는 형태의 while
하지만 if와는 다르게 while문은 루프(loop)라는 개념과 함께 이해할 필요가 있다.

if는 괄호() 안 조건에 부합한다면 statement를 1회 실행하는 특징을 가지지만, while의 경우 괄호() 안 조건이 참인 동안에는 중괄호{}안의 statement를 계속 실행한다.
이 말인 즉슨 괄호 안의 조건이 계속 true라면 중괄호{} 안의 statement는 멈추지 않고 계속 실행되는 무한 루프(loop)가 될 수도 있다는 것이다.

아래의 예를 살펴보자.

public class Test {
    public static void main(String[] args) {
        while (1 < 3) {
            System.out.println("난 너무 예뻐요");
        }
    }
}

난 너무 예뻐요...
졸려서 미쳐버린 게 분명해...ㅋㅋㅋ

while에 따라오는 괄호() 안을 보면 1 < 3 이라는 조건이 제시되어 있다.
1은 3보다 작다. 불변의 진리이기 때문에 괄호 안의 조건 상태는 항상 true라고 보면 된다.
저 위의 코드를 그대~로 가져와서 인텔리제이 터미널에서 실행해보면 난 너무 예쁘다는 컴퓨터의 끊임없는 외침이 이어진다. while 괄호 안의 조건이 항상 참인 상태(true)가 되었기 때문에 무한 루프(loop)가 형성된 것이다.

프로그래밍에서 무한 루프를 필요로 하는 케이스가 얼마나 될지는 모르겠지만...
어쨌든 저 무한 루프를 사용하는 빈도 보다는 일정 횟수만큼은 while문을 통해 반복을 실행하고, 그 횟수를 초과할 경우 탈출하는(escape) 방식으로 사용될 가능성이 더 커보인다. (아참. 혹시 탈출하는 방법을 모르는 분들이 계실까봐... ctrl + C를 누르면 강제 탈출이 가능하다.)

위 예시를 조금 바꾸어 만들어보았다.

public class Test {
    public static void main(String[] args) {
        int x = 0;

        while (x < 3) {
            System.out.println("난 너무 예뻐요");
            x += 1;
        }
    }
}

이 경우 루프는 형성되었지만 무한히 진행되는 것이 아니라, x < 3이라는 조건이 충족되는 때까지만 반복된다.
즉 변수 x가 0이라는 값을 가지고 시작하고, while문이 1회 실행될 때마다 변수 x의 값이 1씩 증가하므로 x < 3의 조건을 만족시키는 때인 x = 2까지 총 3회 반복(x = 0, 1, 2. 총 3회)된 후 while문에서 탈출한다.

while도 중첩시켜 사용하는 경우가 있다. 글을 정리하다 보니 결국 내가 어려운 건 depth가 깊어지는 부분인 것 같다. 드디어 나의 약점이 좀 더 선명히 드러나는 것 같다...하하.....

while문에서 사용했던 재할당 관련 내용(reassign. 예: +=)은 2주차 강의 요약 글에 정리되어 있으니 참고!




3. for

단언컨대 나의 가장 큰 원수(ㅋㅋㅋㅋ)는 바로 for문이다.
if문 할 때는 분명히 안헷갈렸다. 할만해!! 한 느낌이었다.
근데 while의 등장으로 고개가 약간 갸우뚱해졌고, for문을 마주했을 때 드디어 나는 조져졌다.

아까 글을 정리하며 눈치챘지만 결국 for문이 극악 난이도처럼 느껴진 건 depth 때문이란 생각이 가장 크고. 그 다음이 for문의 정확한 작동 '순서'를 모르는게 문제라고 생각한다.
이 정리를 통해서 나도 for문의 작동 순서를 확실히 하고, 헷갈릴때면 내가 써놓은 글을 보며 다시 순서를 바로잡아야겠다.


for 문의 형태와 진행 순서가 잘 나와 있는 예시가 있어 링크출처를 남기고 가져온다.
내용 중에 reassign 하는 부분은(i++) 아샬님이 지양하라고 하신 방식이라 i += 1로 대체해서 사용할 것을 권한다.

어쨌든! for문을 모르는 상태에서 위 예시를 보면 잘 이해가 안될테니... for문은 아래와 같이 작성한다.

for (initialization; termination; increment) {
  	statement(s)
}

ㅋ.. 벌써 어렵다. 하나 하나 해보자. step by step...

먼저!! for문의 모양새만 살펴보자. ifwhile과는 다르게 괄호 안에 뭔가 주루룩 들어가 있고 각각의 요소가 세미콜론(;)으로 구분된다.

'반복의 3요소'라고 불리는 (1) 초기값 지정(initialization), (2) 반복 조건(termination), (3) 상태 변경(increment)이다.

for문이 어떻게 사용되는지는 '구구단 출력하기' 예시를 통해 알아본다.

(1) while 문을 이용해 구구단 2~9단 출력

public class Gugu {
    public static void main(String[] args) {
        int x = 2;

        while (x < 10) {
            int y = 1;

            while (y < 10) {
                System.out.println(x + " * " + y + " = " + (x * y));
                y += 1;
            }

            x += 1;
        }
    }
}

실컷 for문 이야기하다가 웬 while이냐아악!!! 할수 있겠으나...
공식 튜토리얼에도 나와 있는 for문의 장점인 'compact way'를 보여주는 데 좋은 예시인 것 같아 비교하고자 가져왔다.

while문을 사용하여 구구단 2~9단을 출력하는 코드를 보면

  • int 변수의 선언 -> while문을 활용한 반복 -> 결과 출력 및 변수값 증가시켜 재할당
  • int 변수의 선언 -> while문을 활용한 반복 -> 결과 출력 및 변수값 증가시켜 재할당

비록 중첩되어 있으나(2 depth) 큰 틀에서는 while문의 반복이라고 볼 수 있다. 메가테라 동료들은 아샬님의 가르침을 받는(ㅎㅎ) 사람들이므로. 중복을 발견했을 때 패턴을 발견하여 중복을 제거하고 효과적으로 표현하는 방법을 고민해야 한다.

그 효과적인 방법, 즉 compact way를 제공해주는 것이 for문이다.


(2) for 문을 이용해 구구단 2~9단 출력

public class Gugu2 {
    public static void main(String[] args) {
        for (int i = 2; i < 10; i += 1) {
            for (int j = 1; j < 10; j += 1) {
                System.out.println(i + " * " + j + " = " + (i * j));
            }
        }
    }
}

굉~장히 깔끔해지고 정말 컴팩트해졌다.
사실 for문에 익숙하지 않은 나는 이게 뭔소리야 대체!! 하고 고민스럽게 쳐다보고 있지만... 일반적으로 2 depth까지 중첩을 허용하는 for문이므로 위의 코드는 구구단 나열에 있어서는 Best practice에 가깝다고 볼 수 있을것이다.

while문으로 작성했을 때에는 변수의 선언, 충족시킬 조건, 조건 충족 시 실행시키려는 statement, 증감(상태변경)이 while 위 아래로 산재되어 있었는데, for문에는 괄호 안에 순서대로 정리되어 있다.

초기 변수값을 지정하고, 충족시킬 조건을 제시한 후, 변수를 어떻게 재할당 시킬지 정의한다.
초기 변수값은 for문을 최초 실행할 때 확인하고, 반복이 계속될 때에는 고려하지 않아도 된다는 점은 글을 정리하면서 새롭게 알게 된 사실이다.

초기 변수값 확인 -> 조건 확인 -> 조건 충족 시 statement 실행 -> 상태 변경 -> 다시 조건 확인 -> 조건 충족 시 statement 실행 -> 상태 변경 ... -> 조건 확인 -> 조건 미충족 시 반복 종료

앞에서도 몇 번 언급했지만 보통 for문의 중첩은 2번까지 허용(2-depth)하고, 초기값을 할당하는 변수는 i, j, k로 사용하는 관례가 있다. 중첩이 보통 2번까지 되니 i, j까지 주로 사용한다고 이해할 수 있겠다.

덧붙여서, 강의를 들으며 새로 알게 된 개념인 break, continue는 여러번 읽어보아도 개인적으로 이해가 잘 되지 않는 부분이 있어서...
추후에 switch를 다룰 날이 올 때 함께 다루어야 하겠다.

오라클 공식 튜토리얼과 꽤 괜찮은 타 사이트 북마크를 냄겨둔다... 찜찜해 ㅠ...

아...
3주차 강의 중에 1/5도 다 정리하지 못한 기분.
3주차 강의 요약은 시리즈로 하나 만들어야될 것 같다 ;;;

샨띠!!!! 포기하지마!!!!!!
완벽하지 않아도 살아남아야 한다~ 매일매일 정진하자!

profile
가벼운 사진, 그렇지 못한 글

0개의 댓글