※ 요약
std::vector의 멤버 함수인 emplace_back은 C++11부터 추가된 멤버 함수로써 push_back과 같이 vector의 요소 끝에 원소를 추가하는 함수이다. 두 함수의 가장 큰 차이점은, push_back과 같은 삽입 함수들은 삽입할 객체를 받지만 emplace_back과 같은 생성 삽입 함수는 삽입할 객체의 생성자를 위한 인자들을 받아 std::vector 내에서 직접 객체를 생성하여 삽입하므로 임시 객체의 생성과 파괴, 복사(혹은 move)를 하지 않아도 되어 성능상 더 유리하다는 것이다.
필자가 전에 작성한 push_back도 꼭 읽어보길 바란다.

※ 함수 원형

template< class... Args >

void emplace_back( Args&&... args );


emplace의 함수 원형은 하나다. push_back과 다르게 가변인자 템플릿 문법을 이용하여 가변인자를 받는다.


※ 예제

설명을 위해 아래와 같이 임시로 예제를 작성해봤다.


먼저 push_back으로 삽입을 했을때 결과이다. push_back에 삽입하기 위해 객체를 만들어 전달했고 내부적으로 또 임시객체를 만들어 아래와 같이 호출이 많아 성능상 불리하다.


emplace_back으로 삽입할 경우, 생성에 필요한 인자를 받아 내부에서 생성 삽입하므로 아래와 같이 생성자, 소멸자를 한 번씩만 호출하여 성능상 유리하다

.




※ 실제 사용예
필자가 전에 push_back으로 작성했던 코드이다. 이 코드는 CStationObj 임시 객체를 생성하고 그것을 push_back에 전달하는 걸 알 수 있으며 성능을 따져봤을때 비효율적이다.(내부적으로 CStationObj의 임시 객체가 생성되고 생성자와 소멸자도 호출되기 때문)


emplace_back은 함수 원형에서 본 거와 같이 가변 인자를 받을 수 있어서 아래와 같이 인자를 넣을 수 있으며, 받은 인자를 std::vector안에서 직접 CStationObj를 생성하므로 push_back보다 성능상 낫다.


※ 참고 사항

- push_back으로 하여도 컴파일러 내부적으로 최적화 하기 때문에 emplace_back으로 하는 것과 별차이가 없을 수 있다. 고로 개인 프로젝트가 아니라면 호환성이 더 좋은 push_back 사용이 더 나을 수도 있다.

- push_back함수로 할 수 있는 모든 것을 emplace_back으로 할 수 있다.

- push_back함수보다 emplace_back 함수가 대체로 효율적이다.(무조건적인건 아님 반대로 push_back이 더 효율적일 때도 있음)



'STL - Containers > vector' 카테고리의 다른 글

[C++ STL] std::vector - push_back  (0) 2016.02.19
[C++ STL] std::vector 주요 멤버 함수 목록  (0) 2015.11.23
[C++ STL] std::vector 개요  (3) 2015.11.10

※ 요약

std::vector의 멤버 함수인 push_back에 대한 내용이다. 멤버 함수 push_back은 vector의 끝에 요소를 추가할때 사용하는 함수며, 이번 포스팅에서는 C++03과 C++11에서의 사용방법에 대해 간단히 알아보도록 하겠다. 참고로 아래 내용은 vector의 특성을 알고 있다고 전제하고 진행하니 vector의 특성을 잘 모르면 이 게시물을 참고하기 바란다. 또 push_back과 같은 기능을 하지만 성능상 더 유리한 emplace_back에 대한 내용도 정리한게 있으니 꼭 읽어보기 바란다.

※ 함수 원형

void push_back( const T& value );
void push_back( T&& value );        //C++11

push_back의 함수 원형은 C++03때까지 하나였다가 C++11에 추가된 Move Semantics(R-Value) 개념 때문에 하나가 더 추가되서 2개다. 첫 번째는 기존처럼 값 복사를 통해 요소를 추가하고, 두 번째는 (임시)객체의 복사가 아닌 이동을 통해 요소를 추가하므로 불필요한 복사 과정을 없애 오버헤드를 줄였다. Move Semantics나 R-Value에 대해 더 알고 싶으면 이 게시물에 있는 "02. Rvalue Reference and constexpr.pdf"를 보기 바란다.

※ C++03 기본 자료형 예제

아래는 push_back을 이용해 요소를 추가하는 간단한 예제다.


아래 이미지를 보면 vecInt와 vecDouble, vecInt1에 각각 5와 6, 9, 13, 5.0, 6.0이 잘 추가된 것을 확인할 수 있다.


※ C++11 기본 자료형 예제

C++11에서는 initializer_list라는 클래스 템플릿이라는 걸 제공해주는데, 아래와 같이 컨테이너를 선언과 동시에 편하게 초기화할 수 있다. 또 달라진 점으로는 push_back(4)인데, 리터럴 상수인 4는 move semantics를 통해 T&& value를 인자로 받는 함수가 호출된다. 이전 버전의 C++이었다면 push_back( const T& value )가 호출 되었을 것이다.


아래와 같이 값이 잘 추가되었다.


※ 사용자 정의형 예제

아래 예제는 사용자 정의형(구조체나 클래스)에 대한 예제다. 위에 있는 예제들처럼 push_back에 대한 예제이며 기본 데이터형이 아닌 사용자 정의형 데이터를 추가한다는 것만 빼면 위의 예제들과 다를게 없으므로 따로 설명은 하지 않겠다.


아래처럼 값이 잘 들어갔다.



※ 예제

위의 예제들은 어디까지나 설명을 위해 급조한 예제들이고, 아래 소스는 실제 사용예이다. 아래 소스에 대해 간단히 설명하자면 select 쿼리를 날리고 조회된 데이터 행의 개수에 따라 vector의 메모리 공간을 reserve 함수를 통해 미리 예약하고 데이터를 push_back하는 예제이다. 멤버함수 reserve에 대해서는 나중에 알아보도록 하겠다.



'STL - Containers > vector' 카테고리의 다른 글

[C++ STL] std::vector - emplace_back  (3) 2016.04.15
[C++ STL] std::vector 주요 멤버 함수 목록  (0) 2015.11.23
[C++ STL] std::vector 개요  (3) 2015.11.10

 

※ 요약
std::forward_list의 주요 함수 목록이다.
std::forward_list의 경우는 C++11부터 추가된 컨테이너이고, 각 멤버들의 사용법은 다음 게시물부터 올리도록 하겠다.

- C++03

- C++11

 분 류

 멤버 함수

 설 명

Iterators

begin

 첫 번째 원소를 가리키는 반복자를 리턴한다.

cbegin

 첫 번째 원소를 가리키는 상수 반복자를 리턴한다.

end

 마지막 원소를 가리키는 반복자를 리턴한다.

cend

 마지막 원소를 가리키는 상수 반복자를 리턴한다.

rbegin

 제공 안 함

crbegin

 제공 안 함

rend

 제공 안 함

crend

 제공 안 함

Element access

at

 제공 안 함

operator[]

 제공 안 함

front

 첫 번째 원소의 참조를 리턴한다.

back

 제공 안 함

Capacity

empty

 원소 존재 유무를 체크한다. 아무것도 없으면 true, 있으면 false를 리턴한다.

size

 제공 안 함

max_size

 담을 수 있는 원소의 최대 개수를 리턴한다.

resize

 list의 크기를 변경하고 default 값이나 임의 값으로 초기화한다.

capacity

 제공 안 함

reserve

 제공 안 함

shrink_to_fit

 제공 안 함

Modifiers

clear

 list의 모든 원소를 제거한다.

assign

 기존 원소들은 모두 제거 후, 임의 값으로 n개의 원소를 할당한다.

insert_after

 지정된 위치에 뒤에 값을 삽입한다.

emplace_after

 원소 삽입시 컨테이너 내부에서 생성 후 지정된 위치에 뒤에 값을 삽입한다.

emplace_hint

 제공 안 함

erase_after

 지정된 위치 다음이나 지정된 위치 이후의 지정한 범위의 모든 데이터를 지운다.

push_front

 list의 처음에 원소를 추가한다.

emplace_front

 원소 삽입시 컨테이너 내부에서 생성 후 컨테이너의 처음에 원소를 추가한다.

pop_front

 list의 처음 원소를 제거한다.

push_back

 제공 안 함

emplace_back

 제공 안 함

pop_back

 제공 안 함

swap

 list1.swap( list2 )일때 list1과 list2를 swap한다.

List operations

merge

 list1.merge( list2 )일때 list1에 list2를 정렬하면서 병합한다.

splice

 2개의 list 중 인자로 주어지는 list의 지정된 원소들을 대상 list로 이동시킨다.

remove

 인자로 받은 값으로 받은 값과 같은 값의 원소를 모두 제거한다.

remove_if

 함수객체의 조건을 만족하는 원소를 모두 제거한다.

reverse

 list에 담긴 원소의 순서를 역순으로 바꾼다.

unique

 list에 담긴 원소 중 연속적으로 중복된 값이 배치된 원소를 제거한다.

sort

 list에 담긴 원소를 정렬한다. 예 : list.sort( std::greater<int>() )

Lookup

count

 제공 안 함

find

 제공 안 함

lower_bound

 제공 안 함

upper_bound

 제공 안 함

equal_range

 제공 안 함

Observers

key_comp

 제공 안 함

value_comp

 제공 안 함

hash_function

 제공 안 함

key_eq

 제공 안 함

Allocator

get_allocator

 list의 allocator 객체를 반환한다.




'STL - Containers > forward_list' 카테고리의 다른 글

[C++11 STL] std::forward_list 개요  (0) 2015.11.17

 

※ 요약

std::list의 주요 멤버 함수 목록이다.

C++03과 C++11의 구분을 색으로 했으며, 추후에 추가되는 C++14, C++17에 대해서도 추가하도록 하겠다.
std::list의 각 멤버 함수들의 본격적인 사용법을 알아보기 전에 한 번 훑어보면 도움이 될 것이다.

 

- C++03

- C++11

 분 류

 멤버 함수

 설 명

Iterators

begin

 첫 번째 원소를 가리키는 반복자를 리턴한다.

cbegin

 첫 번째 원소를 가리키는 상수 반복자를 리턴한다.

end

 마지막 원소를 가리키는 반복자를 리턴한다.

cend

 마지막 원소를 가리키는 상수 반복자를 리턴한다.

rbegin

 역 순차열의 첫 번째 원소를 가리키는 반복자를 리턴한다.

crbegin

 역 순차열의 첫 번째 원소를 가리키는 상수 반복자를 리턴한다.

rend

 역 순차열의 마지막 원소를 가리키는 반복자를 리턴한다.

crend

 역 순차열의 마지막 원소를 가리키는 상수 반복자를 리턴한다.

Element access

at

 제공 안 함

operator[]

 제공 안 함

front

 첫 번째 원소의 참조를 리턴한다.

back

 마지막 원소의 참조를 리턴한다.

Capacity

empty

 원소 존재 유무를 체크한다. 아무것도 없으면 true, 있으면 false를 리턴한다.

size

 원소의 개수를 리턴한다.

max_size

 담을 수 있는 원소의 최대 개수를 리턴한다.

resize

 list의 크기를 변경하고 default 값이나 임의 값으로 초기화한다.

capacity

 제공 안 함

reserve

 제공 안 함

shrink_to_fit

 제공 안 함

Modifiers

clear

 list의 모든 원소를 제거한다.

assign

 기존 원소들은 모두 제거 후, 임의 값으로 n개의 원소를 할당한다.

insert

 임의 위치에 임의 값을 삽입한다.

emplace

 원소 삽입시 컨테이너 내부에서 생성 후 임의 위치에 임의 값을 삽입한다.

emplace_hint

 제공 안 함

erase

 임의 위치의 원소나 지정 범위의 원소를 삭제한다.

push_front

 list의 처음에 원소를 추가한다.

emplace_front

 원소 삽입시 컨테이너 내부에서 생성 후 컨테이너의 처음에 원소를 추가한다.

pop_front

 list의 처음 원소를 제거한다.

push_back

 list의 끝에 원소를 추가한다.

emplace_back

 원소 삽입시 컨테이너 내부에서 생성 후 컨테이너의 끝에 원소를 추가한다.

pop_back

 list의 마지막 원소를 제거한다.

swap

 list1.swap( list2 )일때 list1과 list2를 swap한다.

List operations

merge

 list1.merge( list2 )일때 list1에 list2를 정렬하면서 병합한다.

splice

 2개의 list 중 인자로 주어지는 list의 지정된 원소들을 대상 list로 이동시킨다.

remove

 인자로 받은 값으로 받은 값과 같은 값의 원소를 모두 제거한다.

remove_if

 함수객체의 조건을 만족하는 원소를 모두 제거한다.

reverse

 list에 담긴 원소의 순서를 역순으로 바꾼다.

unique

 list에 담긴 원소 중 연속적으로 중복된 값이 배치된 원소를 제거한다.

sort

 list에 담긴 원소를 정렬한다. 예 : list.sort( std::greater<int>() )

Lookup

count

 제공 안 함

find

 제공 안 함

lower_bound

 제공 안 함

upper_bound

 제공 안 함

equal_range

 제공 안 함

Observers

key_comp

 제공 안 함

value_comp

 제공 안 함

hash_function

 제공 안 함

key_eq

 제공 안 함

Allocator

get_allocator

 list의 allocator 객체를 반환한다.



 

 

'STL - Containers > list' 카테고리의 다른 글

[C++ STL] std::list 개요  (0) 2015.11.11

 

※ 요약
std::vector의 주요 멤버 함수 목록이다.
오버로딩 되는 항목들에 대해서 모두 넣지 않았지만 대략적인 설명을 할 것이므로 큰 문제는 없을 것이다.
또 한 C++03과 C++11의 구분을 색으로 할 것이며, 추후에 추가되는 C++14, C++17에 대해서도 추가하도록 하겠다.
std::vector의 본격적인 사용법을 알아보기 전에 한 번 훑어보면 도움이 될 것이다.

- C++03

- C++11

 분 류

 멤버 함수

 설 명

Iterators

begin

 첫 번째 원소를 가리키는 반복자를 리턴한다.

cbegin

 첫 번째 원소를 가리키는 상수 반복자를 리턴한다.

end

 마지막 원소를 가리키는 반복자를 리턴한다.

cend

 마지막 원소를 가리키는 상수 반복자를 리턴한다.

rbegin

 역 순차열의 첫 번째 원소를 가리키는 반복자를 리턴한다.

crbegin

 역 순차열의 첫 번째 원소를 가리키는 상수 반복자를 리턴한다.

rend

 역 순차열의 마지막 원소를 가리키는 반복자를 리턴한다.

crend

 역 순차열의 마지막 원소를 가리키는 상수 반복자를 리턴한다.

Element access

at

 n번째 원소를 참조할 때 사용하며 범위 점검을 하므로 []보다 느리다.

operator[]

 n번째 원소를 참조할 때 사용하며 범위 점검을 안하므로 at보다 빠르다.

front

 첫 번째 원소의 참조를 리턴한다.

back

 마지막 원소의 참조를 리턴한다.

Capacity

empty

 원소 존재 유무를 체크한다. 아무것도 없으면 true, 있으면 false를 리턴한다.

size

 원소의 개수를 리턴한다.

max_size

 담을 수 있는 원소의 최대 개수를 리턴한다.

resize

 vector의 크기를 변경하고 default 값이나 임의 값으로 초기화한다.

capacity

 vector에 할당된 메모리의 크기를 리턴한다.

reserve

 지정한 크기 만큼의 메모리를 미리 할당한다.

shrink_to_fit

 사용되지 않는 capacity size를 제거한다. 즉 size() == capacity()가 된다.

Modifiers

clear

 vector의 모든 원소를 제거한다.

assign

 기존 원소들은 모두 제거 후, 임의 값으로 n개의 원소를 할당한다.

insert

 임의 위치에 임의 값을 삽입한다.

emplace

 원소 삽입시 컨테이너 내부에서 생성 후 임의 위치에 임의 값을 삽입한다.

emplace_hint

 제공 안 함

erase

 임의 위치의 원소나 지정 범위의 원소를 삭제한다.

push_front

 제공 안 함

emplace_front

 제공 안 함

pop_front

 제공 안 함

push_back

 vector의 끝에 원소를 추가한다.

emplace_back

 원소 삽입시 컨테이너 내부에서 생성 후 컨테이너의 끝에 원소를 추가한다.

pop_back

 vector의 마지막 원소를 제거한다.

swap

 v1.swap( v2 )일때 v1과 v2를 swap한다.

List operations

merge

 제공 안 함

splice

 제공 안 함

remove

 제공 안 함

remove_if

 제공 안 함

reverse

 제공 안 함

unique

 제공 안 함

sort

 제공 안 함

Lookup

count

 제공 안 함

find

 제공 안 함

lower_bound

 제공 안 함

upper_bound

 제공 안 함

equal_range

 제공 안 함

Observers

key_comp

 제공 안 함

value_comp

 제공 안 함

hash_function

 제공 안 함

key_eq

 제공 안 함

Allocator

get_allocator

 vector의 allocator 객체를 반환한다.




'STL - Containers > vector' 카테고리의 다른 글

[C++ STL] std::vector - emplace_back  (3) 2016.04.15
[C++ STL] std::vector - push_back  (0) 2016.02.19
[C++ STL] std::vector 개요  (3) 2015.11.10

 

※ std::array 요약
std::array는 C++11에 새롭게 추가된 컨테이너 라이브러리로써, 크기가 고정되어 있다는 것을 제외하면 std::vector와 비슷하다.
크기가 고정이므로 스택에 저장되며 C++03까지는 없었던 고정 길이 배열 자료구조 컨테이너로써 기존의 배열을 대체하기에 완벽하다.

※ std::array 특징
- 배열을 대체할 수 있다.
- 정적 배열이므로 스택에 저장된다. (std::vector는 힙 메모리에 저장된다!)
- 데이터가 연속된 위치에 저장되므로 랜덤 액세스가 가능하고 접근 속도도 빠르다.
- 정적이므로 push_back(), pop_back(), insert(), erase(), clear(), resize(), reserve(), capacity()멤버 함수는 지원하지 않는다.

※ std::array를 사용해야 하는 경우
- C++11이 지원되는 컴파일러라면 배열 대신 사용하면 좋다.
(필자는 C++11이 지원되는 컴파일러에서 작업하면 배열 대신 무조건 std::array를 사용한다. STL과 새롭게 추가되는 문법 등과의 결합도가 좋고 속도도 빠르며, 무엇보다 (조금이지만)편하기 때문이다.)


 

※ std::deque 요약
std::deque는 Double Ended Queue의 약자로써, 시퀀스 컨테이너다.

필자는 시뮬레이터 서버를 제작할 때와 Singleton 방식의 Log Class를 제작할때 std::deque의 사용을 고려해본 적이 있다.


※ std::deque 특징

- 크기가 가변적이다. (사실 std::array를 제외한 거의 모든 STL 컨테이너의 특징이다.)

- 앞(front)과 뒤(back)에서의 삽입, 삭제 성능은 좋지만 중간에서의 삽입, 삭제는 그다지 좋지 않다.

- std::deque는 Stack과 Queue가 결합된 자료구조로써 연결 리스트보다 구현하기가 어렵다.

- std::vector처럼 랜덤 액세스가 가능하다.


※ std::deque와 std::vector
- std::deque와 std::vector의 멤버 함수 기능이나 사용 방법은 거의 동일하다.

- std::vector는 뒤(back)에서의 삽입, 삭제 성능이 좋지만 std::deque는 앞(front), 뒤(back), 모두에서 좋다.

- std::deque의 앞, 뒤 삽입, 삭제 성능을 제외한 다른 위치에서의 삽입, 삭제는 std::vector가 더 좋다.

- 둘 다 랜덤 액세스가 가능하다.

 

※ std::deque를 사용해야 하는 경우

- 앞과 뒤에서 삽입, 삭제를 자주 할 때

- 저장할 데이터의 개수가 가변적 일 때

- 데이터 검색을 거의 하지 않거나, 아예 안 할 때 (검색을 해야 한다면 std::map이나 std::set 등의 연관 컨테이너 사용을 고려)

- 랜덤 액세스를 해야 할때

- 서버처럼 받은 패킷을 차례대로 처리할 때 (이 때는 범용적인 deque보다 좀 더 좋은 성능의 독자적인 자료구조를 만들기도 함)


 

 

 

※ STD::forward_list 요약
std::list가 양방향(double linked list)이라면 std::forward_list는 단방향(single linked list)이다.
단방향 연결 리스트라 양방향인 std::list보다 메모리 사용량이나 처리 속도면에서 조금 유리하다.
double linked list가 필요하다면 std::list를, single linked list로도 충분하다면 std::forward_list를 사용한다.

※ std::forward_list 특징
- single linked list(단일 연결 리스트) 자료구조를 이용하여 만든 시퀀스 컨테이너다.
- 설계 디자인을 std::list에 맞춘다.(STL은 범용성을 지향하므로 다른 컨테이너들도 마찬가지다.)
- 속도와 사이즈, 즉 성능을 최우선으로 설계, 제작되었다.
- 다른 STL 컨테이너에 있는 size 함수를 제공하지 않는다.
- size는 다음과 같이 구한다. -> size_t size = std::distance( list.begin(), list.end() )

※ std::forward_list와 std::list
- std::list는 양방향으로 이동 가능하지만 std::forward_list는 한 방향으로만 이동할 수 있다.
- std::list보다 삽입/삭제 속도가 아주 약간 더 빠르다.
- 양방향인 std::list에 비해 메모리를 적게 사용한다. 각 요소 뿐만이 아닌, 컨테이너 자체 사이즈도 더 작다.
- 삽입과 삭제는 지정한 요소의 다음 요소에 한해서만 가능하다.(단방향이므로 당연하다)
- 구현의 복잡성과 성능 문제 때문에 std::list에서 제공하는 insert와 erase를 제공하지 않는다.

 

※ std::forward_list를 사용해야 하는 경우

- double linked list가 아닌 single linked list로도 충분할때


 

 

※ std::set 요약
std::set은 std::map과 상당히 비슷한 연관 컨테이너이다. 다른 점이 있다면 value 없이 key만으로 이뤄졌다는 것 정도이다.
std::set은 노드 기반 컨테이너이며 균형 이진 트리로 구현 되므로 균형 이진 트리의 모든 특징을 갖는다.
std::set은 std::map과 마찬가지로 중복된 key를 저장할 수 없으므로, 중복 저장하고 싶다면 std::multiset을 사용해야 한다.
동일 타입 집합이라는 점에서는 std::vector와 같지만 요소가 정렬된 위치에 삽입 된다는 점이 다르다.

※ std::set 특징
- std::set은 std::map과 상당히 비슷하다. 차이점이라면 std::map과 다르게 value 없이 key만 저장한다는 것 정도다.
- std::set의 key는 중복될 수 없다. 중복 저장해야 한다면 std::multiset을 사용한다.
- 데이터 삽입과 동시에 정렬이 일어난다.
- 정렬은 key를 기준으로 정렬되며 기본 정렬 기준은 less(오름차순) 정렬이다.
- 검색 또한 key를 기준으로 검색(이분검색)한다.
- 검색시 균형 이진 트리를 이용한 로그 시간 검색 복잡도를 보장한다.

※ std::set을 사용해야 하는 경우
- 삽입과 동시에 정렬해야 할때
- key가 있는지 없는지 알아야 할때
- 많은 데이터를 보관해야 하고, 동시에 검색이 빨라야 할때
- 많은 데이터가 중복 되어서는 안 되며 빠른 검색으로 존재 여부를 신속하게 알고 싶을때!

 

※ std::map 요약
필자가 std::vector와 함께 많이 사용하는 연관 컨테이너 std::map에 대한 설명이다.
std::map은 key와 value의 쌍을 원소로 저장(pair 객체로 저장)하며, set처럼 원소의 key는 중복될 수 없다.
중복 key를 저장해야 한다면 std::multimap을 사용하여야 한다.
연관 컨테이너는 어떠한 key와 짝을 이루어 자료를 보관하는데, 자료를 넣거나 빼거나 찾을 때는 key를 이용하여야 한다.

※ std::map 특징
- std::map은 레드-블랙 트리(Red-Black Tree) 자료구조이다.
- std::map의 key는 중복될 수 없다. 중복 저장해야 한다면 std::multimap을 사용한다.
- 데이터 삽입과 동시에 정렬이 일어난다.
- 정렬은 key를 기준으로 정렬되며 기본 정렬 기준은 less(오름차순) 정렬이다.
- 검색 또한 key를 기준으로 검색(이분검색)한다.
- std::map의 원소는 std::pair 객체로 저장된다.
- 저장할 자료가 적을때는 메모리 낭비와 검색시 오버헤드가 생겨 대포로 파리 잡는 격이다.

※ std::map을 사용해야 하는 경우
- 삽입과 동시에 정렬해야 할때
- 많은 데이터를 보관해야 하고, 동시에 검색이 빨라야 할때
- 데이터 삽입, 삭제가 적을때


+ Recent posts