반응형

주어진 문제는 위와 같다. 트리 노드의 개수인 n 이 주어지면, n 개의 노드를 갖는 BST 들을 찾는 것이다. 이 때, n 개의 노드들은 각각 1 부터 n 까지의 값을 갖는다.

 

BST (Binary Search Tree) 는 기본적으로 각 서브트리에서 루트 노드보다 작은 값들만 루트 노드의 Left 서브 트리에 저장될 수 있고, 루트 노드보다 큰 값들만 루트 노드의 Right 서브 트리에 저장될 수 있다는 특징을 갖는다.

 

이러한 특징을 기반으로 재귀를 활용해 문제를 풀이했다. 풀이 방식은 각 재귀 단계마다 BST 를 구성하려는 값의 범위 start ~ end 가 주어지고 그 범위 내의 값들을 루트 노드로 하는 BST 를 찾는 것이다.

 

간단한 슈도 코드로 이를 표현하자면, 다음과 같다.

recursiveBST(start, end):
	for i in (start, end):
    	leftLists <- recursive_bst(start, i - 1)
        rightLists <- recursive_bst(i + 1, end)
        
        for left in leftLists:
        	for right in rightLists:
            	root <- new node(i)
                
                root.left <- left
                root.right <- right

(start, end) 범위 내에서 각각의 값을 갖는 노드를 루트 노드로 구성하고, 그 값보다 작은 값들을 갖는 서브 트리들과 그 값보다 큰 값들을 갖는 서브 트리들을 각각 루트 노드의 왼쪽 서브 트리, 오른쪽 서브 트리로 구성한다.

 

이러한 풀이 방식을 바탕으로 작성한 소스 코드는 다음과 같다.

 

class Solution {
public:
    vector<TreeNode*> generateTrees(int start, int end) {
        vector<TreeNode*> binarySearchTrees;
        if (start > end) {
            binarySearchTrees.push_back(NULL);
            return binarySearchTrees;
        }
        if (start == end) {
            binarySearchTrees.push_back(new TreeNode(start));
            return binarySearchTrees;
        }
        for (int i = start; i <= end; i++) {
            vector<TreeNode*> leftList = generateTrees(start, i - 1);
            vector<TreeNode*> rightList = generateTrees(i + 1, end);

            for (int l = 0; l < leftList.size(); l++) {
                for (int r = 0; r < rightList.size(); r++) {
                    TreeNode* root = new TreeNode(i);
                    root->left = leftList[l];
                    root->right = rightList[r];

                    binarySearchTrees.push_back(root);
                }
            }
        }

        return binarySearchTrees;
    }

    vector<TreeNode*> generateTrees(int n) {
        return generateTrees(1, n);
    }
};

'Algorithm > LeetCode' 카테고리의 다른 글

[LeetCode # 68] Text Justification  (0) 2021.09.07
[LeetCode # 1629] Slowest Keys  (0) 2021.09.07
[LeetCode # 153] Find Minimum in Rotated Sorted Array  (0) 2021.09.01
[LeetCode # 60] Permutation Sequence  (0) 2021.09.01
[LeetCode # 135] Candy  (0) 2021.06.27
반응형

주어진 문제는, 어떤 배열이 주어졌을 때 그 배열에서 가장 작은 값을 찾는 문제이다. 이 때, 배열은 정렬된 배열을 rotation 시킨 배열로 주어진다.

 

예를 들어, [0, 1, 2, 3, 4, 5, 6, 7] 과 같이 정렬된 배열이 주어질 수도 있고 [4, 5, 6, 7, 0, 1, 2, 3] 과 같이 앞의 정렬된 배열에서 [0, 1, 2, 3] 의 위치가 뒤로 이동한 배열이 주어질 수도 있다.

 

이 문제에서 주어진 조건은, 문제 해결 시 O(log n) 의 시간복잡도를 갖는 알고리즘을 사용해야 한다는 것이다.

 

문제 해결 전략은 다음과 같다. 기본적으로 이분 탐색을 사용해 배열을 반씩 분할해 각 분할마다 최소값을 찾고, 그 중 가장 최소값을 찾는다.

로테이션이 된 배열이기 때문에, 전체 배열은 정렬이 되지 않은 상태일 수 있지만 부분 배열은 정렬이 된 상태일 수 있다. 위의 [4, 5, 6, 7, 0, 1, 2, 3] 의 배열을 반으로 분할해 보면, [4, 5, 6, 7], [0, 1, 2, 3] 과 같이 표현된다. 이 때 각 부분배열은 모두 정렬된 상태이므로 최소값을 쉽게 찾을 수 있다.

 

만약, 분할된 부분배열이 정렬되지 않은 배열일지라도, 예를 들어 [4, 5, 0] 이라고 하면 이러한 배열은 다시 또 분할을 해서 정렬된 상태가 될 때까지 분할을 하면 된다. 계속 반으로 분할을 하다보면, 언젠가는 정렬된 부분배열이 될 것이고 (혹은 한 개의 원소만 남은 배열이 되거나) 그 때의 최소값은 바로 탐색할 수 있기 때문에 이 방법은 O(log n) 의 시간복잡도를 갖는 알고리즘이라 할 수 있다.

 

위와 같은 풀이로 작성한 소스 코드는 다음과 같다.

 

class Solution {
public:
    int binarySearch(vector<int>& nums, int s, int e) {
        if (s >= e) {
            return nums[s];
        }
        if (nums[s] < nums[e]) {
            return nums[s];
        }

        int m = (s + e) / 2;
        int l = binarySearch(nums, s, m);
        int r = binarySearch(nums, m + 1, e);
        return l < r ? l : r;
    }
    int findMin(vector<int> &nums) {
        int min = binarySearch(nums, 0, nums.size() - 1);
        return min;
    }
};
반응형

주어진 문제는, 주어진 n, k 에 해당하는 순열을 찾는 것이다. n (1 <= n <= 9) 은 순열에 포함되는 수의 개수이고, k (1 <= k <= n!) 는 순열의 순서이다.

 

예를 들어, (n, k) 가 (3, 3) 으로 주어졌다면 기대되는 출력값은 "213" 이 된다. 위의 그림에서 보여지듯, "123", "132", "213", ... 의 순서로 순열을 생성할 수 있고, 그 중 k 번째 수열은 "213" 이다. (1-indexed)

 

이 문제를 해결하기 위한 전략은 다음과 같다. n 이 3일 때 생성되는 순열은 "123", "132" / "213", "231" / "312", "321" 이다. '/' 로 나눠놓은 것을 보면 각각 수열이 갖는 첫번째 수가 같은 것끼리 묶여있음을 알 수 있고, 이를 바탕으로 문제를 해결할 수 있음을 유추할 수 있다.

 

(n, k) 가 (4, 7) 로 주어진 경우를 생각해 보면, n 이 4이므로 사용 가능한 숫자들의 목록은 [1, 2, 3, 4] 가 된다. 세 개의 숫자로 구성할 수 있는 수열은 6개이므로 "1", "2", "3", "4" 로 시작하는 각각의 수열의 개수는 6개임을 알 수 있다. 이 때, 각 숫자의 순서대로 수열이 순서를 가지므로 k 가 7이라는 것은, "2" 로 시작하는 수열을 찾고자 함을 알 수 있고, 그 중 1번째 수열임을 알 수 있다.

 

이러한 방식으로, 첫 번째 숫자를 찾고 그 뒤에는 남은 [1, 3, 4] 를 통해 앞으로 어떤 숫자들이 수열에 순서대로 위치할 지를 찾아낼 수 있다. 문제를 풀이한 소스 코드는 다음과 같이 작성했다.

 

class Solution {
public:
    int factorial(int n) {
        int result = 1;
        while (n > 1) {
            result *= n--;
        }

        return result;
    }

    string getPermutation(int n, int k) {
        vector<int> nums;
        for (int i = 1; i <= n; i++) {
            nums.push_back(i);
        }

        string ans = "";

        while (n > 1) {
            int blockSize = factorial(n - 1);
            int block = k / blockSize;
            k %= blockSize;

            ans += to_string(nums[block]);
            nums.erase(nums.begin() + block);
            n--;
        }

        return ans + to_string(nums[0]);
    }
};
반응형

AJAX 란?

JavaScript 라이브러리 중 하나로 Asynchronous Javascript and XML 의 약자
브라우저가 가지고있는 XMLHttpRequest 객체를 이용해 전체 페이지를 새로 고치지 않고도 페이지의 일부만을 위한 데이터를 로드하는 기법
JavaScript 를 사용한 비동기 통신, 클라이언트와 서버 간에 XML 데이터를 주고받는 기술

 

기본적으로 HTTP 프로토콜은 클라이언트 측에서 Request 를 보내고, 서버 측에서 Response 를 받으면 이어졌던 연결이 끊기게 되고
화면의 내용을 갱신하기 위해서 다시 Request 를 하고 Response 를 받아 페이지 전체를 갱신하게 됨.
이렇게 할 경우, 엄청난 자원 낭비와 시간 낭비로 이어짐.

 

AJAX 를 이용하게 되면, XMLHttpRequest 객체를 통해 서버에 Request 를 보내고
JSON 이나 XML 형태로 필요한 데이터만 받아 갱신하기 때문에 자원과 시간을 아낄 수 있음.

 

AJAX 의 장점과 단점

장점

  • 웹페이지의 속도향상
  • 서버의 처리가 완료될 때까지 기다리지 않고 처리가 가능하다.
  • 서버에서 Data만 전송하면 되므로 전체적인 코딩의 양이 줄어든다.
  • 기존 웹에서는 불가능했던 다양한 UI를 가능하게 해준다. ( Flickr의 경우, 사진의 제목이나 태그를 페이지의 리로드 없이 수정할 수 있다.)

단점

  • 히스토리 관리가 되지 않는다.
  • 페이지 이동없는 통신으로 인한 보안상의 문제가 있다.
  • 연속으로 데이터를 요청하면 서버 부하가 증가할 수 있다.
  • XMLHttpRequest를 통해 통신하는 경우, 사용자에게 아무런 진행 정보가 주어지지 않는다. (요청이 완료되지 않았는데 사용자가 페이지를 떠나거나 오작동할 우려가 발생하게 된다.)
  • AJAX를 쓸 수 없는 브라우저에 대한 문제 이슈가 있다.
  • HTTP 클라이언트의 기능이 한정되어 있다.
  • 지원하는 Charset이 한정되어 있다.
  • Script로 작성되므로 디버깅이 용이하지 않다.
  • 동일-출처 정책으로 인하여 다른 도메인과는 통신이 불가능하다. (Cross-Domain문제)

'Study > Etc' 카테고리의 다른 글

[Web] HTTP 와 HTTPS  (0) 2021.10.12
[REST] REST 란?  (0) 2021.10.10
Build Tool 이란?  (0) 2021.07.02
Zeppelin 에서 external package import 하기  (0) 2018.02.17
반응형

Features Added in MySQL 8.0

 

MySQL :: MySQL 8.0 Reference Manual :: 14 MySQL Data Dictionary

Chapter 14 MySQL Data Dictionary MySQL Server incorporates a transactional data dictionary that stores information about database objects. In previous MySQL releases, dictionary data was stored in metadata files, nontransactional tables, and storage engine

dev.mysql.com

 

MySQL :: MySQL 8.0 Reference Manual :: 13.1.1 Atomic Data Definition Statement Support

13.1.1 Atomic Data Definition Statement Support MySQL 8.0 supports atomic Data Definition Language (DDL) statements. This feature is referred to as atomic DDL. An atomic DDL statement combines the data dictionary updates, storage engine operations, and bi

dev.mysql.com

  • 보안 및 계정 관리
  • 자원 관리
  • 테이블 암호화 관리
  • InnoDB
  • JSON
  • Data Type Support
  • Optimizer

Reference.

[MySQL 8.0 Ref] https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html#mysql-nutshell-additions

 

MySQL :: MySQL 8.0 Reference Manual :: 1.3 What Is New in MySQL 8.0

These functions are removed in favor of the ST_ names: Area(), AsBinary(), AsText(), AsWKB(), AsWKT(), Buffer(), Centroid(), ConvexHull(), Crosses(), Dimension(), Distance(), EndPoint(), Envelope(), ExteriorRing(), GeomCollFromText(), GeomCollFromWKB(), Ge

dev.mysql.com

 

'Study > Database' 카테고리의 다른 글

[DB] 키의 개념과 종류  (1) 2021.10.08
[DB] 정규화 (Normalization) 란?  (0) 2021.10.08
[DB] DB Index  (0) 2021.10.07
관계형 데이터베이스의 정의와 종류  (0) 2021.07.02
반응형

Java 는 Version 별로 새로운 기능을 출시하는 등 큰 변경점이 있다. 버전 중에서도 LTS (Long Term Service) 버전들은 장기적으로 업데이트가 보장되므로 호환성이나 안정성 면에서 장점이 있다고 생각해 Java 8 과 11 의 각 변경점에 대해서 간단하게 정리를 해 보려고 한다.

 

Java 8

Java 8 은 2014 년 발표된 Java 버전으로 다음과 같은 주요 변경사항이 있었다.

  • Lambda 표현식
  • Stream API
  • java.time 패키지

람다 표현식 (Lambda Expression)

우선 람다 표현식이란, 익명 클래스의 한 개 메소드를 식으로 표현한 것이다. 여기서 익명 클래스란, 말 그대로 이름이 없는 클래스로 단 한 개의 객체만을 생성할 수 있는 일회용 클래스이다.

// 익명 클래스의 예
new Object() {
	int min(int x, int y) {
    	return x < y ? x : y;
    }
}
// 람다 표현식의 예
(x, y) -> x < y ? x : y;

이러한 람다 표현식은 매개변수로 전달될 수 있으며, 메소드의 결과값으로 반환될 수도 있다. 따라서 람다 표현식을 사용할 경우 기존의 불필요한 코드를 줄이고 작성된 코드의 가독성을 높일 수 있다. Java 8 부터는 이러한 람다 표현식을 사용해 자바에서도 함수형 프로그래밍이 가능하게 되었다.

스트림 API (Stream API)

자바에서는 여러 데이터를 저장하기 위해 배열 / 컬렉션을 사용한다. 그리고 이렇게 저장된 데이터에 접근하기 위한 방법으로 반복문이나 Iterator 를 사용해 매번 코드를 작성해야 했다.

하지만 이렇게 작성된 코드는 길이가 길고 가독성도 떨어지며, 코드의 재사용이 거의 불가능하다. 또한, 정형화된 처리 패턴을 가지지 못하기 때문에 데이터마다 다른 방법으로 접근해야 했다.

이러한 문제를 극복하기 위해 도입된 방법이 바로 스트림 API 이다. 스트림 API 는 데이터를 추상화해서 다루므로, 다양한 형태로 저장된 데이터를 위한 공통된 방법을 제공한다. 따라서 스트림 API 를 사용하면 배열이나 컬렉션 뿐 아니라, 파일에 저장된 데이터도 모두 같은 방법으로 다룰 수 있다.

 

다음은 스트림 API 를 사용한 예제이다.

// 정수형 배열에서의 스트림 생성
int [] arr1 = new int[]{1, 5, 11, 13, 20, 52};
Stream stream1 = Arrays.stream(arr1);
stream1.map(i -> i * 2);
stream1.filter(i -> i % 2 == 0); // 재사용이 불가능하기 때문에 에러 발생

// 정수형 배열에서 스트림 생성
int [] arr2 = new int[]{1, 5, 11, 13, 20, 52};
Stream stream2;
stream2 = Arrays.stream(arr2)
				.filter(i -> i % 2 != 0)	// {1, 5, 11, 13}
                .map(i -> i * 2);			// {2, 10, 22, 26}

java.time 패키지

java.time 패키지는 기존에 사용하던 Date 클래스나 Calendar 클래스의 문제를 해결하기 위해 새롭게 등장한 날짜/시간 API 패키지이다.

 

Java 11

Java 11 은 2018 년에 발표된 Java 버전으로 Java 8 이후 최초로 공개된 Java 의 LTS 버전이다. Oracle 은 Java 8 에 대한 지원을 2019 년에 중단했고, Java 11 은 많은 변화가 있었다.

 

Local-Variable Syntax for Lambda Parameters

jdk 10 버전에서 지역변수로 사용할 수 있는 var 가 새로운 feature 로 추가되었는데, jdk 11 버전에서는 var 를 람다 표현식을 쓰는 경우에, 전달되는 parameter 들의 타입을 추론할 수 있는 Feature 가 추가되었다.

list.stream()
	.map((var s) -> s.toLowerCase())
    .collect(Collectors.toList());

물론 기존의 람다 표현식에서도 타입을 생략하면, 컴파일러가 컴파일 시 s 의 타입을 String 으로 추론한다. 그렇다면, jdk 8 의 추론 방법이 더 간단한데 왜 이런 feature 가 추가되었을까?

Align the syntax of a formal parameter declaration in an implicitly typed lambda expression with the syntax of a local variable declaration.

JEP 323의 Goals 를 보면, 위와 같이 명시되어있는데 jdk 10 에서 명시적으로 선언되던 구문을 var 로 선언할 수 있게 되었고, 이런 특징을 람다 표현식에도 적용해, 암시적으로 선언되던 형태를 var 로 선언해 표현식을 통일할 수 있게 되었다.

또한, 이렇게 명시적으로 선언하면 람다표현식에서 어노테이션을 사용하는 경우 아래와 같이 조금 더 간단하게 코드를 작성할 수 있다.

list.stream()
	.map((@NotNull var s) -> s.toLowerCase())
    .collect(Collectors.toList());

HTTP Client (Standard)

jdk 9 에서 추가되고 jdk 10 에서 업데이트된 java.incubator.http 패키지가 인큐베이터에서 나와 java.net.http 패키지로 표준화되었다. 이 패키지가 개발된 이유는 아래와 같다.

  • 베이스가 되는 URLConnection API 가 현재는 거의 사용되지 않는 프로토콜을 염두에 두고 설계되었다.
  • HTTP/1.1 보다 너무 추상적이다.
  • 문서화가 잘 되어있지 않아 사용이 어렵다.
  • Blocking 형태로만 동작한다.
  • 유지보수의 어려움이 있다.

java.net.http 로 옮겨진 패키지의 기능은 아래와 같다.

  • Non-Blocking request and response 지원 (with CompletableFuture)
  • Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 RX Flow 를 구현체에 적용)
  • HTTP/2 지원
  • Factory method 형태로 지원

ZGC : A Scalable Low-Latency Garbage Collector (Experimental)

jdk 11 에서 새롭게 등장한 가비지 콜렉터이다. ZGC 라고도 불리는 이 가비지 콜렉터는 아래의 몇 가지 목표를 가지고 개발되었다.

  • GC 일시 중지 시간은 10ms 를 초과하지 않는다.
  • 작은 크기(수백 메가) ~ 매우 큰 크기(수 테라) 범위의 힙을 처리한다.
  • G1 에 비해 어플리케이션 처리량이 15% 이상 감소하지 않는다.
  • 향후 GC 최적화를 위한 기반을 마련한다.
  • 처음에는 Linux / x64 를 지원한다. (향후 추가 플랫폼을 추가 지원할 수 있다.)

알다시피, JVM 으로 구동되는 어플리케이션의 경우는 GC 가 동작할 때 어플리케이션이 멈추는 현상은 성능에서 큰 영향을 끼쳐 왔다. 이러한 정지시간을 줄이거나 없앰으로써 어플리케이션의 성능 향상에 기여할 수 있다.

ZGC 의 주요한 원리는 Load Barrier 와 Colored Object Pointer 를 동시에 사용하는 것이다. 이를 통해 Java 의 어플리케이션 스레드가 동작하는 중간에, ZGC 가 객체 재배치 같은 작업을 수행할 수 있게 해준다.

 

이 외에도, 다양한 성능적 향상이 java 8 버전에 비해 제공된다고 한다.

'Study > Java' 카테고리의 다른 글

[Java] Annotation 이란?  (0) 2021.11.03
[Java] 서블릿 (Servlet) 과 JSP (Java Server Page)  (0) 2021.09.30
JPA 란?  (0) 2021.06.18
반응형

Build Tool 이란, 프로젝트 내에서 소스 코드를 가지고 실행 가능한 Application 을 자동으로 생성해 주는 도구이다. 빌드에는 소스 코드를 컴파일하고 링크 및 패키징을 통해 실행 가능한 형태로 변환하는 것이 포함된다.

 

기본적으로 빌드의 자동화는 소프트웨어 개발자가 다음과 같은 일상적으로 수행하는 다양한 작업을 스크립트화 하거나 자동화하는 행위로 볼 수 있다.

  • Downloading Dependencies
  • Compiling Source Code into Binary Code.
  • Packaging that Binary Code.
  • Running Tests.
  • Deployment to Product System.

그렇다면, 이러한 빌드 툴은 왜 사용하는 것일까?

소규모의 프로젝트에서는 위와 같이 의존성이 있는 라이브러리나 API 를 직접 설치하고, 소스 코드를 빌드하고 실행하는 것이 큰 문제가 되지 않는다. 하지만 프로젝트의 규모가 커지고, 소스 코드가 방대해질 경우에 각각의 라이브러리들을 일일히 설치하고 사용하는 것은 프로젝트를 수행함에 있어 불필요한 업무의 비중이 높은 것으로 생각될 수 있다. 개발자는 이러한 불필요한 업무를 하지 않기 위해, 자동으로 의존성을 관리하고 소스를 빌드할 수 있는 도구를 사용하는 것이다.

 

Gradle / Maven

그럼 Java Application 에서 사용하는 Build Tool 은 무엇이 있을까? 대표적으로 Ant, Gradle, Maven 이 있다.

이 중 내가 비교할 것은 Gradle 과 Maven 이다. Ant 는 초기 Java 의 빌드 툴이고, 이를 보완해서 등장한 것이 Maven 이기 때문이다.

 

우선, Maven 은 pom.xml 을 이용해 정형화된 빌드 시스템을 제공한다. 또한 프로젝트에 대한 정보를 제공하고 개발 가이드라인을 제공한다. 물론 Build Tool 이기에, 새로운 기능을 쉽게 설치하고 업데이트할 수도 있다.

다른 Build Tool 인 Gradle 은 Maven 에 비해 최근 출시된 Tool 로, Ant 와 Maven 의 장점을 모아서 개발되었다고 한다. Build 라는 동적인 요소를 XML 로 정의하는 것에는 설정한 내용의 가독성이 떨어진다거나 의존관계가 복잡한 경우 등의 한계가 있었다. Gradle 은 Maven 과 달리 Groovy 를 사용하기 때문에 동적인 빌드의 경우 Groovy 스크립트로 플러그인을 호출하거나 코드를 직접 짤 수 있다. 또한, 성능적으로도 차이가 있는데 Gradle 이 Maven 에 비해 최대 100배 빠른 성능을 보여준다고 한다.

 

Gradle 의 단점이라고 한다면, Groovy 문법에 대해 새롭게 공부를 해야 한다는 점으로 볼 수 있을 것이다. 하지만 개발자로서 새로운 것을 배우는 것은 항상 거쳐가야 하는 단계라고 생각을 하기도 하고, 굳이 더 좋은 Gradle 이 있는데 Maven 을 사용해야 할 이유도 없어 Gradle 을 일반적으로 사용하게 될 것 같다.

 

 

'Study > Etc' 카테고리의 다른 글

[Web] HTTP 와 HTTPS  (0) 2021.10.12
[REST] REST 란?  (0) 2021.10.10
AJAX  (0) 2021.07.05
Zeppelin 에서 external package import 하기  (0) 2018.02.17
반응형

관계형 데이터베이스 (RDB ; Relational DataBase)

글을 적기에 앞서 우선, RDB 가 무엇인지부터 얘기해 보려고 한다. RDB 란 Relational DataBase 즉, 관계형 데이터 모델에 기초를 둔 데이터베이스이다. 여기서 관계형 데이터 모델이란, 자료를 2차원 구조의 테이블 형태로 표현하는 것을 말한다.

 

간단한 예로, 학생들의 정보를 저장한다고 할 때 다음과 같이 표현을 할 수 있다.

학생 번호 이름 성별 나이 소속 학교
A0001 김갑수 남자 19 감수고등학교
A0002 나고수 남자 15 한동중학교
A0003 한경자 여자 17 한서고등학교

 

이러한 관계형 데이터 모델에서 사용되는 용어는 다음과 같다.

 

- 릴레이션 (Relation) : 데이터들을 2차원 테이블의 구조로 저장한 것.

- 속성 (Attribute) : 릴레이션의 열(=Column), 개체를 구성하는 속성들.

- 튜플 (Tuple) : 릴레이션의 행(=Row), 속성들의 집합이며 레코드(Record) 라고도 부름.

- 차수 (Degree) : 릴레이션을 구성하는 속성 수(열의 개수)

- 카디널리티 (Cardinality) : 릴레이션에 입력된 튜플의 수

 

RDBMS 는 이런 RDB 를 관리하기 위한 소프트웨어라 정의할 수 있다. SQL 이라는 구조화된 질의어를 사용해 RDB 를 생성하고, 관리할 수 있는데 대표적으로 MySQL, Oracle DB, Maria DB 등이 있다.

 

MySQL

우선, MySQL 은 세계적으로 널리 사용되는 오픈 소스 DBMS 이다. 오픈 소스이기 때문에 무료로 사용이 가능하고, 다양한 운영체제에서 여러 가지의 프로그래밍 언어와 사용할 수 있다. 널리 알려진 표준 SQL 형식을 사용하며 크기가 큰 데이터의 집합도 빠르고 효과적으로 처리가 가능하다.

MySQL 은 CLI 를 통해 사용할 수도 있고, MySQL 에서 공식적으로 개발/지원하는 MySQL Workbench 를 사용해 GUI 를 활용할 수도 있다.

 

Oracle DB

Oracle DB 는 오라클 사의 관계형 데이터베이스 관리 시스템의 이름이다. 현재 유닉스 환경에서 가장 널리 사용되는 RDBMS 라고 한다. 검색이나 업데이트를 위한 언어로 SQL 과 PL/SQL 을 지원한다.

* PL/SQL 은 오라클 DB 에서 SQL 언어를 확장하기 위해 사용하는 컴퓨터 프로그래밍 언어 중 하나이다. 주로 자료 내부에서 SQL 명령문만으로 처리하기에 복잡한 자료의 저장이나 프로지서 / 트리거 등을 작성하는 데 쓰인다고 한다. 

 

MySQL vs. Oracle DB

MySQL 과 Oracle DB 중 무엇을 사용할 것인가?

오라클은 일반적으로 충분히 큰 예산과 복잡한 비즈니스적 요구, 기업 고객을 위해 설계되었다. 반면, MySQL 은 가장 일반적으로 데이터베이스 기반 웹 사이트나 Non-Critical 애플리케이션을 위해 사용되는 저가의 데이터베이스이다.

 

Oracle DB 의 특징

오라클 DB 의 특징은 아래와 같이 크게 5가지로 표현할 수 있다.

  • Oracle Management Server
    • 오라클 DB 는 중앙 집중 방식으로 Administration Monitoring 이 가능하고, Multiple Database 를 튜닝할 수 있다.
    • 다른 Admin User 들과 공유가 가능하다.
  • Oracle Change Manager
    • 변경 Plan 을 작성하고 실제로 구현하기 전에, 변경 사항의 효과를 볼 수 있다.
    • 생산 시스템을 방해하지 않는다.
  • Administrative Alerts
    • 오류 발생 시 오라클은 이메일이나 설정되어 있는 계정으로 연락을 줄 수 있다.
    • 경고는 예정된 정지 시간동안 차단될 수 있다.
  • Capacity Planning
    • 업그레이드 관리자의 계획을 돕기 위해 사용 패턴의 추적이 가능하다.
    • 병목 현상을 쉽게 파악할 수 있다.
  • Query Optimizer
    • 쿼리 최적화 프로그램으로 오라클은 SQL 문을 실행하는 가장 효율적인 방법을 선택한다.
    • Cost 비용의 최소화를 위해 테이블 / 인덱스를 분석한다.

MySQL 의 특징

MySQL 의 특징은 다음과 같다.

  • 사용이 타 RDBMS 에 비해 쉽다.
  • 무료로 사용 가능한 GUI Tool 이 많다.
  • Device 에 적은 Overhead 가 가해진다.
  • 버전이 업그레이드됨에 따라 고급 기능을 지원하기 시작했다.

MySQL 과 Oracle DB 는 목적에 맞게 적절한 사용이 필요할 것으로 보인다. 작은 프로젝트나 데이터를 많이 저장하지 않는 시스템의 경우는 MySQL 을 사용하는 편이 좋을 수 있고, 데이터의 사용량이 매우 많고 고도화된 시스템의 경우에는 Oracle DB 를 사용하는 편이 좋을 것으로 생각된다.

 

'Study > Database' 카테고리의 다른 글

[DB] 키의 개념과 종류  (1) 2021.10.08
[DB] 정규화 (Normalization) 란?  (0) 2021.10.08
[DB] DB Index  (0) 2021.10.07
MySQL 8.0  (0) 2021.07.04
반응형

광고 도메인과 광고 시스템에서 사용할 기술들에 대해 공부하다 보니 따로 알고리즘 문제를 풀고 그걸 정리할 시간이 너무 부족해졌다.

이대로 블로그를 방치하면 또 잊혀질 것 같아 지금 공부 중인 내용들을 글로 적고 스스로 정리할 수 있도록 하려 한다.

 

본 내용에 대해서는 내가 들었던 강의 내용과 따로 찾아본 내용들을 조합해서 내가 생각하는 바를 적은 것이므로 실제와 다를 수 있다.

다분히 개인적으로 정리를 위해 적는 내용이라고 생각하면 좋겠다.

 

AdTech 란 뭘까 ?

AdTech 는 Advertising + Technology 의 합성어로, 광고를 위한 기술적인 환경 혹은 생태계 전반을 의미한다.

광고 거래는 Advertiser, Publisher, Audience 의 상호 작용으로 이루어지는데, 이 상호 작용을 기술적으로 어떻게 지원할 것인가에 대한 내용으로 볼 수 있을 것 같다.

 

초기 광고 거래는 Advertiser 가 직접 Publisher 와 계약을 맺고, 어떠한 매체에 광고를 게재하는 방식으로 이루어졌다 한다.

이 때 광고를 게재할 공간을 인벤토리라 한다.

적은 수의 광고주와 매체가 거래하기에는 이러한 Direct Buying 의 형태가 문제가 없었지만, 광고주가 늘어나고 매체 또한 늘어남에 따라 Direct Buying 은 광고주와 매체 모두에 문제를 일으켰다.

 

광고주는 더 많은 매체에 본인의 광고를 게재하고 싶을 것이고, 그러기 위해서 당연히 여러 매체에 광고 게재를 위한 계약을 해야 한다.

매체 또한 다양한 광고를 내보내 수익을 창출해야 하므로, 많은 광고주와 계약을 맺어야 한다.

이 과정에서 어떠한 규약이 정해져 있지 않고 모든 계약을 일일히 하는 것은 불필요한 소모값이라 여겨졌을 것이고,

광고주는 본인의 광고를 알아서 매체에 게재하고 싶고, 매체는 빈 인벤토리에 적절한 광고를 내보내고 싶었을 것이다.

 

DSP, SSP 의 등장 ?

이러한 요구를 충족하는 플랫폼이 DSP 와 SSP 다.

(중간에 광고 서버가 생겨나고, 여러 과정이 있지만 내게 중요한 것은 그게 아니니 넘어가겠다.)

DSP (Demand Side Platform) 는 광고주가 본인의 광고를 등록하고, 관리하기 위한 시스템이라 할 수 있고,

SSP (Supply Side Platform) 은 매체 입장에서 인벤토리에 적절한 광고를 내보내기 위한 시스템이라 볼 수 있다.

 

광고주는 DSP 에 자신의 광고를 등록하고, DSP 가 광고 게재를 하기 위한 인벤토리를 얻는 거래를 대신 수행한다.

이와 유사하게, 매체는 자신의 빈 인벤토리를 채울 광고를 직접 찾지 않고 SSP 가 찾아온(?) 광고를 게재한다.

실제로 광고 거래에 참여하는 것은 DSP, SSP 로 볼 수 있고 광고주와 매체는 이에 대해 따로 신경을 쓰지 않아도 되므로 비용적인 면에서 긍정적이라 볼 수 있다.

 

DSP 와 SSP 의 동작이나 구조에 대해서는 조금 더 공부를 한 후 다시 정리를 해야할 것 같다.

반응형

n 명의 아이들을 의미하는 정수형 배열이 주어졌을 때, 배열에 저장된 값은 해당 위치에 서 있는 아이의 우선순위를 의미한다. 아이들에게 Candy 를 나눠주고자 하는데 모든 아이들은 최소 1개 이상의 Candy 를 받아야 하고 이웃한 아이보다 우선순위가 높은 아이는 이웃 아이보다 Candy 를 더 받아야 한다. 이 때, 아이들에게 최소한의 갯수로 위 규칙을 만족시키며 Candy 를 분배하는 Candy 의 수를 구하는 문제

 

이 문제는, DP 방식으로 문제를 해결할 수 있었는데 우선 각 아이 별로 왼쪽에 있는 아이보다 많이 받는 경우와 오른쪽에 있는 아이보다 많이 받는 경우를 각각 계산했다. 그 후, 둘 중 더 많은 Candy 를 받는 경우를 계산하면 최소한의 Candy 로 규칙을 만족시키며 분배할 수 있다.

 

예를 들어, ratings 배열이 [1, 0, 2] 로 주어졌을 때 Candy 를 가져가는 개수는 [2, 1, 2] 로 총 5개가 필요하게 된다. 왼쪽에 있는 아이보다 많이 받는 경우를 계산하면 [1, 1, 2] 가 되는데 ratings[1] 은 0 이므로 ratings[0] 보다 작아 더 많이 받을 필요가 없고, ratings[2] 는 2 이고 ratings[1] 은 1 이므로 3번째 아이는 2번째 아이보다 Candy 를 많이 받아야 한다. 반대로 오른쪽에 있는 아이보다 많이 받는 경우는 [2, 1, 1] 이 되는데 ratings[0] 의 오른쪽에 ratings[1] 이 더 작으므로 첫 번째 아이가 Candy 를 많이 받게 된다. 두 경우에서 각 아이가 받는 Candy 의 개수는 최대가 되어야 왼쪽과 오른쪽의 경우를 모두 만족할 수 있으므로 결과적으로 [2, 1, 2] 로 Candy 를 분배하게 된다.

 

위와 같은 풀이로 작성한 코드는 다음과 같다.

 

class Solution {
public:
    int candy(vector<int>& ratings) {
        int sum = 0, n = ratings.size();
        vector<int> left(n, 1);
        vector<int> right(n, 1);
        for (int i = 1; i < n; i++) {
            if (ratings[i] > ratings[i - 1]) {
                left[i] = left[i - 1] + 1;
            }
        }
        for (int i = n - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                right[i] = right[i + 1] + 1;
            }
        }
        for (int i = 0; i < n; i++) {
            sum += max(left[i], right[i]);
        }
        return sum;
    }
};

+ Recent posts