미적분 카테고리는 학생들이 자주 물어보는 내용을 정리해놓은 카테고리입니다. 궁금한 내용이 생기면 언제든 질문 해주세요! 질문은 공개글로 해주셔야 다른 학생들도 같이 봄으로써 우리가 공부하면서 생각하지 못했던 부분을 짚고 넘어갈 수 있습니다. 모르는 것은 부끄러운 일이 아닙니다. 모르는 것을 덮고 그냥 넘어가는 일이 오히려 부끄러운 일입니다. 세상 모든 사람이 지식을 탐구하는 일이 즐겁다는 사실을 알았으면 좋겠습니다.
여기서는 미적분학에 대한 원리를 깨우치는데 조금 더 중점을 두려고 합니다. 풀이를 위한 해석보다는 식을 보고 그에 해당하는 식이 어떤 의미를 가지고 있는지 살펴볼 것입니다. 미적분학과 공학수학은 미적분학을 다루는데 있어서 비슷하지만, 미적분학은 그 의미를 파악하는데 중점적으로 다루는데 반해, 공학수학은 특정 공학적 지식을 다루기 위해 미적분학을 배우는데 의의를 두고 있습니다. 그렇기에 자신의 목적에 맞게 취사선택하시면서 배우시면 되겠습니다.
책에 대해서...
책에 대한 추천을 해달라는 분들이 많습니다. 그렇다면 미적분학의 경우는 몇 개의 양대 산맥이 존재합니다. 대표적으로 많이 쓰이는 미적분학 책은 James Stewart책과 Thomas(George B. Thomas)미적분학이 유명합니다. 다른 서적들도 충분히 좋은 책입니다. 한국에서 쓰여진 서적들의 경우, 위의 사람들의 책을 보고서 우리나라 실정에 맞게 바꾼 좋은 책들도 존재하니 실제 책을 구경할 일이 생기면 직접 읽어보고 사는게 가장 좋습니다.
대학교에서 교재를 사용하신다면 학교에서 추천하는 책을 구매하시는 편이 좋습니다. 판수에 대해서도 질문이 많은데, 판수는 1~2판수 정도 차이나도 크게 차이 나지 않습니다. 다만 완전하게 개편된 경우라면 새로 구매하시는 것도 좋습니다.
미적분학 책은 꼭 구매하시는 편이 좋습니다. 가격대가 비싸지만 평생 사용할 수 있기에 끝까지 제대로 보고 가셨으면 합니다. 현대의 과학에서는 미적분학이 근간이 됩니다. 여기에 추가로 과학과 산업의 발전이 일어나기 위해서는 필요한 기초 교육이라 생각합니다.
* 현대 기술의 발전은 특정 수학의 단계가 누구나에게 자연스러운 상태가 되었을 때 발전됩니다. 예를 들어, 이전 세기에는 미적분학이교수들만 배우는 학문이었다면, 현대에는 미적분학은 고등학생이면 누구나 할 줄 아는 학문이 되었습니다. 그에 따라 우리 과학 기술은 또 한번의 진보를 이룬것이죠.
그 다음 세기의 기술의 발전은 대학교 2학년이나 3학년 수학과에서 배우는 학문이 대부분의 고등학생들이 알게 되는 학문이 된다면 크게 진보하게 될 것입니다. 산업 상의 성공 사례로는 페이스북이라 생각할 수 있겠습니다. 페이스북의 창업자는 해석학에 대해 많은 공부를 했으며, 그에 따라 삶에 대한 다양한 관점을 가질 수 있었던 것입니다. (조금 더 정확하게는 특정 데이터 사이의 유의미한 패턴을 인식하는 능력에 대한 훈련을 조금 더 가질 수 있었다고 볼 수 있겠습니다.) 물론 다른 이유도 더 많겠지만 우리가 수학에 대해 끊임없이 탐구해야 하는 이유라고 생각할 수 있겠습니다.
많은 학생들이 수학을 왜 배워야 하는지에 대해 의문을 많이 품습니다. 하지만 수학은 우리의 인식 속에 우리의 사고를 확장하는데 아주 많이 사용되었습니다. 우리가 특정 물음에 대해 입증하고 증명해나가는 과정 또한 수학 속에 들어간 논리학을 기반으로 사고하고 있습니다. 그것이 다른 여러 학문과의 상호작용에서 나온 것일 수도 있지만 대부분의 논리학과 추론 능력을 기르는데 가장 좋은 방법은 수학이라는 것은 당연한 사실입니다.
객체지향은 이야기하기에는 너무나 방대한 이야기이지만 자바를 배우기 위해서 꼭 필요한 이야기이므로 하고 넘어가도록 하자.
1. 객체지향
객체지향은 자바 프로그래램을 구현하는 하나의 방법이다. 소프트웨어는 하드웨어와 달리 구체화된 상태가 없어서 오히려 설계하기가 힘들다. 그 이유는 제약 사항이 없기 때문이다. 우리에게 무한한 자유를 주기 때문에 오히려 무엇을 할지 못하는 상태가 되버리는 것이 소프트웨어의 제약이다. 무엇이든 할 수 있지만 그렇기에 모든 것을 할 수 없는 상태가 되는 것이다. 현실 세계에서 톱니바퀴를 만든다면 현실 세계의 톱니바퀴는 만드는데 제약이 아주 많다. 재질부터 시작해서 만들어내기 위한 틀 또한 모든 것이 제약 사항이 될 것이다. 하지만 프로그램에서는 제약이 없다. (또 다른 예로는 수식을 만들고자 한다고 생각해보아라, 어떻게 만들어야 할지, 어떤 것을 변수로 놔야 할지 잘 모를것이다.)
그래서 프로그램을 모델링 하기란 너무나 어려운 것이다. 이를 사람이 설계하기 쉽게 만들기 위해 생각한 것이 객체지향 프로그래밍이다. 객체지향 프로그래밍은 일상 생활을 객체로 표현함으로써 이러한 설계 과정을 추상화하기 위해 노력했다.
예를 들어보자, 커피숍에서 커피를 시키는 상황을 생각해보자. 커피숍에는 바리스타와 손님 그리고 커피머신이 있다. 여기서 바리스타, 손님, 커피머신은 각각 하나의 객체라 볼 수 있다. 손님은 바리스타에게 커피를 주문하는 메시지를 전달할 것이며, 바리스타는 이러한 메시지를 받아서 처리해준다. 그리고 바리스타는 커피머신을 활용해서 커피를 만들게 될 것이다. 그리고 다시 커피머신에 의해 만들어진 커피는 바리스타에게 전달되고, 다시 커피는 손님에게 전달됨으로써 상황이 마무리가 된다.
이러한 상황을 모델링 하는 것을 객체지향이라 볼 수 있다. 대부분의 일을 처리할 수 있는 상상력을 가질 수 있게 되는 것이다. C++과 Java는 이러한 객체지향적 언어라 볼 수 있다.
2. 어떠한 방식으로 만들 것인가?
그러면 이를 만들기 위해서 어떠한 방식으로 설계할 것인가가 새로운 문제가 된다. 어디서부터 어디까지가 하나의 객체이며, 어떠한 방식으로 표현하는가가 문제가 된다. 그래서 객체지향은 기본 원칙을 둠으로써 설계할 때, 너무 많이 벗어난 설계를 하지 않도록 하고 있다. 설계의 기본 방향은 네 가지 기본 원칙으로부터 시작된다.
캡슐화
추상화
상속
다형성
이렇게 네 가지 기본 원칙이 존재한다.
캡슐화는 데이터와 데이터에서 작동하는 하나의 단위로 묶는다. 그리고 그 내부의 속성과 메소드의 내부 구조를 숨기는 것을 나타낸다. 이전에 설명한 것처럼 해열제(알약) 안에는 어떠한 성분이 들어있는지 모르더라도 우리는 해열제(알약)이 먹으면 열을 내리는 작용을 한다는 것을 안다.
데이터의 추상화 는 객체의 구현은 현실 세계의 복잡함을 그대로 표현하기 위함이 아닌 추상화된 형태를 표현해야 함을 이야기 한다. 추상화는 특정 일에 대한 구체적인 상황을 제거하고 일에 대한 본질을 표현하는 형태를 이야기한다. (예를 들어, 동사무소에서 하는 일은 민원 처리, 장비 대여, 행정 업무 등 다양한 업무를 보고 있지만 그에 따른 본질은 동에 사는 주민들에 대한 편의를 위한 업무 처리이다.)
상속은 클래스에서 부모와 자식 간의 관계를 정의하는 메커니즘이다. 사실 이 관계는 부모로부터 물려받은 특정 클래스의 특징을 이야기하는데, 여기서 특징은 부모 클래스에서 가지고 있는 어떠한 기능을 이야기한다. 예를 들어, 부모가 가지고 있는 정수를 처리하는 능력은 자식에게 상속되어 그대로 정수를 처리하는 능력을 가지게 되는 것이다. 이는 중복된 기능에 대한 개발을 막기도 하며, 효율성 증대와 더불어 설계의 계층 구도를 생각하기 위함이라 봐도 좋다.
다형성 이란 하나의 이름에 여러 형태를 의미한다. 프로그래머에 따라 같은 이름을 가지더라도 해석은 다를 수 있다. 이러한 것을 객체지향은 받아들여서 다형성이란 이름으로 새롭게 재해석될 수 있는 것이다. 이전에 우리가 배운 println에서 정수형을 받아들이는지, 실수형을 받아들이는지, 문자형을 받아들이는지 모두 다를 수 있다. 프로그래머가 '특정 값을 받아서 출력한다.'의 의미가 프로그래머마다 다를 수 있는 것이다. 특정 값이 어떤 사람은 정수로 받아들일 수도 있는 것이고, 어떤 사람은 실수로 받아들일 수도 있는 것이다. 이러한 부분을 처리하기 위해 다형성을 두게 된 것이다.
또 다른 예로는 우리가 특정 웹사이트에서 게시판을 만들 때, 게시판의 제목과 글쓰기 등의 형태는 유사하지만, 그걸 실제로 구현하는 게시판에 해당하는 제목과 날짜 그리고 디자인은 다를 수 있음을 이야기한다. 즉 실제로 구현하는 사람의 해석에 따라 그 형태가 달라지는 것이다.
3. 클래스와 인스턴스
자바에서는 클래스란 개념이 있는데, 객체지향에서는 객체란 개념이 있다. 이를 매칭시켜야 설계를 할 것이다. 일반적으로 자바에서 클래스를 이용해서 객체를 설계한다. 하지만 이는 하나의 설계도일 뿐이다. 자동차를 예를 들어보자, 자동차는 기본적으로 동일한 속성이 존재한다.
바퀴
엔진
기본 프레임
더 많은 속성이 있겠지만 이정도라 생각하자. 자동차는 이러한 속성은 같지만 실제로 갖는 값은 서로 다르다. H사에서 만든 자동차와 K사에서 만든 자동차는 실제 속성의 값이 틀리다. 엔진도 있고 바퀴도 있고 기본 프레임도 있지만, 엔진의 출력도 다르고 바퀴의 크기도 다르며, 프레임의 색도 다르다. 우리는 이렇게 기본 설계가 되는 형태를 클래스라 하며 실제로 갖는 값을 인스턴스라 할 수 있다.
기본 예시로 H사의 그랜저와 K사의 K9는 인스턴스라 볼 수 있는 것이다. (자동차 객체를 갖는)
객체지향은 이 보다 더 많은 이야기를 담고 있지만, 처음보는 사람이 이 정도만 이해를 하면 충분하다. 대략적인 개념은 이 정도로 담아둔 상태에서 조금 더 프로젝트를 진행시키거나 조금 더 프로그래밍을 연습해보면서 특정 상황적인 부분을 프로그램으로 어떻게 담을지 고민하면서 발전시켜 나가야 한다. 이 글에서도 객체지향의 모든 것을 담지는 못했다. 이는 설계하는 사람에 따라 그 해석 과정이 계속해서 달리지기 때문에 대략적인 이야기를 바탕으로 풀어나가려고 했다.
프로그래밍 언어를 배우면서 가장 근본적인 질문은 어떻게 배워야 하는가에 대한 질문 이었습니다. 프로그래밍은 우리에게 너무나 많은 일을 할 수 있는 강력한 힘을 줍니다. 하지만 문제가 있죠. 너무 강력한 힘을 주면서 동시에 너무나도 큰 자유를 선사해준다는 점입니다.
자유
자유... 자유는 누구나 원하는 일이지만 갑자기 주어지면 뭘 해야 할지 감이 안 옵니다. 초등학교, 중학교, 고등학교에서는 하라는 데로 하기만 하면 됩니다. 심지어 대학교 조차도 커리큘럼이 있습니다. 이러한 커리큘럼을 특정한 시간 내에 특정한 주제가 정해진 상태로 우리는 하라는 일을 하면 됩니다. 하지만 프로그래밍은 우리에게 자유를 줌과 동시에 무엇을 해야 할지 우리가 스스로 결정해서 나가야 합니다. (물론 회사에 들어간다면 해야 할 일이 주어지지만 프로그래밍을 배우는 주된 이유는 내가 원하는 것을 마음껏 펼칠 수 있기 때문입니다.)
그렇다면 무엇을 배워야 할지 모르는 상태에서 나름의 틀을 주는 것은 무엇일까요? 그건 책이죠. 아무것도 할 줄 모른다면 일단은 머릿속에 무언가라도 넣은 상태에서 무엇을 해야 할지 결정해야 합니다. 그것도 싫다면 자바에서 주어지는 여러 기능을 시험삼아 테스트 해봐야 합니다. 틀이 주어지건 안 주어지건 간에 우리는 주어진 기능을 시험해보고 어떻게 사용해야 하며, 쓰다보면 생기는 질문을 꼭 해결하면서 진행해야 합니다.
그렇다면 오늘의 포스팅에서는 어떻게 여러 기능을 연습해볼 수 있는지 살펴보도록 하겠습니다.
1. 어떻게 테스트를 할 것인가?
우리에게 가장 처음의 프로그래밍의 시작은 Hello, World가 주어진 것은 우연이 아닙니다. 가장 기본적인 입출력 프로세스를 익히기 위함이죠. Stdout이라 하는 Standard OutPut은 프로세스에서 가장 기본적인 인터페이스이죠. 그러면 단 한 줄을 분석해보도록 합시다.
이곳에서 확인할 수 있다. 필요한 내용이 있을 때마다 Search를 활용해서 사용하도록 해야 한다.
상단에 보면 Search가 있으니 궁금한 내용을 찾아보는 습관을 들이자. 참고로 영어가 잘 안되도 우리는 할 수 있다. 네이버 파파고와 구글 번역이 있으니 전혀 무섭지 않다. 번역기를 돌리면서 영어로도 한번 읽어보자. 차분히 영어 실력도 같이 늘어가는 것을 볼 수 있다. 언제까지고 영어가 두려워서 영어 페이지가 나오는 것을 외면할 것인가! 한번 시도해보자. 당장에 하루 이틀 만에 확 늘어날 수는 없지만 꾸준히 하면 영어 페이지가 나와도 읽을 만할 정도가 될 것이다.
우리는 여기서 System을 찾아볼 것이다.
많은 검색 결과가 나온다. 그 중에서 java.lang.System을 클릭해서 들어가보자.
두 가지 정보를 바로 얻을 수 있다. Module : java.base와 Package : java.lang 모듈과 패키지를 알아볼 수 있다. 그러면 우리가 모르는 정보는 모듈과 패키지란 단어를 모른다. 다시 찾아보면 된다. 어쨋든 모듈이란 기능상 비슷한 것을 모여서 만든 작은 부품이 조립된 하나의 덩어리를 모듈이라 부른다.
모듈
현실 세계에서 자동차를 만들기 위해서는 수 많은 모듈이 필요하다. 모듈은 수 많은 부품으로 이루어져 있다. 이런 관점에서 보았을 때 모듈은 하나 또는 하나 이상의 기능을 하는 특정한 덩어리이며, 나사와 같은 작은 부품이 모여서 최소한의 기능을 할 수 있게 만들어주는 하나의 덩어리라고도 볼 수 있겠다. 대표적인 모듈은 ABS 모듈이다. 자동차 시스템에서 브레이크 시스템을 담당하는 녀석으로 Anti-lock Break System을 의미한다. 브레이크를 밝을 경우, 한 쪽 바퀴가 먼저 잠기는 것을 방지해서 차가 회전하는 것을 막아주는 역할을 한다.
ABS 모듈의 구성은 바퀴속도 감지기, ECU(전자 제어 모듈), 유압조정장치, 경고등 등이 기본적인 구성 성분이다. 여기서는 다른 모듈을 포함하기도 하는 것이 모듈이다. 소프트웨어에서도 마찬가지이다. 이러한 모듈의 크기는 천차만별인데, 모듈의 크기가 커지면 처음에 설계하기가 어려워지는 대신에, 모듈과 모듈을 합치는 과정이 편해진다. 반대로 모듈의 크기가 작아지면 처음에는 설계하기 쉽지만, 이러한 모듈들을 조립하는 단계에서 힘들어 진다. 자동차에서도 부품이 너무 많은 나머지 조립할 때, 일반인은 하지 못하는 것과 마찬가지이다. 하지만 조금 더 모듈의 크기가 큰 전자제품의 경우, 자동차 보다 조립하기는 쉬운 경향이 있다. 물론 이러한 예는 정확한 예는 아니지만 모듈에 대해 이해하기에는 충분하리라 생각한다.
모듈을 사용하는 이유는 사람이 다룰 수 있는 단위로 나누어서 소프트웨어를 설계하기 쉽고 유지보수 하기 쉽게 만들기 위함이다. 프로그램이 하나의 덩어리로만 이루어진다면 우리는 다음 소프트웨어 버전을 만들기 위해서 처음부터 설계해야할 것이다. 또한 특정 부분이 고장나서 고치려고 할 때, 그 소프트웨어를 다시 사야 할 것이다.
지금 세상은 모듈화가 잘 이루어져 있어서 특정 예를 들긴 어렵지만, 소비자의 입장에서 예를 들어보로독 하자. 대표적인 덩어리 모듈의 예시를 들어보자면 핸드폰에서 탈착식 배터리와 일체형 배터리의 차이라 볼 수 있다. 탈착식 배터리의 장점은 배터리의 수명이 다 되어, 새 것으로 교체하고자 한다면 언제든지 교체가 가능하다. 하지만 일체형 배터리는 그렇게 하기 어렵다. 액정을 뜯어내야 하며, 그것을 다시 붙여야 한다. 이러한 과정에서 소비자가 직접 하기 힘든데다가 엔지니어에게 맡길 경우 많은 비용이 소모되는 것이다.
패키지
패키지란 Class들의 모음을 패키지라 한다. Package(패키지)란 말에서 알 수 있듯이 하나의 선물 꾸러미라 생각하면 편하겠다. 여기에 추가로 인터페이스를 같이 묶어두고 하나의 폴더에 저장해둔 것이다. 여기서 인터페이스라 하면 사용할 수 있게끔 만들어주는 장치라 보면 된다. 전자기기에서는 전기 코드가 인터페이스에 해당한다. (전기 코드 자체도 인터페이스이지만, 전자기기의 여러 버튼들 또한 인터페이스라 볼 수 있다.)Interface는 영어 단어 해석에서 보자면 [결합부], [접속기], [대면부] 등의 뜻을 가지고 있다. 특정 물체와 물체가 맞닿는 곳을 인터페이스라 할 수도 있다. 혹은 사물과 사용자가 서로 의사소통 할 수 있도록 만들어 놓은 매개체를 의미한다. 사용자와 맞닿은 인터페이스를 UI (User Interface)라 하기도 한다. 핸드폰에서 보이는 화면 대부분이 UI이기도 하다.
패키지를 두는 대표적인 이유 중 하나는 클래스 이름의 고유성을 보장하기 위해서이다. 프로그래밍 프로젝트가 커지면 커질 수록 패키지 이름이 겹치는 경우가 있는데, 이러한 상황에서 다른 패키지를 사용함으로써 중복을 회피할 수 있는 것이다.
예로 들자면, A와 B는 파일 123을 저장하고 싶은 상태이다. 그런데 바탕화면에다가 저장하면 파일이 중복되서 하나의 파일이 사라질 확률이 있다. 이러한 상태에서 폴더를 따로 둠으로써 이를 피하는 것이다. A는 폴더 'A의 폴더'에 저장하고, B는 'B의 폴더'에 저장함으로써 파일 123은 유지가 되는 것이다.
이제 불러오는 방식을 확인해보면, A의 폴더 -> 파일123과 B의 폴더 -> 파일123은 분명히 구분이 가능한 상태가 되었다.
* 이곳에서는 패키지의 사용법이 아닌 패키지가 무엇인지만 보도록 하고 나중에 패키지를 사용하는 방법에 대해 자세히 다루도록 하자.
자바에서 둘 사이의 차이점? 패키지와 모듈
그렇다면 모듈과의 차이점은 무엇인가? 패키지는 클래스와 인터페이스를 묶어놓은 하나의 폴더를 의미한다. 모듈은 이러한 패키지를 포함해서 특정 필요한 리소스를 모아놓은 하나의 컨테이너이다. 패키지보다는 모듈이 조금 더 상위 개념이라 볼 수 있지만, 그렇다고 패키지 위에 모듈이 있다고는 볼 수 없다. 실행가능하도록 최소한의 것들을 모아놓은 것이라 생각할 수 있다. 그래서 하드웨어적 성능이 떨어지는 IoT 기기 상에서도 응용 프로그램을 실행가능하다.
다시 System.out.println으로 돌아가자.
여기서 System은 System class를 의미하고 있으며, 여러 class와 메소드를 포함하고 있는 것이다.
module에서는 java.base, Package java.lang에 들어있다.
여기에서는 PrintStream에서 out 필드임을 확인할 수 있다. out은 표준 출력 스트림을 의미한다. 여기서
스트림이란?
마우스와 키보드 같은 입력 장치와 모니터, 프린터기 같은 출력 장치에서 보낸 신호와 컴퓨터에서 보낸 신호는 컴퓨터 상에서 알아서 처리해준다. 우리는 하드웨어적인 부분을 신경쓸 필요가 없다. 이러한 작업을 해주는 것이 스트림이다.
스트림은 방향에 따라 두 가지로 나뉘어지는데, 컴퓨터 쪽으로 들어오는 스트림을 입력 스트림이며, 컴퓨터 쪽에서 사용자 방향으로 나가는 스트림을 출력 스트림이라 한다.
여기까지만 공부해도 충분하다. 여기서 더 파고 들어서 그 원리까지 알면 좋겠지만, 마음이 허락 안할 수 있기에 이해력과 마음이 허락하는 한 파고들면 된다.
스트림에 이어서 println
println은 특정 값을 입력받은 뒤에 사용자가 볼 수 있도록 출력해주는 역할을 한다. 하지만 println은 하나만 정의된 것이 아니다.
다양한 형태의 println이 정의되어 있다. 이렇게 하는 이유는 사용자가 어떤 값을 입력할지 모르기 때문이다. 우리가 앞서 보았듯이 컴퓨터는 한정된 형태의 데이터를 인식할 수 있다. 정수면 정수, 실수면 실수, 문자면 문자로 인식하는 것이다. 사람이야 각 형태를 따로 따로 자동으로 인식되지만 컴퓨터는 그러지 못하다. 그러므로 이를 모두 인식할 수 있도록 도와주는 것이 다양한 형태로 정의해두는 것이다. 우리는 이러한 형태를 자바의 다형성이라 불리며 실제 구현 방식 중 하나인 오버로딩(Overloading)방식이라 한다.
같은 이름의 함수를 여러 개 정의하고, 매개변수와 그에 따른 유형 그리고 개수를 다르게 함으로써 사용자의 다양한 호출에 반응하기 위함이다. 그래야지 사용자가 숫자를 호출하건, 문자를 호출하건 다양하게 대응할 수 있는 것이다.