Javascript 핵심 개념 학습
Wireframe 개념 학습
CSS 핵심 선택자 및 display 속성(flex) 학습
한 번에 다량의 데이터를 사용해야 할 때, 배열 또는 객체를 사용한다면, 단 한번의 선언으로 대량의 데이터를 다룰 수 있습니다.
다양한 데이터 타입 중 배열과 객체는 대량의 데이터를 쉽게 다룰 수 있게 해줍니다.
대량의 데이터를 다루기 적합한 배열과 객체는 참조 타입(reference type)의 데이터 입니다.
이 참조 타입에 대해선 아래에 서술하겠습니다.
배열 : 컴퓨터 과학에서 배열은 번호와 번호에 대응하는 데이터들로 이루어진 자료 구조를 나타낸다. 일반적으로 배열에는 같은 종류의 데이터들이 순차적으로 저장되어, 값의 번호가 곧 배열의 시작점으로부터 값이 저장되어 있는 상대적인 위치가 된다. - 출처
배열은 대량의 데이터들을 순서를 정해 처리해야할 때, 사용하는 데이터 타입입니다.
Javascript에서 배열은, [a, b, c]
대괄호로 선언하며, 그 안의 요소(element)를 콤마로 구분합니다.
또한, 이 배열의 순서를 매기는 방식은 0부터 매깁니다. 이 순서를 인덱스(index)라 합니다.
index[0]
은 배열의 0번째 인덱스를 조회합니다. 즉, 배열의 첫번째 값을 리턴합니다.
우리에게 무언가 시작한다는 의미의 숫자는 1인데, Javascript에선 0이 됩니다.
다른 나라들은 태어날 때부터 0살이지만, 우리나라는 태어날 때부터 1살인걸로 보아, 인덱싱이 0부터 시작한다는 게 더 어색하게 느껴지는 것 같습니다...
배열은 내부 요소들을 다룰 수 있는 다양한 메소드가 있습니다.
index[]; // 해당 인덱스의 요소 조회
Array.length; // 배열의 길이(배열 요소의 갯수)
Array.push(); // 특정 값을 배열의 마지막 인덱스에 추가
Array.pop(); // 배열의 마지막 요소 삭제
Array.isArray(); // 변수가 배열인지 아닌지 판별
Array.shift(); // 배열의 맨 앞의 요소 삭제
Array.unshift(); // 배열의 맨 앞에 특정 값 추가
Array.slice(start, end); // 배열의 시작부터 끝까지 잘라내어 복사본 생성
Array.splice();
.
.
.
이 외에도, 배열을 다룰 수 있는 다양한 메소드를 여기에서 확인하실 수 있습니다.
객체 : 컴퓨터 과학에서 객체 또는 오브젝트(object)는 클래스에서 정의한 것을 토대로 메모리(실제 저장공간)에 할당된 것으로 프로그램에서 사용되는 데이터 또는 식별자에 의해 참조되는 공간을 의미하며, 변수, 자료 구조, 함수 또는 메소드가 될 수 있다. 프로그래밍 언어는 변수를 이용해 객체에 접근하므로 객체와 변수라는 용어는 종종 함께 사용된다. 그러나 메모리가 할당되기 전까지 객체는 존재하지 않는다. -출처
Javascript에서 객체는 하나의 변수에 여러 정보를 담아 처리해야할 때 사용하기 적합합니다.
어떤 게임 캐릭터에 비유해보자면...
리그 오브 레전드의 89번째 챔피언인 아리입니다.
챔피언들을 출시 순으로 조회하고 싶다면, 배열을 사용해 쉽게 조회할 수 있을 것 같습니다.
leagueOfLegendsChampions.index[88] ; // 'Ahri'
그러나, 아리
라는 챔피언의 정보를 알고 싶다면?
아리의 별칭은 구미호, 주 역할군은 마법사, 소속은 아이오니아, 가격은 790RP, 성우는 이용신, 캐릭터 스펙은 blah blah...
이 아리
라는 챔피언에 담긴 수많은 관련 데이터들을 처리하고, 조회하기 위해선 객체를 사용해야 합니다.
또한, 100가지가 넘는 챔피언이 존재하는 리그오브레전드에서, 챔피언의 이름, 별칭, 가격, 캐릭터 스펙 등 다른 값을 가지지만 입력해야하는 데이터의 종류가 동일한 경우, 이를 객체를 사용해 쉽게 처리할 수 있습니다.
let Ahri = {
Name: 'Ahri',
aka: 'the Nine-Tailed Fox',
Role: 'Mage',
affiliation: 'Ionia',
Price: '790RP',
};
객체는 중괄호(Curly bracket)으로 구성되며, 좌측을 키(key), 우측을 값(value)로 구분합니다.
이렇게 어떤 객체에 담긴 다양한 데이터들 중, 원하는 키의 밸류를 알고 싶을 때 그 값만 호출할 수 있습니다.
또한, 해당 키의 밸류를 변경하고 싶을 때, 객체 전체를 수정하는 것이 아닌 키 값만 변경할 수 있습니다.
Ahri.Price; // 아리의 가격은 790RP 입니다.
객체를 호출할 땐, 위처럼 객체의 이름에 .
을 찍는 dot notation
이 있고, Ahri['Price']
이처럼 대괄호로 구분하는 bracket notation
이 있습니다.
흔히 하는 실수가, bracket notation
을 사용할 때 키의 이름에 꼭 따옴표를 붙여야 한다는 것입니다. 따옴표를 붙이지 않을 경우, 변수로 취급되기 때문에 따로 변수를 지정하지 않았다면 꼭 따옴표를 붙여 사용해야 합니다.
키 값이 변수일 땐 반드시 bracket notaion
을 사용해야 합니다.
dot notation
과 bracket notation
으로 객체에 값을 추가, 수정, 삭제를 할 수 있습니다.
Ahri.voiceActor = '이용신'; // voiceActor 라는 key 추가, 그 key에 '이용신'이라는 value가 할당
Ahri['releaseDate'] = '2010-12-13'
Ahri.releaseDate = '2011-12-13' // 값을 수정할 수 있다.
delete Ahri.releaseDate; // key, value 삭제
배열과 객체의 차이점은 '순서'의 유무입니다.
배열은 대괄호 안에 존재하는 엘리먼트들의 순서 를 갖고 있으며,
객체는 중괄호 안에 존재하는 엘리먼트들의 의미 를 갖고 있습니다.
Javascript에서 number
,string
,boolean
과 같은 고정된 저장 공간을 차지하는 데이터를 모두 원시 타입 데이터(Primitive type)로 구분합니다.
원시 자료형 : 고정된 저장 공간을 차지하는 데이터 타입
원시 자료형 타입은 데이터가 하나의 정보를 담고있습니다. 하나의 정보만 담고있기 때문에, 고정된 저장 공간을 사용하는 것이 합당합니다. 원시 자료형 타입의 값 자체는 변경이 불가능하지만, 변수에 다른 데이터를 할당할 수 있습니다.
원시 자료형으로 구분되는 데이터는 다음과 같습니다.
string
number
boolean
undefined
null
bigint
...
Javascript에서 원시 자료형을 제외한 모든 것은 참조 자료형(Reference type)입니다.
고정된 저장 공간을 사용하는 것이 원시 자료형이라면, 고정된 저장 공간을 사용하지 않고 특별한 저장 공간을 사용하는 타입은 무엇일까요?
참조 자료형은 heap
이라는 특별한 저장소를 사용합니다.
let a = 1 // 변수 a에 1을 할당
위처럼 a라는 변수 이름을 가진 저장소에 1이라는 숫자를 저장소에 저장하는 것은 원시 자료형(숫자) 입니다.
그러나, 참조 자료형은 어떤 변수 이름을 가진 저장소에 값을 저장하는 것이 아니라, 주소를 저장합니다. 그 주소에 해당하는 값이 heap이라는 저장소에 들어있고, 값을 찾을 땐 저장소에 저장된 주소를 보고, heap에서 그 주소에 맞는 값을 찾아 반환하는 구조입니다.
참조 자료형은 Object
로 구분되는 모든 자료형에 해당합니다.
배열, 객체, 함수들이 참조 자료형에 해당됩니다.
참조 자료형의 공통점은, 타입별로 하나의 주제는 있지만, 서로 다르고 그 안에 여러개의 데이터를 갖고 있는 것이라 할 수 있습니다.
즉, 하나의 의미를 가지는 것이 아니라, 보관되는 데이터의 양이 유동적으로 바뀔 수 있습니다.
Javascript가 이렇게 원시, 참조로 자료형을 구분한 이유가 무엇일까요?
변수에 넣을 수 있는 데이터의 크기, 저장소의 크기가 제한되기 때문입니다.
기술이 진보하면서, 처리해야할 데이터의 양도 늘었고, 이 늘어난 데이터를 다루기 위해 구현된 것이 배열, 객체, 함수들입니다. 이 타입들은 데이터의 양이 유동적으로 변합니다.
즉, 저장소엔 데이터가 위치한 곳(메모리상의 주소)만 저장하고, 값을 불러올 땐 저장소에 저장된 주소를 따라가서, heap
이라는 특별한 데이터 저장소에서 찾는 방식으로 데이터를 처리하게 됩니다.
데이터는 특별한 저장소에 별도로 관리되고, 우리가 다루는 변수엔 주소만 저장됩니다. 이 변수를 사용할 땐 그 변수의 주소를 '참조'하여 실제 변수가 있는 장소에 어떤 데이터가 있는지 도착하고 나서야 비로소 '읽을' 수 있기 때문에, 참조 자료형(Reference type)으로 불리게 되었습니다.
간단히 원시 자료형과 참조 자료형의 차이를 구분하자면,
원시 자료형은 변수에 값이 할당될 때, 값 자체가 할당됨
참조 자료형은 변수에 값이 할당될 때, 보관함의 주소(reference)가 할당됨
변수엔 원시 값 혹은 주소만 지정할 수 있고, 주소는 크기가 변하는 특별한 데이터 저장소를 참조하게 되는 것입니다.
변수 영역(Scope) : 컴퓨터 프로그래밍에서 변수 영역은 변수가 유효성을 갖는 영역을 가리킨다. - 출처
Javascript에서 이야기하는 스코프는 변수의 유효 범위
로 정의할 수 있습니다.
Javascript에서의 스코프 역시, 무언가 제한된 범위를 잘 들여다보기 위해 사용되는 개념입니다.
스코프는 함수, 또는 중괄호(Curly bracket)에 의해 나뉘어집니다.
스코프를 다중으로 선언한다면,
바깥쪽 스코프에서 선언한 변수는 안쪽 스코프에서 사용 가능합니다.
반대의 경우, 사용할 수 없습니다.
가장 바깥쪽의 스코프는 전역 스코프(Global scope)라고 부르고, 블록으로 구분된 스코프는 지역 스코프(Local scope)로 부릅니다.
여기서, 지역 스코프와 전역 스코프에서 선언한 각각의 변수를, 지역 변수, 전역 변수라고 하며, 이 두 변수의 우선순위는 지역 변수가 더 높습니다.
예를 들면, 전역 변수에 a라는 변수를 선언하고, 지역 변수에 같은 a라는 이름을 가진 변수를 선언한다면, 그 지역 스코프에선 지역 변수에 선언된 a를 사용하게 됩니다.
동일한 변수 이름으로 바깥쪽 변수가 안쪽 변수에 의해 가려지는 현상을 쉐도잉(Variable Shadowing)이라 부릅니다.
지역 스코프는 블록 스코프, 함수 스코프로 구분됩니다.
블록 스코프는 중괄호(Curly bracket)를 기준으로 범위가 구분됩니다.
함수 스코프는 function
키워드가 존재하는 함수 선언식 및 함수 표현식입니다.
일반적으로, 스코프를 구분할 땐 블록단위로 구분해야 합니다. 블록 단위의 스코프가 더 예측 가능하고, 협업에서 혼란을 예방할 수 있습니다.
우리가 변수를 선언할 때, let
, const
, var
이렇게 세가지 키워드를 사용합니다.
여기서 const
는 변하지 않는 값, 즉 상수(constant)를 정의할 때 쓰는 키워드입니다. 이 키워드로 선언한 변수의 값은 재할당이 불가능합니다.
나머지 let
과 var
은 큰 차이가 있습니다.
let
으로 선언한 변수의 유효 범위는 블록입니다.
var
으로 선언한 변수의 유효 범위는 함수입니다. 블록 스코프를 무시합니다.
즉, 어떤 블록 내에서 var
키워드로 변수를 선언했다 하더라도, 다른 블록에서 그 변수를 재사용할 수 있습니다.
이 경우, 코드 작성에 있어서 혼란스러울 수 있고, 버그를 유발할 수 있습니다.
그렇기 때문에, const
로 변수를 선언할 때 이외에, 변수를 선언할 땐 let
키워드로 선언하는 것이 코드 작성에 있어서 안전합니다.
클로저의 정의를 찾아보면, ' 함수와 함수가 선언된 어휘적 환경의 조합 ' 이라고 확인할 수 있습니다. 잘 와닿지 않는 글입니다. 제가 이해한 바로 말씀드리자면,
클로저(Closure) : 외부함수의 변수에 접근할 수 있는 내부함수
클로저는 스코프를 이용해 변수의 접근 범위를 설정하는 것으로 사용할 수 있습니다.
일반적인 함수는 함수의 실행이 끝나면 함수 내부의 변수를 외부에서 사용 불가능하지만, 클로저를 사용하게 되면 외부 함수의 실행이 끝나도 외부 함수 내 변수가 메모리에 저장됩니다. 즉, 데이터를 스코프에 가둬 계속 사용할 수 있게 해줍니다.
' 클로저로 만들어진 함수는 변수가 보존되어 있다. ' 의 의미는, 새로운 이름의 변수를 여러개 만들어 그 안에 클로저 함수를 넣더라도, 클로저 함수 내 변수는 독립적으로 사용되어, 서로 영향을 주지 않습니다. 즉 함수의 재사용성을 극대화할 수 있습니다.
예를 들어, 입력한 값에 항상 5를 곱한 값을 반환하는 함수를 만들어 보겠습니다.
let multiply = function(x){
let result = function(y) {
return x*y;
}
return result;
}
multiply
라는 함수는 외부 함수이고, 그 안에 result
는 내부 함수입니다. 내부 함수의 x
는 외부 함수에 선언된 x
에 접근할 수 있습니다. 즉, result
는 클로저입니다.
이 클로저를 이용해 5를 곱한 값을 반환하는 함수는
let foo = multiply(5);
foo(6) // multiply(5)(6) -> multiply의 매개변수가 5, result의 매개변수 6, 즉 result = 30
foo(10) // 5 * 10
foo(15) // 5*15
위처럼 만들 수 있습니다.
만약, 항상 5를 곱하는 것이 아닌, 항상 10을 곱한 값을 반환하는 함수를 만들고 싶을 땐 어떻게 할까요?
새로 함수 코드를 짜야할까요? 그렇지 않습니다.
클로저를 사용한다면 보다 생산성있는 코드를 구성할 수 있습니다.
let bar = multiply(10);
bar(10) // 10 * 10
bar(2) // 10 * 2
이처럼, 클로저를 사용하면 변수가 보존되어 있어, 새로운 이름의 변수를 할당하더라도, 서로 영향을 주지 않습니다. 즉, 코드의 모듈화를 실현할 수 있습니다.
와이어프레임(Wireframe) : 페이지 회로도 또는 화면 청사진이라고도하는 웹 사이트 와이어 프레임은 웹 사이트의 골격 프레임 워크를 나타내는 시각적 가이드입니다. 와이어 프레임은 특정 목적을 가장 잘 달성하기 위해 요소를 배열하기 위해 만들어집니다. - 출처
웹 또는 앱을 개발할 때, 레이아웃의 뼈대를 그리는 단계를 와이어프레임이라 합니다.
이 레이아웃을 기반으로 HTML로 구조를 잡고, HTML 태그에 CSS를 적용해 시각화를 수행합니다.
이 와이어프레임은 직접 손으로 노트에 스케치하듯 그릴 수 있고, 파워포인트로 만들 수 있고, Figma를 통해 만드는 등 정해진 방법은 없습니다.
왕도는 없다!
CSS엔 여러가지 셀렉터가 있지만, 후손 셀렉터와 자식 셀렉터와의 차이를 잘 구분해야 합니다.
이름 그대로, 후손 셀렉터는 부모의 자식, 손자, 증손자,,, 등 모든 요소를 포함합니다.
반면, 자식 셀렉터는 부모의 자식, 단 하나의 셀렉터입니다.
<div class="container">
<header>
<h1>title</h1>
</header>
<ul>
<li>list</li>
<li>list</li>
</ul>
</div>
위의 예시로 보면, container
라는 클래스의 div
의 자식은 header
, ul
이 되겠습니다.
후손은 h1
,li
가 되겠습니다.
들여쓰기로 쉽게 확인할 수 있습니다. h1
의 부모는 header
이며, h1
은 div
에게 손자가 될 수 있겠죠.
만약 CSS로 li
의 배경색을 지정하고자 할 땐, 자식 선택자가 아닌 후손 선택자로 지정해줘야 합니다.
.container li{background-color : #000}
header
의 여백을 주고자할 땐, 자식 선택자를 지정해야 합니다.
.container>header {margin:50px}
이와 같이 후손 선택자와 자식 선택자의 차이는 ' '
공백과 >
화살표로 구분할 수 있습니다.
웹 페이지의 화면을 늘렸다 줄였다 할 때마다 블록들의 구성이 페이지의 사이즈에 맞게 자리잡는, 반응형 웹을 만들기 위해 CSS의 flex 속성이 필요합니다.
<ul class="container">
<li>box 1</li>
<li>box 2</li>
<li>box 3</li>
</ul>
부모 요소에 display:flex
를 선언하면 부모 요소 내 모든 item들은 flex item이 되어 부모 요소의 크기와 위치에 따라 자신의 위치를 변경할 수 있습니다.
.container { display:flex;}
디폴트 정렬 방향은 가로 방향입니다. 정렬 방향을 세로로 변경하려면,
.container {
display:flex;
flex-direction:column;
}
flex-direction
속성을 추가합니다.
그리고, 요소들의 정렬, 즉 li
들을 가운데 정렬할 지, 박스의 맨 위로 보낼지, 간격을 동일하게 배치할 것인지 등을 정렬할 수 있습니다.
.container {
display: flex;
flex-direction: column;
justify-content: center; // flex-direction 방향에 따라 정렬(column이면 세로축 기준 정렬)
align-items: stretch; // flex-direction 방향의 반대쪽(column이면 가로축 기준 정렬)
}
이 외에, 자식 요소에 flex
속성을 할당해 가로 세로 크기 비율을 조절할 수 있습니다.
더 공부해서 flex 및 grid 속성을 주제로 포스팅해보도록 하겠습니다.
flex
박스 및 레이아웃과 관련하여 유용한 동영상 이 있어 첨부합니다!