본문 바로가기
생활코딩 학습일기(Web 기초)

12) javascript의 연산자

by cuziam 2022. 8. 29.

목차

  1. 산술연산자
  2. 대입연산자
  3. 증감연산자
  4. 비교연산자
  5. 논리연산자

연산자(operator)가 무엇일까?
연산을 할 때 사용할 때 사용하는 부호다. 연산이라 하면 대개 수학적인 연산, 그러니까 사칙연산을 같은 것을 떠올릴 것이다. 하지만 꼭 수학에만 한정할 필요는 없다. 하나 이상의 대상에서 규칙에 따라 새로운 것을 만들어 내는 조작. 이것을 연산이라고 한다. 그리고 연산의 대상을 피연산자라고 한다. 만약 연산의 대상이 하나면 단항연산자, 두개면 이항연산자, 세개면 삼항연산자라고 부른다. 갑자기 새로운 개념을 몰아쳤으니, 예시를 하나 들어보는 것이 좋겠다.

 

만약 3+5이라는 식이 있다고 하자그럼 3 5는 피연산자이고, 덧셈기호인 +는 이항연산자에 속한다. 그리고 해당 연산자는 양 옆의 수를 더한 수를 내놓는 규칙을 갖고 있다. 만약 임의로 내가 ‘$’기호가 50을 곱하라는 규칙을 가진 연산자로 정했다고 하자. 그럼 3$에서 3은 피연산자 $는 단항연산자이다. 3$는 결과로 150을 내놓을 것이다.

 

javascript에서 제공하는 연산자도 여러 가지가 있다. 7종류 정도로 나눌 수 있는데 그 쓰임을 전부 외우고 있는 것이 좋다. 사실 굳이 외우려 하지 않아도 자연스럽게 외우게 될 것이다. 프로그래밍에서 가장 기본이 되는 것들이기 때문에, 끊임없이 사용하게 되기 때문이다. 그리고 배우기 딱히 어려운 것도 아니다. 어떤 연산자들이 있는지 살펴보고, 실습을 해보자.


산술연산자

산술연산자는 이항연산자이며 사칙연산을 다루는 가장 기본적인 연산자이다. 덧셈, 뺄셈, 곱하기, 나누기, 나머지 연산으로 구성되어 있다. 

산술연산자의 사용 예시

  • + :왼쪽 피연산자에서 오른쪽 피연산자의 값을 더한다.
  • - :왼쪽 피연산자에서 오른쪽 피연산자의 값을 뺀다.
  • * :왼쪽 피연산자에서 오른쪽 피연산자의 값을 곱한다.
  • / : 왼쪽 피연산자에서 오른쪽 피연산자의 값을 나눈다.
  • % :왼쪽 피연산자의 값에서 오른쪽 피연산자의 값을 나눈 후에, 그 나머지 값을 반환한다.

아마 위의 연산자들은 어렵지 않을 것이다. 위의 연산자들은 우리가 평소에 수학 계산을 할 때의 법칙을 그대로 갖고 있다.

초등수학을 잘 배웠다면 크게 어렵지 않다.

  1. 곱셈,나눗셈을 먼저 처리하며 그 다음에 덧셈과 뺄셈을 계산한다.
  2. 왼쪽에서 부터 오른쪽 방향으로 차례대로 계산한다.
  3. 괄호가 씌어진 연산이 있다면, 그것을 최우선적으로 처리한다.

대입연산자

대입연산자는 오른쪽 피연산자의 값을 왼쪽에 대입하는 연산자이다. 프로그래밍 언어를 처음 배우는 사람은 우리가 수학시간에 배운 '등호'의 의미 때문에 조금 헷갈릴 수 있는데 이런 개념은 잠시 접어두자. 이전 편에서 언급하였듯, 메모리 공간에 어떤 값을 저장하는 행위로 생각하는 것이 좋을 것 같다.

 

대입연산자는 사실 '=' 하나라고 무방하다. 하지만 방금 배운 산술연산자와 결합해서 여러 복합 대입연산자를 만들어낸다. 예시를 보자.

대입연산자와 복합대입연산자

  • = : 왼쪽 피연산자에 오른쪽 피연산자의 값을 대입함
  • += : 왼쪽 피연산자의 값에 오른쪽 피연산자의 값을 더하고, 그 결과를 왼쪽 피연산자에 대입함.
    ex) a += 3은 a = a+3 과 동일한 표현이다
  • -= : 왼쪽 피연산자의 값에 오른쪽 피연산자의 값을 빼고, 그 결과를 왼쪽 피연산자에 대입함.
    ex) a -= 2은 a = a-2 과 동일한 표현이다
  • *= : 왼쪽 피연산자의 값에 오른쪽 피연산자의 값을 곱하고, 그 결과를 왼쪽 피연산자에 대입함.
    ex) a *= 7은 a = a*7 과 동일한 표현이다
  • /= : 왼쪽 피연산자의 값에 오른쪽 피연산자의 값을 나누고, 그 결과를 왼쪽 피연산자에 대입함.
    ex) a /= 4은 a = a/4 과 동일한 표현이다
  • %= : 왼쪽 피연산자의 값에 오른쪽 피연산자의 값을 나누고, 그 나머지를 왼쪽 피연산자에 대입함.
    ex) a %= 3은 a = a%3 과 동일한 표현이다

증감연산자

증감 연산자는 피연산자를 1씩 증가 혹은 감소시킬 때 사용하는 연산자이다. 이전의 두 연산자와는 다르게 단항연산자이다.

증감연산자의 예시

  • ++피연산자 : 먼저 피연산자의 값을 1 증가시키고 해당 연산을 진행한다.
  • 피연산자++ : 먼저 해당 연산을 수행하고 나서, 피연산자의 값을 1 증가시킨다.
  • --피연산자 : 먼저 피연산자의 값을 1 감소시키고 해당 연산을 진행한다.
  • 피연산자-- : 먼저 해당 연산을 수행하고 나서, 피연산자의 값을 1 감소시킨다.

증감연산자에서 주의할 것은 연산의 순서이다. 다음 예시를 보자

증감연산자를 사용하는 순서에 따라 출력되는 변수 값이 다른 것을 확인할 수 있다.

위의 코드는 x와 y의 초기값을 10으로 설정한 뒤, 각각 다른 순서로 증감연산자를 사용한 결과를 나타낸다. console.log(x++);에서 x의 값은 먼저  console.log()가 실행될 때 적용된 후, x의 값이 증가한다. 따라서 처음 10이 출력된 뒤, 값이 11로 증가한다. 그 뒤 console.log(++x); 에서는 x값이 1이 증가한 뒤, console.log()가 실행될 때 그 값이 적용된다. 결과적으로 12가 출력된다.

 

y값의 경우 console.log(++y);에서 y값이 우선적으로 1 증가한뒤, console.log() 실행될 때 그 값이 적용된다. 따라서 처음에 11이 출력된다. 그리고 console.log(y++);에서 console.log()가 실행될 때 기존에 y값이 그대로 적용된다. 그래서 다시 11이 출력된다. 그 뒤 y값은 1 증가하여 12가 된다.

 

이해가 되었다면 좀 더 어려운 예시를 풀어보자.

 

y의 값은?

위의 코드에서 y값은 무엇일까? 앞서 배운 것들을 종합해서 생각해보자.

정답은 23이다. 왜 그런지 차근차근 알아보자.

연산순서

산술연산은 앞에서 부터 차례대로 실행되므로 x-- + 5가 먼저 계산된다.

  1. x값이 10인 상태에서 5를 더한다. x-- + 5의 값은 15가 된다. 즉 전체 연산이 y = 15 + --x가 정리되는 셈이다.
  2. 그 뒤 x의 값이 1이 감소하여 9가 된다.
  3. 두 번째 덧셈연산인 15 + --x가 계산되기 시작한다. --x로 인해 x의 값이 덧셈연산을 실행하기 전에 1 감소한다. 즉 x값은 8이 된다.
  4. 전체 연산은 y = 15 + 8로 정리된다.
  5. 결과적으로 y의 값은 23이 된다.

비교연산자

비교연산자는 두 피연산자 사이의 크기를 비교하여 참(true)이나 거짓(false)를 반환하는 이항연산자이다. 

비교연산자의 예시

  • == : 왼쪽 피연산자와 오른쪽 피연산자의 값이 같으면 참을 반환
  • === : 왼쪽 피연산자와 오른쪽 피연산자가 값이 같고, 완전히 같은 자료형이면 참을 반환
  • != : 왼쪽 피연산자와 오른쪽 피연산자의 값이 같지 않으면 참을 반환
  • !== : 왼쪽 피연산자와 오른쪽 피연산자의 값이 같지 않거나, 타입이 다르면 참을 반환.
  • > : 왼쪽 피연산자의 값이 오른쪽 피연산자의 값보다 크면 참을 반환
  • >= : 왼쪽 피연산자의 값이 오른쪽 피연산자의 값보다 크거나 같으면 참을 반환.
  • < : 왼쪽 피연산자의 값이 오른쪽 피연산자의 값보다 작으면 참을 반환
  • <= : 왼쪽 피연산자의 값이 오른쪽 피연사자의 값보다 작거나 같으면 참을 반환.

비교할 때 원칙!

  1. 피연산자가 둘 다 숫자면, 숫자의 대소를 비교한다.
  2. 피연산자가 둘 다 문자면, 알파벳 순서를 대소 비교에 이용한다.
    ex1) "Ace" < "Base" 에서 Ace가 Base보다 알파벳 순서가 빠르므로 true가 반환된다.
    ex2) "Ace" <= "Ace"에서 두 피연산자의 알파벳 순서는 동일하므로 true가 반환된다.
  3. 피연산자의 타입이 다른 경우 javascript엔진이 암묵적 형변환을 시도한 후 대소를 비교한다. 이와 관련된 부분은 따로 글을 다뤄야 하므로 짧게 짚고 넘어가고자 한다.

여기서 헷갈릴 수 있는 부분이 바로 ==과 ===일 것이다. (이것의 반대인 !=와 !==도 당연히 헷갈릴 것 같다) 설명하자면 이렇다.

  • ==은 피연산자의 타입이 서로 다르더라도 강제로 동일하게 만든 뒤에 그 값이 동일한지 비교한다.
    ex) 2=="2"에서 하나는 숫자 데이터, 다른 하나는 문자 데이터임에도 두 피연산자의 데이터 타입을 동일하게 만들면 똑같이 2가 나오므로 true가 반환된다.
  • ===은 값뿐 아니라 데이터 타입까지 정확히 확인한다.
    ex) 2 === "2"에서 두 피연산자의 데이터 타입이 다르므로 false가 반환된다.

+추가지식: 암묵적 형변환

javascript는 암묵적 형변환이란 것을 지원한다. ==연산자에서 그러한 것 처럼, 말 그대로 연산자에 따라서 피연산자의 데이터 타입을 암묵적으로 바꾸는 것이다. (반대 개념으로 명시적 형변환이란 말이 있다. 이는 프로그래머가 직접적으로 데이터의 타입을 다른 것으로 변환시키는 것을 말한다.) javascript의 이런 특징은 양날의 검이다. 사실 요즘은 설계적 결함으로 보는 시선이 더 많다고 한다. 데이터 타입이 명확하지 않으므로 버그를 발생시키기 쉽다는 문제 때문이다. 그래서 프론트엔드 쪽에선 데이터 타입을 정확하게 정할 수 있는 typescript를 사용하는 것을 자주 볼 수 있다.

 

위의 간단한 코드 정도는 괜찮지만...코드가 늘어지면 형변환 때문에 예상치 못한 버그가 자주 발생한다.

 숫자와 문자열을 곱하니까 문자열이 숫자로 바뀌어서 결과가 숫자가 나오거나, 숫자와 문자열을 더했더니 이번엔 숫자가 문자열로 바뀌어서 서로 합쳐진 문자가 나오거나... 기타 등등 이런 자유로운 형변환이 편할 때가 있지만, 편하게 사용하기  위해선 언제 어떻게 형변환이 되는지 정확히 알아두는 것이 좋다. 이를 알고 싶다면 검색을 직접해보거나 아래 링크를 참고하길 바란다.

* 형 변환 : https://ko.javascript.info/type-conversions


 

논리연산자

논리 연산자는 두 피연산자에 주어진 논리식을 판단해서 참과 거짓을 반환하는 연산자이다.

 

논리연산자의 예시

  • && : AND연산(논리곱 연산), 논리식이 모두 참이면 참을 반환.
  • || : OR연산(논리합 연산), 논리식 중 하나라도 참이면 참을 반환.
  • ! : NOT연산(부정 연산), 논리식의 결과가 참이면 거짓을, 거짓이면 참을 반환하는 단항연산자.

+추가지식: 단축 평가

단축 평가가 발생한 논리연산자

방금 전의 예시에선 두 피연산자 모두 불리언값으로 표현되었지만, 이번에는 그렇지가 않다. 처음 보면 당황스러운 결과일 것이다. 왜 위의 결과가 나온 것일까?

 

그것은 논리연산자에서 발생한 단축 평가란 것 때문이다. 대부분의 프로그래밍 언어에서 연산은 앞에서 부터 차례대로 이루어진다. "dog" && false를 예를 들면, 가장 먼저 "dog"가 참인지 아닌지 검사한다. 그 후에 "dog"이 참이면 뒤의 false가 참인지 아닌지 검사하고, 참이 맞다면 true를 내놓는다. 여기까지는 javascript를 포함한 많은 프로그래밍 언어의 공통적인 부분이다.

 

C/C++같은 언어에선 "dog"가 불리언 값이 아니므로 바로 false를 내놓지만 javascript는 다르다! 일단 피연산자가 불리언이 아니더라도 불리언으로 바꿔버린 후, 참 거짓을 판단한다. 문자열의 경우 그냥 참으로 판단해버린다. 그래서 사실상 true && false를 연산한 값이 나오는 것이다.

 

"dog" || false는 어떨까? 왜 "dog"일까? 방금 말한 것으로 따지면 true || false를 계산한 셈인데 말이다. 연산과정을 보자. "dog"을 먼저 연산해보면 "dog"은 true로 변환된다. 그리고 OR연산을 하는데 OR계산은 피연산자 중 하나라도 true라면 true이기 때문에 여기서 javascript 엔진은 연산을 바로 마쳐버린다. 그리고 그 때 논리 연산의 결과를 결정한 그 피연산자를 그대로 내놓는다. 따라서 "dog"이 나온다.

 

이렇게 나머지 피연산자를 건드리지 않은 채 연산을 바로 마쳐버리는 행위를 단축 평가라고 한다.

 

*자세한 내용을 알고 싶다면 링크를 참고하세요(아래 링크에선 단락 평가라는 말로 번역하였음)

논리 연산자: https://ko.javascript.info/logical-operators

 

논리 연산자

 

ko.javascript.info

 


위의 연산자 이외에도 비트연산자, 쉼표연산자, typeof 연산자, delete 등이 존재하는데 이와 같은 연산자는 차차 쓰임을 알아가도록 하자. 이 연산자들을 건너뛰는 이유는 지금 당장은 쓸 일이 거의 없기도 할 뿐더러, 중간에 필요하다면 검색을 통해 충분히 알아낼 수 있을만한 내용이기 때문이다. 또한 현재 생활코딩 학습일기의 글들은 철저히 프로그래밍 입문자를 고려한 글이기 때문에 현재로선 중요도가 낮은 연산자를 잠시 제쳐둘 필요가 있었다. 만약 알고 싶다면 크게 어렵지는 않으니 검색을 통해 알아보면 된다. 

 

다음 글은 "제어문"에 대해서 알아보려고 한다!