1주차 월요일, Javascript Study+코딩테스트

Edwin·2023년 2월 13일
post-thumbnail
  • 본 내용은 javascript-study를 기반으로 하고 있으며, 이해한 언어로 풀어쓴 정리노트이다.
    javascript-study

항해99-1주차, Javascript Study

Day 01. Hello World!

01) 시작하기 전에

컴파일 언어와 인터프리터 언어

먼저 컴파일이라는 용어에 대한 정의가 필요하다. 컴파일이란 "소스코드"를 작성함으로 컴퓨터가 알아들일 수 있도록 사람의 언어를 컴퓨터의 용어로 번역하는 과정(0과 1의 이진법)이다. 이러한 번역의 과정에는 대표적으로 두개의 언어군으로 나눠진다.

컴파일 언어는(C언어, Java 등) 기록된 문서를 전부 읽고 난 뒤에 실행을 한다.

  • 기록된 문서를 전부 읽어야 하기에, 컴파일에도 시간이 많이 걸린다.
  • 번역의 과정에서 문법을 검사하는데, 이 과정에서 실행 전에 에러에 맞추치는 상황이 발생한다.
  • 그러나 장점으로는, 실제 프로그램이 실행되는 과정에서 발생될 오류는 적어진다는 특징이 있다.

인터프리터 언어는(Python, Javascript) 반면에 한 줄씩 읽어가며 문장을 실행한다.

  • 별도의 컴파일의 시간이 필요하지 않아, 동작이 빠르게 되지만, 실행의 과정에서 발생되는 오류를 즉시로 해결해야 하는 국면을 마주치게 된다.

메모리/저장공간 그리고 프로그래밍 언어

프로그램이 동작하기 위해서는 두 가지의 자원이 필요하다. 이 두 가지의 자원과 프로그래밍 언어를 설명하는 가장 대표적인 접근은 성능/안전성과 편의성의 Trade-off관계라는 용어로 접근함에 있다. 쉽게 설명하면, 하나를 얻으면 하나를 잃는다.

프로그래밍 언어가 실행되는 환경에서 언저 자체에 권한을 부여할수록(메모리 관리 등) 프로그램의 성능과 안정성은 일반적으로 떨어지게 된다. 이는 메모리 관리까지 코드를 통해서 제어하는 순간 개발 난이도와 시간이 비례적으로 상승하기 때문이다.

반대로 프로그래밍 언어를 최적화 시켜서, 메모리를 제한적으로 관할하게 되면, 개발 난이도와 시간은 줄어들 것이다. 물론 이렇나 경우 편의성을 가져온 것이지만, 따르는 결과도 있다. 별도의 처리가 필요해지가 때문이다. 그런 부분에서 프로그램의 전체적인 성능이 하향된다.

프로그래밍 패러다임

이 용어는 개발자가 프로그래밍을 바라보는 관점을 설명한다. 예를 들어 객체지향 프로그래밍은 개발자들의 시야가 상호작용을 하는 객체들의 집합으로서의 프로그램에 쏠린다는 것이고, 함수형 프로그래밍은 상호작용보다는 함수가 연속적으로 실행되는 프로그램의 관점에 집중된다는 것을 의미한다.

언어 자체가 프로그래밍을 설정하는 것이 아니라, 언어를 컴파일 하는 개발자가 위의 두개의 패러다임을 선택하고 코드를 작성하는 것임으로, 어떤 패러다임을 자신이 가지고 코드를 작성하고 있는지를 점검해 보는 것은 코드를 작성하기 전에 개발자가 가져야할 덕목 가운데 하나인 셈이다.

02) Javascript

자바스크립트는 1995년 웹페이지를 동적으로 움직일 수 있도록 하고 싶다는 욕망에서 탄생되었다. 자바스크립트로 작성한 프로그램을 스크립트(script)라고 부르는데, 스크립트는 사전작업이나 컴파일 없이 문서를 한 줄 한 줄 읽어가며 코드를 실행하는 컴파일 언어군에 속한다. 반면에 유사어인 Java는 인터프리터 언어군에 속하기에 이 둘은 완전히 다른 언어임을 먼저 인지하자.

  • 초기이름 : LiveScript
  • 용어변경 : 자바의 인기를 염두에 두고, 홍보차원에서 이름이 Javascript로 변경되었다.
  • 현재상황 : ECMAScript라는 고유한 명세를 갖춘 독립적인 언어가 되었다. 현재 버전10 (ES2019)
  • 사용의 확장 : 서버에서까지 현재 사용되고 있다.

    V8(Chrome과 Opera), SpiderMonkey(Firefox)과 같은 자바스크립트 엔진을 통해 동작한다.

브라우저

브라우저에서는 '가상머신'이라 불리는 엔진이 내장되어 있기에, 특별한 설치 없이 사용가능하다. 브라우저에서는 새로운 HTML을 추가하거나, 수정, 마우스의 움직임에 따른 제어, 서버에 요청을 보내어, 파일을 다운받거나, 업로드 하는 것 등이 가능히다. 또한 클라이언트 측에 데이터 저장을 하는데 이때에는 로컬 스토리지를 통해서 해당 과정을 수행한다.

그러나 할 수 없는 일도 존재한다. 대표적으로 보안과 관련된 영역이다. 스크립트는 로컬에 저장된 임의의 파일을 읽고, 쓰고, 복사, 실행하는데 제한을 받을 수 있다. input 태그를 통해 파일을 선택할 때와 같은 상황에서라도 제한적 허용만 승인한다.

이러한 제한 사항을 Same Oring Policy(동일 출처 정책)이라고 부른다. 물론 자바스크립트를 이용한 페이지 사이에서는 정보를 쉽게 주고 받을 수 있다. 그러나 보안과 관련된 문제 때문에 타 사이트나 도메인에서 데이터를 받아노는 건 불가능하다.

그럼에도 Node.Js 환경에서는 임의의 파일을 읽거나 쓰고, 네트워크에 요청을 수행하는 함수를 지원한다.

3가지 장섬

  1. HTML/CSS와 완전히 통합이 가능함
  2. 어려운 일을 쉽게 처리하도록 도움
  3. 모든 주요 브라우저에서 지원하고, 기본 언어로 사용됨

03) Javascript 기본문법

실행되지 않은 경우(1) src 경로가 선언되어 외부와 연결된 경우
<script src="file.js">
  alert(1); // 
</script>

이와 같이 태그의 속성이 선언된다면, 자바그크립트 내부에 있는 내용은 실행되지 않는다.

자바스크립트와 세비콜론(;)

자바스크립트는 줄 바꿈이 있으면 이를 '암시적' 세미콜론으로 해석한다. 그러나 줄바꿈이 있다면 생략할 수도 있고, 오류가 발생되지 않는다. 또한 코드의 가독성 때문에 코드를 각 문은 다른 줄에 기록하는 것이 일반적이다. 물론 때에 따라 동작은 하지만 오류가 발생되는 경우가 존재하기도 한다.

  • 에러발생
alert("에러가 발생합니다.")
[1, 2].forEach(alert)
  • 정상작동
alert("제대로 동작합니다.");
[1, 2].forEach(alert)
엄격모드

자바스크립트는 오랜시간 호환성 문제 없이 발전을 거듭했지만, 기존의 기능을 변경하지 않는 선에서 새로운 기능을 추가시켰다. 이러한 변화는 기존에 작성한 코드가 절대 망가지지 않는다는 장점이 있지만, 초기의 불완전한 결정이 언어 안에 영원히 남게 된다는 단점도 발생되었다.

그 결과 ECMAScript(ES5, 2009)를 기점으로 기존의 관점이 수정되었다. 기존 기능 중 일부가 변경되었다. 이것이 의미하는 것은 무엇일까? 기존의 기능의 호환성 문제가 발생되었다는 것이다. 그래서 등장한 코드가 아래의 코드이다. 해당 코드를 최상단에 기록하면, ECMAScript(ES5, 2009)이전의 작동방식으로 즉, '모던한' 방식으로 동작한다. 이를 엄격모드라고 부른다.

"use strict";

기능개발을 테스트하기 위해 브라우저 콘솔을 사용하는 경우가 있는데, 콘솔은 "use strict";에서 무관하기에, 에디터에서 기록하는 방식과 다르게 기록해야 한다.

'use strict'; <Shift+Enter를 눌러  바꿈 >
//  ...테스트하려는 코드 입력
<Enter를 눌러 실행>

또는 함수로 감싸주어 실행하는 수 밖에는 없다.

(function() {
 'use strict';

 // ...테스트하려는 코드...
})()
변수선언(var, var의 단점을 극복한 const와 let)

그러나 변수가 선언될 때, 사용하지 못하는 단어들이 존재한다. 이것을 예약어라고 한다. break case catch class const default 같은 단어들이다. 이는 이미 Javascript에서 사용하고 있는 단어들이기 때문에, 이 단어들의 실행을 위해서 변수로 선언되지 못한다. 해당 단어들의 목록은 모질라 사이트에서 확인할 수 있다.
모질라, 예약어 리스트

첫째날에 대한 코딩테스트

명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다. 아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.

가장 긴 가로 길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다. 하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.
모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다. 모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때, 지갑의 크기를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • sizes의 길이는 1 이상 10,000 이하입니다.
  • sizes의 원소는 [w, h] 형식입니다.
  • w는 명함의 가로 길이를 나타냅니다.
  • h는 명함의 세로 길이를 나타냅니다.
  • w와 h는 1 이상 1,000 이하인 자연수입니다.
function solution(cal) {
  let arr1 = [];
  let arr2 = [];
  let arr3 = [];
  for(let i =0;i<cal.length;i++) {
     if(cal[i][0] > cal[i][1]) {
       arr1.push([cal[i][0], cal[i][1]])} 
     else {arr1.push([cal[i][1], cal[i][0]])}}
     
  for(let i =0;i<arr1.length;i++) {
    arr2.push(arr1[i][0])
    arr3.push(arr1[i][1])}
    
  return arr2.sort((a,b) => b-a)[0] * arr3.sort((a,b) => b-a)[0]}

풀이는 했다. 일단 문제를 이해하는 것이 너무나 어려었다.

  • 1) 매개변수로 들어온 내용을 반복문으로 돌려서 arr1의 빈 배열에 담았다.
  • 1-1) 이때만 해도 Math.max 매소드를 완전히 까먹고 있었기 때문에 무조건 배열을 내림차순으로 만드록자 했다.
  • 2) 조건문을 통해서 [a, b]의 값을 비교하여 높은 숫자가 앞으로 가도록 조건문을 주었다.
  • 3) 그리고 다시 반복문을 실행하여, arr2와 arr3에 시키는데 a는 arr2 배열에, b는 arr3 배열로 들어가게 하였다.
  • 4) arr2와 arr3를 다시 역순으로 정렬해서 첫번째 값을 곱해주는 내용으로 코드를 구성하였다.
팀원의 풀이
  • 2)번의 과정을 생략하고 그냥 매열에 집어 넣었다. 그러기에 조건문이 없었다.
  • 4)번의 정렬의 과정도 없었다. 그냥 Math.max 매소드와 전개구문을 가지고 접근하여 해당 문제를 풀었다.
function solution(cal) {
  let arr1 = [];
  let arr2 = [];
  let arr3 = [];
  for(let i =0;i<cal.length;i++) {
     arr1.push([cal[i][0], cal[i][1]])
     arr2.push(arr1[i][0])
     arr3.push(arr1[i][1])
  return Math.max(...arr2) * Math.max(...arr3)

이래서 한 번 보는 것이 아니라 계속 반복해서 살펴볼 이유가 있는 것이다. 분명 알고 있는 내용들이었지만 사용하지 않으니 완전히 까먹었다.

다른사람의 풀이
function solution(sizes) {
    const newSizes = sizes.map(e => e.sort((a, b) => a - b));
    return Math.max(...newSizes.map(e => e[0])) * Math.max(...newSizes.map(e => e[1]));
}

그렇다 나도 처음에 map매소드를 사용하려고 했는데, 접근하지 못했던 코드기록이었다. 그런데 두번이나 들어갔구나. 코드를 읽어보자.

  • 1) map 매소드를 통해서 들어온 인자를 하나씩 인자의 값을 정렬하는데, 낮은 숫자가 앞으로 오게 하였다.
  • 1-1) 그렇게 반영된 값을 콘솔에 기록하였다.
  • 2) 이렇게 정렬된 newSizes를 전개구분으로 돌려서, 0번지에서 최고값을 구하고, 1번지에서 최고값을 구하여 곱셈을 하였다.

04) TIL

KeyWords
: html, css, 웹 브라우저, 인터프리터 언어, 런타임, 자바스크립트 엔진, node.js, 멀티 패러다임, 타입, 메모리

JS는 인터프리터 언어군에 속한 프로그래밍 언어다. 컴파일 언어와 달리 한 줄씩 코드를 실행해 컴파일링 속도가 빠르며, 메모리를 할당받는 것도 주어진 상황에서만 할당받기에 부화를 덜 발생시킨다.

런타임이란 JS가 구동할 수 있는 환경을 말하는데, 웹브라우저와 Node.js가 대표적이다. 각각의 환경에는 JS가 동작하게 하는 여러 엔진이 존재하는데 그 종류로 V8(크롬, 오페라), SpiderMonkey(파이어폭스), 가상머신(브라우저) 등이 있다. JS는 해당 엔진을 통해 HTML과 CSS를 제어함으로(변경, 동작 구현) 사용자에게 동적인 환경을 제공한다.

비록 JS는 그 자체적으로 패러다임이 없지만, 개발자가 선호하는 방식에 따라서 함수형 패러다임과 객체지향 패러다임 등으로 나뉜다. 그러나 개발자는 한 패러다임에 갇히지 않고 상황에 따라서 코드를 작성할 수 있는 유연함(멀티 패러다임)이 필요하다.

마지막으로 JS는 프로토타입 기반 언어에 해당한다. 객체를 복사하여 새로운 객체를 생성하는 특징을 가지고 있기 때문이다. JS 프레임워크인 React에서 이러한 단위를 component라고 부른다.

1. 참고자료, 모질라
2. 프로토타입 이해

05) 나가는 말

계속 새로운 내용을 배우는 것은 신선하고 재미있다. 그러나 지나간 것을 되돌아 보지 않는다면, 완전히 내것이 되지 못하는 것을 다시금 발견했다. 한참 코딩테스트를 했을 때는 어려운 매소드들을 쉽게 다루었지만, 시간이 지나고 새로운 내용이 들어오자, 결국 신선함 보다는 익숙함만이 남았고, 코드는 길어졌다. 이를 해결하려면 어떻게 할까? 복습이 답이다. 복습.

그러기 위해서 다시 정리하지 않기 위해, TIL을 지금까지 열심히 적지 않았는가? 복습만이 익숙해짐의 살길이다. 외움이 아니라. 익숙해짐이다. 그러기에 오늘의 내용을 토대로 잃어버렸던 배열 매소드들을 와전히 정리하고 넘어가자.

나만의 복습방법

TIL을 열심히 적는 이유는 웹페이지를 PDF로 아이패드에 담아서 보기 때문이다. 한 번 나의 언어로 정리된 글은 세상 그 어떤 글보다 독해력이 높다. 그리고 다시 읽었을 때 이것을 처음 접했을 때의 아찔함이 되새김질 되기 때문에, 추억이 젖어있는 내용들이라 더 머리속에 스며드는 것 같다. 그렇게도 원격저장소인 아이패드로 부터 다시 pull 받아, 새로워지자!

profile
신학전공자의 개발자 도전기!!

0개의 댓글