원시타입과 객체타입에 대해서 제대로 알고 넘어가기 위해 오늘은 원시타입과 객체타입, 그리고 더 나아가 얕은복사, 깊은복사에 대해서도 알아보자.

원시타입과 객체타입


원시타입

1. 원시타입의 값

원시타입의 값은 변경 불가능한 값이다. 읽기전용이다.

1
2
3
4
5
var str = "hello";

str[0] = "H";

console.log(str); // hello

변수 str의 첫번째 문자열을 인덱스로 접근하여 직접 바꾸려했지만 변경불가능하여 바꿀 수 없다.

2. 원시타입의 메모리 공간

원시타입은 변수 할당 시 메모리 공간에 실제 값을 저장한다.

변수와 메모리에 대해 자세히 언급하면 사실 변수라는 식별자가 값을 저장하는 게 아닌 값이 저장된 메모리 공간에 대한 메모리 주소를 저장하고 있다.

즉, 메모리 공간에는 값이 저장되어 있고 변수라는 식별자는 메모리 공간의 메모리 주소를 저장한다.

3. 원시타입 값의 전달

원시값을 갖는 변수를 다른 변수에 할당하면 원시값이 복사되어 전달된다.

1
2
3
4
5
6
7
8
var str = "hello";

var greeting = str;

greeting = "hi";

console.log(str); // hello
console.log(greeting); // hi

사실 값이 복사되어 전달되는 것이 아니고 동일한 값을 새로운 메모리 저장공간에 저장한 뒤 해당 메모리 공간의 메모리 주소를 copy라는 변수에 할당하는 것이다.


객체타입

1. 객체타입의 값

객체타입의 값은 변경가능한 값이다.

1
2
3
4
5
6
7
8
9
10
11
var obj = {
name: "yiju",
age: 28,
smoke() {
console.log("no-smoking");
},
};

obj.name = "jangoon";

console.log(obj); // {name: 'jangoon', age: 28, smoke: ƒ}

2. 객체타입의 메모리 공간

객체타입은 변수 할당 시 메모리 공간에 참조값(주소값)이 저장된다.

원시타입에서는 메모리 공간에 값이 저장되고 변수 식별자에 해당 메모리 공간을 가리키는 주소가 저장되어 있다.

하지만, 객체타입에서는 메모리 공간에 다른 메모리 공간을 가리키는 메모리 주소가 담겨있다. 다시말해서, 객체타입의 메모리는 원시타입의 메모리보다 과정이 한번 더 일어나게 되는 것이다.

3. 객체타입 값의 전달

객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조값(주소값)이 복사되어 전달된다.

1
2
3
4
5
6
7
var person = {
name: "Lee",
};

var copy = person;

console.log(person === copy); // true

변수 person과 copy는 {name:’Lee’} 객체 프로퍼티들의 주소가 담겨있는 메모리 공간의 메모리 주소를 저장한다. 그러므로 같은 참조값(주소값)을 비교하고 있기 때문에 일치 비교 연산자가 true가 나왔다.


객체타입의 얕은복사

객체를 spread 문법을 사용하여 얕은복사를 해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
let person = {
name: "yiju",
fruit: {
1: "peach",
2: "strawberry",
},
};

let someone = { ...person };

// 두 객체가 같은지 비교
console.log(person === someone); // false

// 객체의 프로퍼티 비교
console.log(person.name === someone.name); // true
console.log(person.fruit === someone.fruit); // true

// 1. 원시타입의 값을 변경했을 경우
person.name = "minseok";

console.log(person); // {name: 'minseok', fruit: {…}}
console.log(someone); // {name: 'yiju', fruit: {…}}

// 2. 객체타입의 값을 변경했을 경우
person.fruit["1"] = "watermelon";

console.log(person); // fruit: {1: 'watermelon', 2: 'strawberry'}
console.log(someone); // fruit: {1: 'watermelon', 2: 'strawberry'}

변수 person의 원시타입의 값을 수정하였을 때, 서로의 원시타입의 값은 공유하지 않는다. 하지만 객체타입의 값을 바꾼 경우 서로의 객체타입의 값을 공유하는 모습을 볼 수 있다.

왜 그럴까? 앞서 언급한 내용으로 깊게 파헤쳐보자.

  1. person, someone은 일치하지 않으니 서로 다른 주소값을 갖는다. 각각의 주소는 javascript {name:'yiju',fruit:{1:'peach',2:'strawberry'}} 객체 프로퍼티들의 주소를 담고있는 메모리 공간을 가리킨다.

예를 들면 name 식별자가 가리키는 주소, fruit 식별자가 가리키는 주소 이런식으로 프로퍼티의 주소들을 담고 있다.

여기서 name 식별자는 원시타입의 값을 가리키는 메모리 주소를 저장한다. javascript person.name = 'minseok' 을 실행하면 person.name과 someone.name이 서로 다른 주소값을 갖게된다.

  1. fruit의 식별자 주소는 javascript {1:'peach',2:'strawberry'} 프로퍼티들의 주소를 담고있는 메모리 공간을 가리킨다. person.fruit와 someone.fruit가 서로 같다(메모리 주소가 같다). 즉, fruit 프로퍼티들의 주소가 담긴 메모리 공간을 가리키는 메모리 주소가 같다.

그리하여 javascript fruit['1'] = 'watermelon' 로 fruit 프로퍼티인 1을 수정하면 식별자인 1이 가리키는 메모리 주소가 바뀌게 되고 person과 someone 식별자가 식별자 1을 포함하는 프로퍼티들의 주소를 담은 메모리 공간을 가리키는 메모리 주소는 변하지 않으므로 서로 공유하게 된다.


객체타입의 깊은복사

객체타입의 깊은복사는 JSON.parse, JSON.stringify 메서드를 사용하여 구현할 수도 있고 lodash 라는 라이브러리를 사용한다.

하지만 JSON.stringify 방식으로는 함수(메서드)를 복사할 수 없기 때문에 재귀를 사용하거나 실무에선 라이브러리를 사용한다.

lodash 방법

1
2
3
4
5
6
7
8
const o = { x: { y: 1 } };

const _ = require("lodash");
const c2 = _.cloneDeep(o);

// 객체비교
console.log(c2 === o); // false
console.log(c2.x === o.x); // false

JSON 방법

1
2
3
4
5
6
7
8
9
10
const a = {
b: 1,
c: {
d: 2,
},
};
let b = JSON.parse(JSON.stringify(a));
b.c.d = 4;
console.log(a); // { b: 1, c: { d: 2 } }
console.log(b); // { b: 1, c: { d: 4 } }

소감

자바스크립트 DeepDive 책을 읽으면서 팀원들과 각자 공부한 내용을 말로 풀어서 설명하다보니 내가 무엇이 부족한지 알 수 있었고 내가 모르거나 제대로 알지 못하던 부분을 확실히 알고 이렇게 TIL까지 작성하면서 정리하니 기억에 오래 남을 것 같다.

댓글 공유

데이터 타입

카테고리 JavaScript

Javascript Data type

자바스크립트는 크게 2가지의 데이터 타입으로 나뉜다.

  1. 원시타입 (Primitive Data Type)

  2. 객체타입 (Object Type, Reference Type)

이 중에서도 원시타입에는 6가지의 타입이 존재하고 그 외의 것들은 모두 객체타입이다. 그래서 자바스크립트를 객체 지향 프로그래밍 언어라고 부르나 보다.(6가지 빼곤 모두 객체니깐…)

오늘은 데이터 타입에 대해 공부해보도록 하자.


Primitive Data Type (원시타입)

원시타입의 종류는 6가지가 있다.

  • number (숫자형)
  • string (문자형)
  • undefined
  • null
  • boolean (불리언형)
  • symbol

원시 타입의 값은 변경 불가능한 값이며, pass-by-value(값에 의한 전달)이다. 이에 대한 자세한 내용은 다음 TIL에서 더 알아보고 각 자료형에 대해 알아보자.


number

Javascript에서는 숫자형을 모두 실수로 처리한다. 추가로 아래와 같은 자료도 숫자형이다.

  • Infinity : 양의 무한대
  • -Infinity : 음의 무한대
  • NaN : 산술 연산 불가(Not A Number)

NaN은 자기 자신과 일치하지 않는 유일한 값이다. 그러므로 어떤 값이 NaN인지 판단하기 위해서는 Number.isNaN() 빌트인 함수를 사용하거나 Object.is() 메서드를 사용하여야 한다.

1
2
3
4
5
NaN === NaN; // false

Number.isNaN(NaN); // true

Object.is(NaN, NaN); // true

string

C언어와 다르게 Javascript의 문자열은 원시타입으로 변경 불가능하다.

1
2
var str = "Hello";
str = "World";

위 코드에서 str 변수에 ‘World’라는 문자열로 데이터를 수정하는 것이 아니다.
임의의 메모리 주소를 갖는 메모리 공간에 ‘World’라는 문자열을 저장하고 변수의 식별자인 str이 새로운 메모리 주소를 가리켜 변수를 재할당하는 것이다.

boolean

참, 거짓을 나타내는 자료형이다. 암묵적 불리언 형변환이 발생하면 해당값들을 false로 바꿔주는 falsy 값들이 있다.

falsy

  • “” (빈문자열)
  • undefined
  • null
  • 0, -0
  • NaN

undefined

변수의 선언 단계는 사실 선언단계와 초기화 단계 두 단계로 나눠서 볼 수 있는데, 초기화 단계에서 컴퓨터가 변수가 할당되기 이전에 undefined값으로 변수의 값을 초기화해준다.

때문에 이는 개발자의 의도가 담긴 것이 아니다.

null

변수의 값이 없다는 것에 개발자의 의도를 담고 싶다면 null을 사용한다. 자바스크립트는 대소문자를 구별하기 때문에 null, Null, NULL 모두 다른 값이다.

함수가 유효한 값을 반환할 수 없는 경우 명시적을 null을 반환하기도 한다.

null 값의 type을 확인하기 위해서는 typeof 연산자를 사용하는 것 대신 일치 연산자(===)를 사용한다.

1
2
3
var foo = null;
typeof null; // 'object'
foo === null; // true

symbol

심볼은 이름이 충돌한 위험이 없는 유일무이한 원시타입의 값이다. 주로 객체의 유일한 프로퍼티 키를 만들기 위해 사용한다.

1
2
3
4
5
6
var key = Symbol("key");
typeof key; // 'symbol'

var obj = {};

obj[key] = "value"; // 이름이 충돌할 위험이 없는 유일무이한 값인 심볼을 프로퍼티 키로 사용

Object Type, Reference Type (객체타입)

객체란, 데이터와 그 데이터에 관련된 동작(절차, 방법, 기능 등)을 모두 포함할 수 있는 개념적 존재이다.

다시말해 데이터를 의미하는 프로퍼티와 동작을 의미하는 메소드를 포함할 수 있는 독립적 주체이다.

원시타입을 제외한 나머지 값(배열, 함수, 정규표현식 등)이 모두 객체이다.

객체는 pass-by-reference (참조에 의한 전달)이다. 이 부분에 대해서는 후에 객체에 대해서 TIL 작성시 다뤄보자


소감

모던 자바스크립트 Deep Dive 책을 읽으면서 그전에 포이마 웹을 통해 공부했을 때 놓쳤던 부분까지 꼼꼼하게 이해하고 넘어갈 수 있어서 재밌는 시간이었다.

매일 매일 조금씩 읽은 것들에 대해 하나의 주제를 잡고 정리해보는 습관을 가져봐야겠다.

댓글 공유

opacity

요소의 투명도를 설정하는 속성이다.

0 ~ 1.0 사이의 값을 가질 수 있으며 기본값은 1이다.

1
2
3
img {
opacity: 0.5;
}

exam

특징

내부의 자식 요소들에게도 상속이 된다. 그러므로 내부의 텍스트가 있다면 가독성이 떨어질 수 있으므로 조심해야한다.

또한, RGBA를 사용하여 투명도를 설정할 수 있다.

exam2

1
2
3
div {
background: rgba(76, 175, 80, 0.3); /* Green background with 30% opacity */
}

댓글 공유

문제

RGB거리에는 집이 N개 있다. 거리는 선분으로 나타낼 수 있고, 1번 집부터 N번 집이 순서대로 있다.

집은 빨강, 초록, 파랑 중 하나의 색으로 칠해야 한다. 각각의 집을 빨강, 초록, 파랑으로 칠하는 비용이 주어졌을 때, 아래 규칙을 만족하면서 모든 집을 칠하는 비용의 최솟값을 구해보자.

1번 집의 색은 2번, N번 집의 색과 같지 않아야 한다.
N번 집의 색은 N-1번, 1번 집의 색과 같지 않아야 한다.
i(2 ≤ i ≤ N-1)번 집의 색은 i-1, i+1번 집의 색과 같지 않아야 한다.

입력

첫째 줄에 집의 수 N(2 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 각 집을 빨강, 초록, 파랑으로 칠하는 비용이 1번 집부터 한 줄에 하나씩 주어진다. 집을 칠하는 비용은 1,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 모든 집을 칠하는 비용의 최솟값을 출력한다.

예제 입력 1

1
2
3
4
3
26 40 83
49 60 57
13 89 99

예제 출력 1

1
110

예제 입력 2

1
2
3
4
3
1 100 100
100 1 100
100 100 1

예제 출력 2

1
3

예제 입력 3

1
2
3
4
3
1 100 100
100 100 100
1 100 100

예제 출력 3

1
201

예제 입력 4

1
2
3
4
5
6
7
6
30 19 5
64 77 64
15 19 97
4 71 57
90 86 84
93 32 91

예제 출력 4

1
208

예제 입력 5

1
2
3
4
5
6
7
8
9
8
71 39 44
32 83 55
51 37 63
89 29 100
83 58 11
65 13 15
47 25 29
60 66 19

예제 출력 5

1
253

내 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const [N, ...input] = require("fs")
.readFileSync("/dev/stdin")
.toString()
.trim()
.split("\n");
const n = +N;
const costs = input.map((elem) => elem.split(" ").map(Number));

const MAX = 100001;
let answer = MAX;

let dp = Array.from({ length: n + 1 }, () => [0, 0, 0]);

for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === j) dp[0][j] = costs[0][j];
else dp[0][j] = MAX;
}

for (let j = 1; j < n; j++) {
dp[j][0] = Math.min(dp[j - 1][1], dp[j - 1][2]) + costs[j][0];
dp[j][1] = Math.min(dp[j - 1][0], dp[j - 1][2]) + costs[j][1];
dp[j][2] = Math.min(dp[j - 1][0], dp[j - 1][1]) + costs[j][2];
}

for (let j = 0; j < 3; j++) {
if (i === j) continue;
answer = Math.min(answer, dp[n - 1][j]);
}
}

console.log(answer);

해설

RGB 거리 문제와는 다르게 첫번째 선택한 색상을 마지막에서도 선택하면 안되므로 첫번째 선택한 색상을 기억해두도록 접근하자.

예를 들어 첫번째 색상을 R로 선택했다고 하면 나머지 G,B 색상은 선택하지 못하도록 최대값으로 설정해준다.

이후에 다음 집에서는 R을 제외한 나머지 2가지 색상 중 작은 값을 선택하고 해당 집의 색상 비용을 더해줘서 DP 배열을 완성 시켜나간다.

그리하여 DP 배열이 완성되고 나면 DP 배열의 최종 인덱스에 위치한 배열 중 가장 작은 값을 answer 변수에 저장해둔다.

이렇게 첫번째 집을 R로 설정한 경우, G로 설정한 경우, B로 설정한 경우 총 3번을 진행하고 나서 최종적으로 answer 값을 출력해주면 된다.

댓글 공유

자료구조

자료구조는 효율적으로 데이터를 관리하고 수정, 삭제, 탐색, 저장할 수 있는 데이터 집합이다.

어떤 비즈니스 로직을 처리할 때 가장 효과적인 자료구조를 찾아서 쓰는 것이 중요하기 때문에 자료구조를 명확하게 알아야한다.

자료구조를 설명하기 위해 C++은 이해하기 쉬운 언어이기 때문에 자료구조 공부는 C++로 할 것이다.

1
2
3
4
5
6
7
8
#include <bits/stdc++.h> // 1
using namespace std; // 2
string a; // 3
int main(){ // 4
cin >> a; // 5
cout << a << '\n'; // 6
return 0; // 7
}
  1. 헤더 파일. import할 때 사용한다. bits/stdc++.h 는 모든 표준 라이브러리를 의미한다.

  2. std라는 네임스페이스 사용하겠다. cin, cout 사용할 때 원래는 std::cin처럼 네임스페이스 달아서 사용해야하는데 이를 기본으로 설정한다는 뜻이다.

  3. 문자열 선언. <타입> <변수명> 이런식으로 선언한다. 예를들어 string a = 'Wix' 이렇게 선언했다면, a는 lvalue, Wix는 rvalue라고 한다. lvalue는 추후 다시 사용될 수 있는 변수이고 rvalue는 한 번 쓰고 다시 사용되지 않는 변수이다.

  4. 입력. 대표적으로 cin, scanf가 있다.

  5. 출력. 대표적으로 cout, printf가 있다.

  6. return 0은 프로세스가 정상적으로 마무리 됨을 뜻한다.

int는 4바이트 정수를 사용할 때 사용되는 타입이다. 표현범위는 -2,147,483,648 ~ 2,147,483,647 입니다.

시간복잡도

시간복잡도란, 입력 크기에 대해 어떤 알고리즘이 실행되는데 걸리는 시간이다. 직접적인 시간을 측정하는 것이 아닌 주요 로직의 반복횟수를 중점으로 측정된다.

왜냐하면 직접적인 시간은 여러가지 요인에 따라 변경될 수 있기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
for(int i = 0; i < 10; i++){
for(int j =0; j < n; j++){
for(int k = 0; k < n; k++){
if(true) cout << k << '\n';
}
}
}

for(int i = 0; i < n; i++){
if(true) cout << i << '\n';
}

위 코드에서 시간 복잡도는 10n^2+n이다.

빅오표기법(Big - O)

빅오표기법은 복잡도에 영향을 가장 많이 끼치는 항의 상수인자를 제거하고 나머지 항을 없애서 복잡도를 표기하는 표기법이다.

앞선 예시를 빅오표기법으로 나타내면 O(n^2)이다.

여기서 영향을 가장 많이 끼친다는 의미는 입력 크기가 커질수록 증가속도가 가장 큰 것을 의미한다.

예를 들어 n^2은 1,4,9,16,25 이런식으로 증가하는데, n은 1,2,3,4,5 이런식을로 증가하기 때문에 영향이 가장 큰 n^2 항의 상수 인자를 제거하여 빅오표기법으로 나타낸 것이다.

빅오표기법 차트는 외워두자!

n! > 2^n > n^2 > nlogn > n > logn > 1 순입니다.

Big-O chart

상수시간 시간복잡도 O(1)

상수시간 시간 복잡도는 입력 크기와 상관없이 일정한 시간복잡도를 가지는 것을 말한다.

  1. 입력과 출력
1
cin, cout, scanf, printf
  1. 곱하기
1
a[2] *= 2;
  1. 간단한 비교 if 문
1
2
3
if (a[0] == 2) {
// 로직
}
  1. 배열 인덱스 참조
1
2
int a[3] = {1,2,3};
int b = a[2]

댓글 공유

node.js

node.js란 비동기적 이벤트 주도 방식, 논블로킹 I/O 모델을 사용하는 구글의 V8 엔진을 장착한 자바스크립트 런타임이다.

런타임이란, 프로그램이 실행될 때 그 프로그램이 머무는 공간을 의미한다. 때문에 브라우저는 자바스크립트 런타임이라고도 한다.

이와 동일하게 node.js 또한 자바스크립트 런타임이므로 자바스크립트로 만든 프로그램을 실행할 수 있다.

이번에는 node.js로 서버를 만들어서 API를 구현해보는 예시를 해보자.

실습

  1. nodejs를 설치한다.

  2. json 파일과 서버파일을 생성한다.

1
2
3
4
5
// a.json
{
"name": "Wix",
"tall": "178"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// b.js
import express from "express";
import fs from "fs";

const app = express();
const port = 3000;
app.get("/", (req, res) => {
const f = JSON.parse(fs.readFileSync("a.json", { encoding: "utf-8" }));
const data = {
name: f.name,
tall: f.tall,
};
res.send(data);
});
app.listen(port, () => {
console.log(`http://127.0.0.1:${port}`);
});
  1. express 모듈 설치
1
npm install express

express는 node.js에서 동작하는 웹 프레임워크이다. 라우팅, 미들웨어, 정적자원서버 설정이 쉬운 장점이 있다.

  1. 터미널로 node 프로그램을 실행해본다.
1
node b.js

get() 메서드에 설정한 경로 /로 get 요청이 보내졌고 서버에서는 name, tall이 담긴 자바스크립트 객체 데이터가 응답으로 전송되었다.

앞서 API의 특징을 설명할 때, 파일 내부가 변경되더라도 API를 변경되지 않도록 설계할 수 있다고 하였다.

a.json 파일 내용을 바꾸더라도 API를 바꿔줄 필요가 없다.

댓글 공유

API

API란, 둘 이상의 컴퓨터 프로그램이 서로 통신하는 방법이자 컴퓨터 사이에 있는 중계 계층을 의미한다.

API는 어떻게 통신할 것인지, 어떤 데이터를 주고 받을 것인지 등에 대한 방법(HTTP, HTTPS 프로토콜 중 어떤 거 사용할지, GET인지 POST인지 등)이 정의된 중계 계층이다.

API 특징

  • 제공자는 본인이 원하는 부분만 드러낼 수 있다.
  • 사용자는 해당 서비스가 어떻게 구현되는지 알 필요없이 필요한 정보만 받을 수 있다.
  • OPEN API의 경우 애플리케이션 개발 과정을 단순화 시켜주어 개발 시간과 비용을 절약할 수 있다.
  • API를 만들고 나서 내부 프로세스가 수정될 때마다 매번 API를 수정해줄 필요가 없다.
  • 제공자는 데이터를 한곳에 모을 수 있다. 예를 들어 방문자 수, 클릭수 등을 집계하고 싶을 때 해당 API를 만들고 이벤트가 발생할 때 해당 API를 호출하여 데이터를 한 곳에 모을 수 있다.
  • 제공자의 경우 API를 이용해 제 3자가 만든 앱을 통해 데이터를 수집하여 해당 서비스 확장할 수도 있고 홍보에도 도움이 된다.

API 종류

  • private: 내부적으로 사용. 주고 해쉬키를 기반으로 서버와 서버간 통신에 사용된다.
  • public: 모든 사람이 사용. 많은 트래픽 방지하기 위해 하루 요청 수 제한.

댓글 공유

JSON

JavaScript 객체 문법으로 구조화된 데이터를 표현하기 위한 표준 포맷이다.

모든 서비스와 애플리케이션은 데이터를 기반으로 그것을 보여주거나 뒤에서 다루면서 데이터를 많이 사용하게된다.

세상의 모든 정형화된 데이터만 있다면 편리하겠지만, 그렇지 않은 복잡한 데이터도 많다.

예를 들어, 아래와 같은 내용을 데이터로 표현하려면 복잡하다.

Wix

  • 나이: 29
  • 좋아하는 것: 자전거타기(로드), 노래부르기(발라드)

이런 데이터를 컴퓨터도, 사람도 이해하기 쉽게 표현한 것이 바로 JSON이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"Wix": {
"age": 29,
"Likes": [
{
"name": "Riding Bike",
"type": "Road"
},
{
"name": "Sing a song",
"type": "Ballad"
}
]
}
}

특징

  • key:value 형태
  • {} 중괄호로 감싼다.
  • key, value에 “”만 사용가능하다.
  • 자바스크립트와 호환이 좋다.
  • 각 객체가 다른 타입이어도 괜찮다.
  • value에 메서드와 undefined가 올 수 없다. 이외의 수, 문자열, 불리언, 배열, 객체, null 값은 올 수 있다.
  • 프로그래밍 언어나 플랫폼에 독립적이기 때문에 서로 다른 시스템 간의 데이터 교환시 유용하다. ex) API, config 파일

XML

JSON과 비교하면 중괄호 대신 열린 태그와 닫힌 태그 구조로 이루어진 데이터 포맷이 XML이다.

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?> <!-- 프롤로그 -->
<Wix>
<age>29</age>
<Likes>
<Like>
<name>Riding Bike</name> <type>Road</type>
</Like>
<Like>
<name>Sing a song</name> <type>Ballad</type>
</Like>
</Likes>
</Wix>

특징

  • 최상위 태그는 하나만 사용해야한다.
  • JSON에 비해 무겁다. JSON에 비해 닫힌 태그까지 들어가서 2번씩 들어간다.

sitemap.xml

XML의 대표적인 예시로는 SEO에 사용되는 sitemap.xml이 있다.

사이트가 매우 크거나 서로 링크가 종속적으로 연결되어 있지 않다면 크롤러가 일부 페이지를 누락하는 일이 발생하는데 이를 방지하기 위해 sitemap.xml를 사용한다.

댓글 공유

pseudo-class

요소의 특정한 상태를 정의하기 위해 사용하는 CSS 속성이다.

  • 사용자가 마우스를 올렸을 때, 요소를 스타일링 하기
  • 방문한 링크와 미방문 링크 스타일 구분하기
  • focus가 잡혔을 때, 요소 스타일 주기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* unvisited link */
a:link {
color: #ff0000;
}

/* visited link */
a:visited {
color: #00ff00;
}

/* mouse over link */
a:hover {
color: #ff00ff;
}

/* selected link */
a:active {
color: #0000ff;
}

a:hover는 a:link, a:visited 속성 이후에 선언되어야한다. 또한 a:active 속성은 a:hover 속성 이후에 선언되어야 한다.

:first-child pseudo-class

요소의 첫번째 자식을 선택하는 선택자이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
<style>
p:first-child {
color: blue;
}
</style>
</head>
<body>
<p>This is some text.</p>
<p>This is some text.</p>

<div>
<p>This is some text.</p>
<p>This is some text.</p>
</div>
<section>
<p>this is first element</p>
<p>this is second element</p>
</section>
</body>
</html>

first-child

이 외에도 많은 pseudo-class들이 있으니 필요하면 찾아서 사용하자.

pseudo-element

요소의 특정 부분을 스타일링 하기 위해 사용하는 CSS 속성이다.

  • 요소의 첫번째 줄이나 첫문자를 스타일링 하기
  • 요소 content의 이전이나 이후에 content를 삽입하기

::first-line

첫번째 줄의 특별한 스타일링을 추가하기 위해 사용한다.

  • block level 요소에만 설정 가능하다.
1
2
3
4
p::first-line {
color: #ff0000;
font-variant: small-caps;
}

::first-letter

첫번째 문자를 스타일링 하는데 사용된다.

  • block level 요소에만 설정 가능하다.
1
2
3
4
p::first-letter {
color: #ff0000;
font-size: xx-large;
}

::before

요소의 content 이전에 어떤 content를 삽입하기 위해 사용한다.

1
2
3
h1::before {
content: url(smiley.gif);
}

before

::after

요소의 content 이후에 어떤 content를 삽입하기 위해 사용한다.

1
2
3
h1::after {
content: url(smiley.gif);
}

::selection

사용자에 의해 선택된 부분을 스타일링한다. 아래는 드래그하여 텍스트를 선택하였을 때의 상황이다.

1
2
3
4
::selection {
color: red;
background: yellow;
}

selection

댓글 공유

loco9939

author.bio


author.job