생활코딩

Coding Everybody

코스 전체목록

닫기

클래스와 인스턴스 그리고 객체

클래스와 인스턴스 이전의 프로그래밍

객체를 만들기 전에 이미 익숙한 코드로 돌아가보자. 아래 예제는 간단한 더하기 프로그램이이다. 그런데 이 예제를 잘 활용하기 위해서는 상상력이 필요하다. 아주 간단한 예제지만 상당히 복잡한 작업을 실행하고 있는 로직이라고 가정하자.(실행)

package org.opentutorials.javatutorials.object;

public class CalculatorDemo {

    public static void main(String[] args) {
		// 아래의 로직이 1000줄 짜리의 복잡한 로직이라고 가정하자.
		System.out.println(10 + 20);
		System.out.println(20 + 40);
	}

}

메소드화

실행 결과는 30과 60이다. 프로그래밍의 기본은 중복을 제거하는 것이다. 위의 로직은 두개의 값을 더한다는 중복이 존재한다. 이 중복을 제거하기 위한 방법으로 고려해볼 수 있는 기능이 메소드다. 로직을 메소드로 만들면 코드의 양을 줄일 수 있고, 문제가 생겼을 때 원인을 더 쉽게 찾을 수 있다. 아래의 코드는 위의 코드를 메소드화시킨 예제다. (실행)

package org.opentutorials.javatutorials.object;

public class CalculatorDemo2 {

    public static void sum(int left, int right) {
		System.out.println(left + right);
	}

	public static void main(String[] args) {
		sum(10, 20);
		sum(20, 40);
	}

}

그런데 똑같은 수를 이용해서 더하기 뿐 아니라 평균도 구해야 한다면 어떻게 해야할까? 아래와 같이 할 수 있을 것이다. 입력값(left, right)을 변수화시키고 메소드들(sum, avg)가 이 값을 사용하면 코드의 양을 줄일 수 있게 된다. (실행)

package org.opentutorials.javatutorials.object;

public class ClaculatorDemo3 {

    public static void avg(int left, int right) {
		System.out.println((left + right) / 2);
	}

	public static void sum(int left, int right) {
		System.out.println(left + right);
	}

	public static void main(String[] args) {
		int left, right;

		left = 10;
		right = 20;

		sum(left, right);
		avg(left, right);

		left = 20;
		right = 40;

		sum(left, right);
		avg(left, right);
	}

}

객체화

평균을 계산하는 메소드 avg를 추가했고, 두개의 메소드(sum, avg)에서 동일한 입력값(10, 20)을 사용하고 있기 때문에 변수를 이용해서 좌항(left)과 우항(right)에 값을 담았다. 코드가 복잡해지기 시작한다.

상상력을 이용해서 위의 코드를 더욱 복잡하게 만들어보자. 실행 메소드인 main 에는 계산과 관련된 로직 밖에 없지만, 만약에 위의 코드에 직원 정보를 데이터베이스에서 가져오는 로직이나, 계산된 결과를 그래프로 표시하는 로직과 같은 것이 함께 위치한다면 코드는 점점 복잡해 질 것이다. 그러다 누군가 변수 left, right의 의미를 계산을 위한 좌항과 우항이 아니라 그래프의 디자인을 변경하는 코드로 사용했거나, 메소드 sum을 더하기가 아니라 요약(summary) 정보를 그래프로 표시하는 의미로 사용하게 되었다면 어떻게 될까? 하나의 프로그램 안에서 메소드나 변수의 의미가 달라지게 되는 것이다.

코드가 복잡해짐에 따라서 버그는 많아지고, 팀웍은 서서히 깨지기 시작할 것이다. 여러분이 언어의 설계자라면 이런 상황을 완화하기 위한 고민을 시작할 것이다. 이런 맥락에서 객체 지향이라는 개념이 등장하기 시작하는 것이다. 

객체 지향은 많은 선배 프로그래머들에 의해서 만들어졌기 때문에 다양한 의도가 반영된 프로그래밍 패러다임이다. 그래서 객체 지향이 만들어진 동기를 하나의 케이스로 설명하는 것은 어려운 일이다.

객체 지향의 핵심은 연관되어 있는 변수와 메소드를 하나의 그룹으로 묶어서 그룹핑하는 것이다. 위의 예제를 분석해보자. 연관되어 있는 부분과 반복적인 부분을 찾아 볼 수 있다.

메소드 sum과 avg는 변수 left와 right와 서로 연관 되어 있다. 또한 합계와 평균을 구하는 작업은 다른 에플리케이션에서도 사용할 수 있는 기능이다. 이것들을 그룹핑해서 하나의 부품으로 만들면 필요할 때마다 반복적으로 사용할 수 있을 것이다. 객체를 만들 때가 된 것이다.

아래의 예제는 의미적으로 연관된 로직들을 물리적으로 응집된 하나의 객체로 만드는 법을 설명하는 예제다. (실행)

본 수업에서는 아래의 코드를 기본 예제로 사용할 것이다. 우리 수업의 목적은 개론서이기 때문에 다양한 코드 경험보다는 개념의 빠른 이해를 목적으로 하고 있다. 처음 시작하는 입장에서는 개념도 쉽지 않는데 새로운 개념이 등장할 때마다 새로운 코드가 등장한다면 부담이 두배가 될 것이다. 필자는 개념의 이해는 쉽게 하는 것이 바람직하다고 생각한다. 그래서 본 수업은 계산기의 예제를 크게 벗어나지 않을 것이다. 빠른 속도로 수업 전체를 완주 한 후에 예제가 풍부한 다른 개론서를 천천히 완주하는 방법을 추천한다. 마음 같아서는 적당한 규모의 실제 프로젝트를 한줄 한줄 해석하면서 따라해보는 수업도 만들어보고 싶다. 할 수 있을까? ^^
package org.opentutorials.javatutorials.object;

class Calculator{
    int left, right;
     
    public void setOprands(int left, int right){
        this.left = left;
        this.right = right;
    }
     
    public void sum(){
        System.out.println(this.left+this.right);
    }
     
    public void avg(){
        System.out.println((this.left+this.right)/2);
    }
}
 
public class CalculatorDemo4 {
     
    public static void main(String[] args) {
         
        Calculator c1 = new Calculator();
        c1.setOprands(10, 20);
        c1.sum();       
        c1.avg();       
         
        Calculator c2 = new Calculator();
        c2.setOprands(20, 40);
        c2.sum();       
        c2.avg();
    }
 
}

클래스

코드가 급격하게 변했지만 차근차근 짚어가면 이해 못 할 것도 없다. 4행을 보자.

class Calculator {

위의 예에서 변수 left와 right, 메소드 sum과 avg는 연관되어 있는 로직이다. 이 로직들의 연관성은 계산을 하기 위한 것이다. 그래서 필자는 이 로직들을 대표하는 이름을 계산기라는 의미의 Calculator라고 정하고 이것들을 Calculator이라는 이름으로 그룹핑하고 싶다. 이럴 때 사용하는 키워드가 class이다. class 키워드 뒤에는 클래스 이름이 오고 그 뒤의 중괄호는 클래스의 시작과 끝의 경계를 의미한다. 이렇게 해서 더하기(sum)와 평균(avg)를 계산 할 수 있는 클래스가 만들어졌다. 클래스는 아래와 같이 정의 할 수 있다.

클래스는 연관되어 있는 변수와 메소드의 집합이다.

인스턴스

이제 클래스를 사용하는 방법을 알아보자. 클래스는 일종의 설계도다. 클래스를 정의하는 것 자체로는 할 수 있는 일이 많지 않다. 설계도를 구체적인 제품으로 만들어야 한다. 그 때 사용하는 키워드가 new이다. 25번 라인을 보자.

Calculator c1 = new Calculator();

new Calculator()은 클래스 Calculator를 구체적인 제품으로 만드는 명령이다. 이렇게 만들어진 구체적인 제품을 인스턴스(instance)라고 부른다. 아래의 관계를 기억하자.

  • 클래스 : 설계도
  • 인스턴스 : 제품

위의 코드는 new를 이용해서 만든 인스턴스를 변수 c1에 담고 있다. 변수 c1에 인스턴스를 담은 이유는 c1을 통해서 인스턴스를 제어해야 하기 때문이다. 그런데 c1 앞에 Caculator가 위치하고 있다. 지금까지 우리는 여러가지 변수를 선언해왔다. 예를들어서 변수 a는 변수가 담을 수 있는 데이터 타입에 따라서 아래와 같이 다양한 형태로 선언된다.

그럼 아래와 같은 구문은 변수명 c1의 데이터 타입이 무엇이라는 의미일까?

Calculator c1

Calculator라는 의미다. 즉 클래스를 만든다는 것은 사용자 정의 데이터 타입을 만드는 것과 같은 의미다. 하지만 지금 단계에서는 사용자 정의 타입이라는 개념이 쉽게 와닿지 않을 것이기 때문에 이에 대한 설명은 차차로 하겠다. 지금 기억할 것은 클래스를 인스턴스화 할 때는 변수에 담아야 한다는 것과 이 때 사용하는 변수의 데이터 타입은 그 클래스가 된다는 점이다.

클래스와 인스턴스는 설계도와 제품이라고 설명했다. 그럼 객체는 클래스일까 인스턴스일까? 다소 논란이 있지만 일반적으로 설계도인 클래스가 구체적인 실체인 인스턴스가 되었을 때 객체라고 부른다. 보통은 구체적인 코드 상에서 나타는 객체를 인스턴스라고 부르고, 로직을 설계 할 때 나타나는 인스턴스를 객체라고 부른다. 또는 클래스, 인스턴스의 구분없이 포괄적으로 객체라는 말을 쓰기도 한다. 이런 혼란을 피하기 위해서 필자는 가급적 클래스와 인스턴스를 사용하도록 하겠다. 이에 대한 논의는 생활코딩 페이스북 그룹을 참고하자.

클래스를 단순히 변수와 메소드의 묶음으로 보면 부족하다. 우리가 객체를 만들어서 사용하는 이유는 재활용성을 높이기 위해서다.

Calculator c1 = new Calculator();
c1.setOprands(10, 20);
c1.sum();       
c1.avg();       

Calculator c2 = new Calculator();
c2.setOprands(20, 40);
c2.sum();       
c2.avg();

위의 코드를 보면 두개의 인스턴스를 각각 c1과 c2에 담았다. 그리고 각각의 인스턴스에 소속된 메소드를 호출하고 있다. 각각의 인스턴스는 메소드 setOprands를 통해서 변수 left, right의 값을 설정하고 있다. 그 결과 인스턴스 C1과 C2는 아래와 같이 서로 다른 변수의 값을 내부적으로 가지고 있게 된다.

public void setOprands(int left, int right){
    this.left = left;
    this.right = right;
}

이 때 메소드 setOprands 내에 this.이라는 것이 있다. this는 클래스를 통해서 만들어진 인스턴스 자신을 가리킨다. 위의 코드에서 left는 매개변수이고 이 변수는 setOprands 밖에서는 접근 할 수 없다. 반면에 this.left는 4행에서 선언한 변수에 값을 설정하는 것이고 메소드 밖에서 선언한 변수는 인스턴스 내의 모든 메소드에서 접근이 가능하다. 이에 대한 이야기는 뒤에서 차차 하겠다. 이해가 안가더라도 걱정하지 말자.

변수를 다른 말로는 상태(state)라고도 표현한다. c1.sum의 결과는 30, c2.sum의 결과는 60인 것을 통해서 알 수 있듯이 상태가 다른 객체를 대상으로 메소스를 실행시키면 다른 결과를 나타내게 된다. 메소드를 다른 말로는 행동(behave)라고도 표현한다.

  • 변수 : 상태
  • 메소드 : 행동

즉 하나의 클래스를 바탕으로 서로 다른 상태를 가진 인스턴스를 만들면 서로 다른 행동을 하게 된다는 것을 알 수 있다. 하나의 클래스가 여러개의 인스턴스가 될 수 있다는 점이 객체 지향이 제공하는 가장 기본적인 재활용성이라고 할 수 있다.

객체 지향의 객체를 하나의 작은 프로그램처럼 느껴보자. 프로그램 안에 객체라는 작은 프로그램을 만드는 것이다. 이것들을 레고 블럭처럼 쌓아서 웅장한 프로그램을 만드는 것이 객체 지향이 추구하는 바라고 할 수 있다.

댓글

댓글 본문
작성자
비밀번호
  1. ubiquitous4g
    https://play.google.com......BAJ
    프로그래맹 기초 공통 부분 이해 끝나셨으면(4장 이하), 이 책 5.6장 부터 보시는걸 추천드려요.
    자바 하나하나의 개별 개념을 단계적으로 배우기는 힘들어요,
    그냥 흘러가는데로 처음부터 끝까지 다 보고, 조금씩 알게되면, 처음부터 다시 봐야 되요.
    위 책이 그나마 쉽고, 단계적입니다.
    대화보기
    • ubiquitous4g
      refactoring 이라는 관점에서 바라보니, 제가 모르던 부분이 있어 크게 깨우치고 갑니다.
      아직 배우는 입장이지만, 클레스 인스턴스 객체 부분은 쉽게 이해해서 그냥 넘어갔었는데..
      객체를 사용해 반복을 제거하기 전의 모습은 어떠했을까? 라는 관점에서 바라보니..
      oop에서 반복이라는 큰 틀의 객체 생성과, 기능 각각의 부품화 해야 할 메소드 모습이 머리속에 더 잘 그려지네요.
      감사합니다.
    • 열정하나
      5월 2일 나두 완료!
      하지만 1번 더 들어야지~
    • 5월 1일 클래스와 인스턴스 그리고 객체 완료!
    • 박현모
      감사합니다~
    • 최진영
      말 그대로 노트에 연필로 코드를 적어 보는 겁니다
      대화보기
      • 박수진
        프로젝트를 한줄한줄따라가는 수업 할수있으시고 완전 좋을것같아요. 지금 몇번째 강의 듣는지 모르겠어요... 너무나도 유익하고 적용할때 뿌듯함을 느낍니다. 감사합니다!
      • 성은영
        정말 유익한거 같아요~` 늘책으로 독학을 할려는데 정말 이해도 안갔었는데
        차분히 설명해주시는거 어쩜...너무 이해가 잘됩니다^^
      • 김세창
        와.... 진짜... 설명 잘 하십니다...
        역시 고잉님... 최고입니다..
        저는 솔직히 자바 진심으로 너무 어려웠는데, 여기까지 따라오면서,
        드디어 자바언어를 읽고 이해할 수 있게 되었네요...
        정말 감사합니다!!
      • 미래 자바개발자
        자바 기본 개념을 잡고 스몰 프로젝트를 진행한 후, 자바 자격증을 취득해서 자바개발자로 전향을 계획중에 있습니다.
        어렴풋이 알고 있었던 것들이 점점 자리를 잡아가는 것 같습니다.
        감사합니다.
      • 홍제걸
        아니 어쩜 설명도 잘하시는데 그림도 잘 그리세요.
        화이트보드 넘 센스있게 잘 그리시네..
      • 연필코딩이먼가요
        대화보기
        • 김진홍
          감사합니다.
        • ㅁㄴㅇ
          초보입장에서 쉽게 설명해주셔서 감사합니다
          잘보고 배우고 있습니다
        • 하면된다하자
          완료!
          명강의 감사합니다. 늦은 나이에 프로그래밍을 공부중인데, 큰 힘이 됩니다.
        • 코딩초보자
          저 완전 초짜라서 감히 말씀드리기 좀 그렇지만. 혹시라도 먼가 코딩이 너무 초반에 어렵게 느껴지시는분. 이게 연필코딩추천합니다 ㅋㅋ 이게 코드로직을 손으로 직접 한 세 번쓰면 머랄까 개념이나 로직이 머리속에 팍팍 박히는 느낌이 듭니다. 강추드립니다. 컴퓨터로 쓰면 그 로직의 손맛이랄까 그게 안느껴져서요. 진짜 먼말인지 하나도 모르겠다가 이런식으로 공부하니까 오 엄청재밌네요 이해하는 짜릿함.
        • 코딩초보자
          너무 재밌어서 밤새고있어요 멈출수가 없음 ㅋㅋ 아니 보통 집에서 공부안하는데 코딩이 저랑 체질이 맞는건가? 단언하긴 힘들지만 이고잉님 후 감사합니다 ㅠㅠ
        • 컴공전공
          왠만한 유료강의보다 쉽게 설명해주고 있다고 느껴지는데요...
          언어계열이 복합적인 내용이라 횡설수설 하는 것처럼 느껴질 수도 있지만
          다른 언어를 알고 강의를 듣는 입장에서는 이보다 좋은 강의는 찾기 힘들다고 생각합니다.
          대화보기
          • 설명을 잘하시네요!
          • 쉽게 설명하려고 노력한 분에 대한 예의가 아닌 것 같습니다만..
            대화보기
            • 강의에서 무슨 용어가 혼용 되었는지 알려주실 수 있나요? 영상에서 어떤게 잘못되었는지를 알려주시면 다른 분들이 보실 때 참고하실 수 있을 것 같습니다만.
              대화보기
              • 뭐이리 용어가 혼용되고 횡설수설인지..
              • 이근환
                감사합니다!
              • 프로그램은 이게 전부라고 할 수 있겠네요.

                모든 JAVA API 가 객채와 클래스로 짜여져 있으니까요.

                너무나 방대한 자바 API...
              • popinbompin
                ㅇㄹ
              • selina
                완료
              • package Calender;

                import java.util.Scanner;

                public class CalenderMaxDemo2 {

                static class Center {
                public static void Ex(int a){
                if(a == 1) {
                System.out.println("해당 월을 입력하시오 : ");
                Scanner scannerNum = new Scanner(System.in);
                int monthNum = scannerNum.nextInt();

                int[] monthMax = {31, 29, 30, 31, 32, 31, 31, 30 ,31 , 32, 31};
                System.out.printf("%d월5의 최대일수는 %d 입니다.",monthNum, monthMax[monthNum -1]);

                scannerNum.close();
                } else {
                System.out.println("프로그램을 종료합니다.");
                }
                }
                }

                public static void main(String[] args) {
                System.out.println("작업을 하겠습니까 : ");
                Scanner scannerInt = new Scanner(System.in);
                int monthInt = scannerInt.nextInt();
                Center.Ex(monthInt);
                scannerStr.close();

                }
                }

                정말 단순한 프로그래밍작품중 하나입니다. 완성이된 작품이지만 한가지 문제가 있습니다. 정수를 main 함수에서 입력하면 Ex함수로 그숫자가 적용이되서 프로그램이 구동됩니다 하지만 문자열을 이와같은 상황으로 실행시키면 Ex 클레스가 구동되지 않습니다. 문자열을 어떻게 사용하면 객체지향적인 프로그램이 될까요?
              • GoldPenguin
                감사합니다.
              • Younghun Liam Youn
                사용자 정의 데이터 타입이라는 말이 와닿네요!
              • 김두한
                공산당 할꺼야안 할꺼야
                대화보기
                • 우리수니
                  저도 this를 무조건 붙여야 하나 헷갈렸었는데요, 아래처럼 변수명을 다르게 줘봤더니 this를 안붙여도 되더라구요..

                  class calculator{
                  int v1, v2;
                  public void setOprands(int left, int right) {
                  v1 = left;
                  v2 = right;
                  }
                  public void sum() {
                  System.out.println(v1+v2);
                  }
                  public void avg() {
                  System.out.println((v1+v2)/2);
                  }
                  }
                  대화보기
                  • 나도c언어만준마스터
                    네 맞는거같아요. 저도 c언어만 알고 java처음 접하는데 calculator가 사용자정의 자료형이되고, c언어에서 봤을때 구조체랑 흡사한거같아요. 거기에 함수도 추가되있는. c언어를 알고 들으니까 확실히 이해가 편하네요.
                    대화보기
                    • 완료.!
                    • C언어만마스터
                      C언어의 관점에서 본다면 클래스라는건 구조체 + 해당 구조체에서만 사용할 수 있는 함수를 정의한 것이라고 생각해도 될까요?
                    • 이시태
                      와.. 나는 이거 설명하라고 해도 못하겄네;;

                      ㄷㄷㄷㄷㄷㄷ

                      수고 진짜 많이하셨습니다 후우~
                    • 심영
                      저는 작성해보고 다시보고 작성해보고 강의듣고 작성하고 또듣고 5회하니까
                      혼자 해볼정도는 오네요

                      감사합니다 정말 이해 안되더라고요...
                      ㅠㅠ
                    • trochi
                      이고잉 형님 너무 너무 고마워요 설명 - 시간내주셔서 만들어 주셔서 !! :)))
                    • 홍차
                      아래 님 이거보다 어떻게 더 쉽게 하나요.. 이해 안되면 계속 서치하면서 보셔야할듯
                    • Curtis
                      좀 더 쉽게 좀 ㅠ
                    • 후키키
                      오 짱이에요
                    • 야스오
                      입문자들화이팅
                    • yoon88
                      완료
                    • 입문자들모두화이팅!
                      "즉 하나의 클래스를 바탕으로 서로 다른 상태를 가진 인스턴스를 만들면 서로 다른 행동을 하게 된다는 것을 알 수 있다."

                      라는 부분을 저는, " 서로 다른 상태를 가진 인스턴스를 만들면 행동(메소드)를 거쳐 서로 다른 결과가 나타나게 된다" 라고 이해했는데, 댓글을 보니 몇몇 분들도 역시 이 부분이 좀 걸리시는 것 같아서 제 생각을 남겨봅니다.
                      결국 의도하시고 싶으신 의미는 클래스 내에 1) 여러가지의 인스턴스(객체) 를 만들 수 있고, 2) 인스턴스마다 정의하는 변수가 다르며 3) 고로 변수에 따른 메소드의 "결과"가 다르다는 것을 서로 다른 행동을 하게 된다고 표현하신 것 같습니다 ! :)
                      제가 이해한 바가 아닌 경우 아낌없이 피드백 부탁드립니다 !

                      생활코딩으로 오래 전 배웠던 자바를 복습하고 있는데, 무작정 코드위주가 아닌 개념과 이해 위주로 진행되어서 한결 부담없이 복습하고 있습니다. 감사합니다 !
                    • 고유나
                      매개면수와 인ㅌ스턴스 변수의 이름이 같아도 되는 이유가 뭔가용..?
                    • 티에리앙리
                      다음 강의를 보니까 행동하는 건 avg,sum의 인자값에 따라 달라질 수 있다는 말씀이시군요
                      그래서 서로 다른 행동을 하게 된다고 하신거같네요
                      대화보기
                      • 티에리앙리
                        질문 있습니다. 마지막 그림설명에서 밑줄친
                        "즉 하나의 클래스를 바탕으로 서로 다른 상태를 가진 인스턴스를 만들면 서로 다른 행동을 하게 된다는 것을 알 수 있다. "
                        이 부분에서 서로 다른 상태를 가졌다는건 c1과 c2가 left,right 값이달라 서로 다른 상태를 가진 인스턴스(c1,c2)를 만들었다는 말은 이해가 가는데
                        그 다음에 서로 다른 행동을 하게 된다고 하셨는데 행동(메소드)은 avg,sum 으로 하는거 아닌가요?
                        결국 둘다 sum과 avg를 하는데 같은 행동을 하는거 아닌가요?? 음 제가 잘못이해한건지..
                        답변 부탁드립니다 ㅠ
                      • shonny
                        동영상 강의 몇개를 들어봤는데 선생님 강의가 가장 잼있어요. ㅎㅎ 감사합니다.
                      • 책이랑 같이보고 있는데 이해가 잘 되고 자바가 뭔지 조금 알것 같아요! 끝까지 열심히 들어서 혼자서도 얼른 실습 해보고 싶어요. 좋은 강의 만들어주셔서 감사합니다!
                      • 정우진
                        정독하면서 댓글 한 번 안 달았네요.다른 강의는 봐도 봐도 장황하고 필요 없는 말도 많이 하면서 이해하기가 힘들었는데 정말 선생님의 강의는 최고입니다. 지루하지 않게 15분 안에서 끊는 강의, 진도에 따라 학생이 가지고 있을 지식을 가늠하여 설명, 받아들이는 것과 이해하는 것의 차이, 말하자면 끝도 없겠지만 단순 강의를 떠나 선생님만의 교육 철학이 담겨있음을 들을 수록 느낍니다.
                        다른 강의는 자바 절차지향만 떼기도 힘들었는데 이 강의는 어느새 객체지향 도입부까지 도착했네요. 어려움없이요^^ 선생님 믿고 끝까지 정독하겠습니다 감사합니다
                      • 윤종섭
                        한달동안 학원다니고 유료 인강들으면서도 객체지향,메소드,인스턴스 등등의 개념들이 도저히 이해가 안가고 막상 코딩할 때도 헤매고 했는데 여기 강의들으면서 조금씩 명확해집니다!! 제가 찾던 강의에요ㅠㅠ 진심 이런 디테일한 강의를 접하기가 쉽지 않아요 ㅋㅋ 강사들이 자기들은 아는 내용이니 대충 넘기던지 귀찮아하는 경향이 강합니다. 여기 강의하시는 강사님은 정말이지 촤고네요 ㅋㅋ이런 세부적인 설명이 입문자나 초보자에게 얼마나 큰 배려인지 다른 강사들도 알았으면 좋겠어욬!
                      버전 관리
                      egoing
                      현재 버전
                      선택 버전
                      graphittie 자세히 보기