3번째 스터디가 진행되었습니다. 벌써 반이나 지났네요.
이번 스터디 시간은 지난 시간에 이어 미처 다루지 못한 나머지 데이터타입과 연산자 나머지 내용과 첫번째 시간에 언급된 변수와 제어문에 대해서도 다시 한번 살펴보았습니다.
변수 vs 상수
1강에서 다뤘던 내용 기억나시나요? 기초 문법으로 배워던 문과 식, 그리고 변수! 그 때 변수를 자세히 살펴보지 못했습니다만, 오늘은 그 변수를 좀 더 자세히 살펴보았습니다.
변수가 뭐지?
많은 책들에서는 변수를 ‘값을 담을 수 있는 그릇과 같은 것’이라고 많이들 이야기합니다.
네 맞습니다. 변수는 말 그대로 ‘변하는 수’로 변하는 값을 임시로 저장하는 곳이죠.
하지만 지난 스터디에서 배웠다시피 변수는 결국 ‘메모리 주소값의 별명’을 의미하는 것이었습니다.
기억 나시죠..?
변수를 쓰면 뭐가 좋지?
그렇다면 변수를 왜 쓰는지 다시 한 번 생각해 볼 필요가 있습니다.
지난번에 메모리 주소를 일일이 기억하는 것이 힘들기 때문에 메모리 주소의 별명으로 변수를 쓴다고 했습니다.
네 맞습니다. 하지만 다른 이유들도 있으니…
장점 1: 코드가 읽기 좋아짐
코드가 읽기 좋아진다는 뜻은 그 코드가 어떤 의미를 가지는지 더 명확해진다는 의미로, 변수 이름을 통해 값이 어떤 것을 의미하는 지를 알려줄 수 있어 값을 직접 쓸 때보다 코드의 의미가 더 명확해집니다. (물론 변수 이름을 잘 지어야한다는 전제 조건이 있습니다만…)
곧 여름이 다가오니 예로 BMI를 구해보죠. BMI(Body Mass Index)는 비만도를 측정하는 지표중 하나로 키, 체중만으로 간단하게 그 값을 구할 수 있습니다. (하지만 실제로 체지방율이나 체형 및 비만도를 제대로 반영하지 못한다는 치명적인 단점이 있다는…-_-;;;)
다음은 키가 160cm이고 55kg가 나가는 사람의 BMI를 구하는 예시입니다.
//비만도 계산하기 var bmi = 0 ; //값으로 직접 BMI 구하기 bmi = 55 / (160 * 160); // 변수를 사용해 BMI를 구하기 var height = 160; var weight = 55; bmi = weight / (height * height);
위에서 보시다시피 변수를 썼을 때 코드만 보고도 BMI 공식이 몸무게를 키의 제곱으로 나누는 것이라고 알 수 있죠?
장점 2 : 유지/보수할 때 훨씬 수월해짐
위의 예에서 BMI뿐만 아니라 남자/여자의 표준 몸무게도 구한다고 생각해봅시다.
//값으로 구하는 경우 menAvgWeight = 160 - 100 * 0.9; //남자 표준 몸무게 womenAvgWeight = 160 - 100 * 0.85; //여자표준 몸무게 //변수로 구하는 경우 menAvgWeight = height - 100 * 0.9; //남자 표준 몸무게 womenAvgWeight = height - 100 * 0.8; //여자표준 몸무게
그런데 만약 170cm에 70kg인 사람의 치수로 값을 변경해야 한다면 어떻게 될까요?
값으로 썼던 부분을 모~~~두 직접 다 바꿔줘야 합니다.
게다가 바꿀 때 바꾸는 값이 진짜 키 또는 몸무게인지 확인도 해봐야 하구요.
값으로 쓴 경우에는 아주 귀찮고 시간이 많이 걸리지만… 변수를 이용하면 변수에 할당 값만 바꿔 간단하게 수정할 수 있습니다.
// 값으로 쓴 것에서는 160은 170으로, 55는 70으로 모두 바꿔줘야함. bmi = 70 / (70 * 160); menAvgWeight = 170 - 100 * 0.9; womenAvgWeight = 170 - 100 * 0.85; // 변수를 사용한 경우에는 할당값만 바꿔주면 됨 var height = 170, weight = 70;
변수를 이용한 것이 훨씬 더 쉽지요^^?
변수를 잘 활용하도록 합시다.
자바스크립트 버전과 변수 선언
아시다시피 자바스크립트에서는 ‘var’ 키워드로 변수를 선언해 사용할 수 있습니다.
var defineVar; //변수를 만든다는건 선언한다고 합니다. var defineOnly; //이렇게 키워드 + 변수명만 써서 선언만 할 수도 var defineAndAssign = 3; //선언과 할당을 같이 할 수도 있어요.
그런데 var 말고도 또 변수를 만들 수 있는 방법이 있는데..
그 방법을 알아보기 전에 우선 자바스크립트의 버전에 대해 알아봅시다.
프로그래밍 언어는 만들어지면 가만히 있는 것이 아니라 점점 좋은 방향으로 진화를 합니다. (물론 다 그런건 아니구요, 선택받지 못해 도태되어 죽는 아이들도 있습니다ㅠㅠ 진정한 약육강식의 세계!)
그리고 그 진화의 내용은 버전으로 구별하구요.
자바스크립트(정식 명칭은 ECMA Script)는 2015년을 기준으로 아주 획기적인 내용의 진화가 일어나는데요, 그 버전을 ECMA2015(=ES6)라고들 합니다. 그 뒤로도 꾸준히 업데이트가 되어 그 다음버전은 ES7이 아닌 년도별 명칭으로 ECMA2016, ECMA2017…이렇게 붙이기로 약속했습니다.
아쉽게도 ECMA2015가 모든 브라우저에서 작동하지는 않고, ECMA2015라고 하더라도 이전 버전도 모두 작동 되므로 통 자바스크립트를 배운다고 하면 ES3/ES5를 기준으로 배웁니다. (*저희 교재는 ECMA2015 기준!)
ECMA2015를 기준으로 내용이 아주 많이 바뀌었습니다. 변수 선언 방식도 바뀌었는데요, 새로운 키워드인 ‘let’을 통해 변수 선언을 할 수 있습니다.
let version; // var처럼 선언만 할수도 version = 'ECMA2015'; let companyName = 'Bsidesoft'; //선언과 할당을 같이 할 수도 있어요!
상수
한편 ECMA2015에서는 let 말고 상수를 선언할 수 있는 키워드 const가 추가되었습니다.
상수는 그 값이 한번 정해지면 프로그램에서 변하지 않는 값으로 변수와 상대되는 개념을 말합니다.
const COMPANYNAME1 = 'Bsidesoft'; //ECMA2015에서는 const라는 키워드로 상수를 만들 수 있어요. const COMPANYNAME2; //const는 선언할 때 할당을 안하면 에러나요.
그렇다면 const로만 상수를 만들 수 있는걸까요?
저는 ECMA2015이전에는 const키워드가 없고 var로 선언한 변수는 계속 값 변경이 가능하니까 자바스크립트에서 상수는 없다고 생각했습니다. 다른 프로그래밍 언어에서는 상수를 선언하고 다시 값을 변경하려고 하면 에러가 나던데… 그렇게 ‘시스템적으로 값을 변경할 수 없어야만 상수’라고 생각을 했습니다.
그런데 상수는 개념적인 정의입니다. 즉, 실제로 값을 변경할 수 있고 없고의 여부보다, 의미상 변하지 않는 값이면 시스템으로 변경할 수 있어도 상수의 의미를 가집니다. var로 선언한 변수도 앞으로 변할 가능성이 없거나, 코드로 값을 못바꾸게 막아두었다면 상수인 것입니다. 실제로도 우리가 변수로 쓴다는 많은 값들의 대부분은 상수입니다. 그래서 책에서는 처음에 const를 이용해 상수로 선언하고, 나중에 변하면 let 변수로 바꿔 사용하라는 언급하기도 했습니다.
undefined vs null
저번 시간에도 언급을 했지만, 자바스크립트의 데이터타입은 총 7가지가 있습니다. (*데이터 타입을 알려주는 연산자 typeof의 반환값과는 조금 다르다는 점도 잊지 않으셨죠?)
- String
- Number
- Boolean
- Undefined
- Null
- Symbol
- Object
이 중에서 전에 살펴보지 못한 undefined와 null을 알아봅시다.
Undefined란 말 그대로 define되지 않음을 의미합니다. 즉, 값이 없다는 것을 알려주는 데이터 타입입니다.
한편, Null은 ‘값이 비어있는 값’을 의미합니다.
Undefined와 Null 둘 다 값이 없다, 값이 비어있다 똑같은 말인 것 같은데… 두 개가 참 헷갈리죠…? 말장난 같기도 하고^^…
값이 없다는 것과 빈 값을 갖는다는 것은 우리에게 똑같은 것으로 느껴질 지도 모르겠지만, 컴퓨터는 이것을 다르게 구별합니다. Undefined는 값 자체가 없는 것인 반면에 Null은 값이긴 값이거든요.(단지 값의 의미가 빈값이라서 그러지…) 빈 값이라는 표현이 헷갈린다면 아무것도 아닌 값, 아무 의미도 없는 값이라고 하면 될 것 같습니다.
헷갈리는 두 타입, 다음의 그림처럼 비유할 수 있습니다.
(저는 이 그림을 보고 아하?하고 깨달음을 얻은…!!)
아 아직도 헷갈리신다구요..? 그렇다면, 언제 Undefined를 갖는지를 기억하시면 될 것 같습니다.
- 변수 선언 후 초기화를 안한 경우.
var a; //이 때 a에는 undefined가 할당됨
- 함수에 return값이 정의되지 않은 경우, 함수 호출시 undefined 리턴됨.
〉console.log('a'); ------------------------ a < undefined //console.log는 리턴 값이 없으므로 undefined 리턴
복합 연산자, 증감연산자
지난 후기에 자세하게 담지 못했지만, String, Number, Boolean 데이터 타입을 다루면서 각각의 데이터 타입과 관련된 연산자들을 살펴보았습니다. 데이터 타입을 알게 되었다면 그 데이터의 값을 바꿀 수 있는 여러가지 방법들을 배운 것이죠.
Number타입에서는 우리가 잘 아는 사칙연산을 할 수 있는 +, -, *, / 와 조금은 특이한(?) 나머지 연산자 %가 있었고, String에서는 +연산자, 그리고 Boolean에서는 비교 논리 연산자를 살펴보았습니다. 그 외에도 연산자의 우선순위와 연산자의 작동 방향(왼쪽에서 오른쪽), 그리고 대입 연산자까지 많은 내용이 다뤄졌는데요…그 것 말고도 또 많은 연산자가 있었으니!!
바로 복합연산자와 증감연산자입니다.
복합연산자는 말 그대로 복합적인 연산자로, 기본 연산을 한 후 대입까지 2가지 연산을 한번에 처리할 수 있는 연산자입니다.
x += y // 덧셈후 대입. x = x + y와 동일 x -= y // 뺄셈후 대입. x = x - y와 동일 x *= y // 곱셈후 대입. x = x * y와 동일 x /= y // 나눗셈 이후 대입. x = x / y와 동일 x %= y // 나머지 연산후 대입. x = x % y와 동일
위 예 이외에도 다른 복합 연산자들이 있으니 확인해보세요!
복합연산자가 등장하게 된 가장 큰 이유는 아마도 ‘중복’이지 않을까 싶습니다.
개발자들이 ㅓ누너문아럼눔나어러 너무너무 싫어하는 것 바로 중복…
중복이 왜 싫으냐!!!
첫번째, 키보드를 한 번이라도 더 적게 누르는 코드를 짜야합니다. 하지만 중복은 키보드를 아주아주 많이 치게하므로 안됩니다.
두번째, 유지보수 측면에 있어서 최악인 중복! 중복 코드가 있는 만큼 수정할 게 많아집니다.
그러므로 여러분, 중복은 없애야 합니다.
그래서 자주 쓰는 것은 언어에서 기능으로 지원해주는 경우가 있는데, 복합연산자도 언어차원에서 만들어준 것이 아닐까 합니다.
그래서 좋은것 같지만……… 이녀석, 꽤나 어렵습니다.
뭐가 어렵냐면… 말한대로, 저” var a = 3; a += 3; ” 두줄에 참 많은 것이 담겨 있기 때문이죠.
저 코드를 자세하게 분해해봅시다.
우리는 사람은 단 3줄로 이해하지만, 컴퓨터는 위 내용처럼 꽤 많은 과정을 거칩니다. 짧은 2줄의 코드에 저렇게 긴 내용을 컴퓨터가 처리해주니 좋은 것 같죠?? 하지만 문제는 바로 이것입니다. 복잡한 연산이 함축될수록 우리가 인식하는 과정과 컴퓨터가 실제 작동하는 과정에 간극이 생깁니다.
컴퓨터는 8번의 과정을 거쳐 차근차근 한줄씩 실행을 해나가는데 그 한줄 한줄이 컴퓨터에겐 시간입니다. 즉, 우리의 시간과 컴퓨터의 시간은 다르다는 것이죠. 컴퓨터의 시간은 처리 또는 상태의 변화를 의미하기도 하는데, 이렇게 한번 처리하는 것을 ‘클럭’이라고 합니다. 이 클럭을 1초동안 얼마나 많이 할 수 있느냐에 따라 CPU의 성능이 결정됩니다.
제어판 > 컴퓨터 시스템 가면 내 컴퓨터의 능력치를 확인해 볼 수 있어요.
어쨌든, 복합 연산자를 쓰면 우리에게 한줄로 보이지만(=동시에 일어난다고 착각하게 만드는) 사실은 그 사이에 많은 클럭들이 발생합니다. 그리고 그 숨겨진 클럭들이 많을 수록, 데이터의 상태를 정확하게 추적하기 어려워지므로 에러가 발생하는 확률도 높아지겠죠…☆
다음은 증감 연산자로 1만큼 일정하게 증가 또는 감소시켜주는 연산자입니다.
//사용은 이렇게~ var a = 3; //후위 연산(나중에 연산) a++; a--; //전위 연산(먼저 연산) ++a; --a;
개념은 참 간단하지만… 연산을 먼저 하느냐(전위) 나중에 하느냐(후위) 순서까지 포함하므로 연산 결과를 추측하기가 어렵습니다.
다음 예를 살펴봅시다.
console.log(arr)의 결과는 무엇일까요?
그리고 마지막 때의 index의 값은 어떻게 되구요..?
var arr = ['a', 'b', 'c', 'd']; var index = 0; arr[index++] = arr[index++]; console.log(arr);
가장 복잡한 부분인 arr[index++] = arr[index++]이 문제죠.
저 부분의 연산은 크게 보면 오른쪽의 값을 왼쪽에 할당하는 ‘대입 연산’입니다. 대입 연산을 하려면 왼쪽과 오른쪽의 값을 각각 하나의 값으로 수렴시켜야 합니다. 코드는 대입연산자를 제외하고 항상 왼쪽에서부터 오른쪽으로 진행하니까 먼저 왼쪽의 값을 하나의 값으로 수렴시킵니다.
1. 왼쪽 항 arr[index++] 연산
왼쪽항 arr[index++]은 대괄호 연산을 먼저 해야합니다.
그런데 대괄호 안의 값을 보니 index++ 증감 후위 연산자이므로 arr에 index값을 먼저 할당한 뒤 index의 값을 1 증가시켜줘야 합니다.
따라서 왼쪽 항의 연산결과는 arr[0]이며, 그 상태에서 index의 상태는 1입니다.
2. 오른쪽 항 arr[index++] 연산
오른쪽 항도 왼쪽 항과 같은 arr[index++]이므로 대괄호에 index값을 할당한 후에 index에 1을 증가시켜줍니다.
하지만 이미 왼쪽항 연산을 통해 index가 1인 상태입니다. 따라서 오른쪽 항의 연산결과는 arr[1]이며, index의 상태는 2가 되어 있습니다.
3. 대입연산
양쪽의 항이 arr[0] = arr[1] 하나의 값으로 수렴하니 대입 연산을 진행할 수 있습니다.
대입연산이므로 왼쪽항은 arr[0]이 가리키는 변수를 인식하고, 오른쪽항 arr[1]은 그 값인 ‘b’를 찾습니다. 그리고 그 값을 arr[0]에 대입합니다. 그 결과 arr은 [‘b’, ‘b’, ‘c’, ‘d’]가 됩니다.
4. 결과
따라서 console.log(arr)의 결과는 [‘b’, ‘b’, ‘c’, ‘d’]이며, 이 때 index의 값은 2입니다.
허허.. 참 복잡하죠..?
그래서 이런 복잡한 연산자는 쓰지 않거나, 쓸 때에는 아주 깊게 주의하며 쓰기로… (심지어 어떤 언어에서는 ++, --와 같은 연산자를 악마의 연산자라며 금지시키기도 했다고 하네요 ㅎㄷㄷ)
2장은 끝!
이로서 2장의 길고(?) 자세한 내용이 끝났습니다. 배우고나니 프로그래밍이 요리와 비슷하다는 생각이 들었습니다. 2장에서 배운 데이터 타입과 연산자등의 기본 내용이 마치 본격적으로 요리를 하기에 앞서 도마, 칼 처럼 음식을 다루는 도구들을 배우고, 재료에는 야채, 과일, 고기등 어떤 종류가 있는지를 살펴보며 각각의 재료들과 도구들간의 관계를 살펴본 것 같은 느낌..?
그리고 다음 장인 3장 조건문은 마치 불을 어떻게 다룰 것인가와 같은 느낌이랄까…?
실제 스터디에서는 3장도 나갔습니다만 다음주에도 계속해서 조건문 관련해 제어문(Control Statement)를 살펴볼 것 같으니 그 때 다시 정리하기로 하고, 지금까지 배운 기초를 다시한번 꼼꼼히 되새겨봐야겠다고 생각했습니다. 재료와 칼질방법을 잘 모르면 제대로 된 요리를 할 수 없을테니까요!!!
동영상 강의 보기
summer| bsidesoft 신입사원
디자인을 공부했던 섬머는 개발까지 해버리겠다는 욕심으로 개발자의 세계에 입문하게 되었습니다. 개발왕이 되어 멋진 제품을 만들어내는 꿈을 꾸고 있습니다. 코드, 디자인을 포함한 세상의 모든 아름다운 것들과 미드, 그리고 달리기를 좋아합니다.
recent comment