Skip to main content

[번역] Docker 컨테이너를 Windows Bash에서 구동하기

Linux를 위한 Windows Subsystem(WSL)1이 Microsoft의 Build 컨퍼런스 2016에서 발표되었을 때, Windows 개발자들에게 새로운 도구의 세계가 열렸습니다. 개인적으로, PowerShell, Bash와 예전의 낡은 cmd까지, 스크립트를 할 때 자유롭게 고를 수 있다는 점을 참 좋아합니다. 그리고 Windows Bash에서 Docker 를 구동하지 못하고 있다는 점은 저를 지금까지도 괴롭게 합니다.

이 글의 원본 제목은 “Windows Bash에서 Docker를 구동하기”였습니다만, 이는 다소 과장되어 있습니다. Docker 는 Windows에서 완전히 완성되지 않은 수많은 시스템 호출에 대한 접근을 필요로 하며, 이로 인해 WSL에서 엔진을 구동하는 것은 아마도 쉽지 않을 것입니다. 대신, 우리는 Docker Engine을 Windows에서 구동하고 이를 Bash에서 연결할 것입니다. 이 또한 PowerShell에서 컨테이너를 시작하고 Bash로 상호작용하거나, 다른 방식을 제공한다는 장점을 갖고 있습니다. 다시 말해서, 당신의 컴퓨터가 단일 머신처럼 느껴질 것입니다.

그 방법을 알아봅시다.

1. Docker를 Windows에서 설치하기

Docker 엔진을 Windows에서 설치하려면, docker.com에 가서 적절한 배포판을 다운로드합니다. 물론, 하드웨어 가상화가 활성화돼있고, Hyper-V가 설치되어 있어야 하며, 그렇지 않으면 엔진이 시작되지 않습니다.

가장 빠른 방법: Windows 10 크리에티터 업데이트 설치

Windows 실행 파일을 Bash에서 실행할 수 있게 되었기 때문에, Windows 10 크리에이터 업데이트에서는 이 과정이 더욱 단순해졌습니다. 그저 아래 두 줄을 .bashsrc에 추가하고 (환경을 다시 로드하면) 끝납니다!

export PATH="$HOME/bin:$HOME/.local/bin:$PATH"
export PATH="$PATH:/mnt/c/Program\ Files/Docker/Docker/resources/bin"
alias docker=docker.exe
alias docker-compose=docker-compose.exe

docker –version을 Bash에서 실행하면, 나머지 글을 읽을 필요도 없습니다. :)

*) Windows 10 크리에이터 업데이트는 2017년 4월 11일에 인사이더에 공개되었으며 현재 유효합니다.

Windows 10 애니버서리 에디션에서 작동하는 법

Docker를 WSL에 설치하기 위해서, 몇 가지 더 많은 단계가 필요합니다. 일부 선택적 단계를 제외하고는 WSL에서도 잘 작동하는, 일반적인 Ubuntu 설치 방법은 여기 적혀 있습니다.

제가 한 방식은 이것입니다:

# Install packages to allow apt to use a repository over HTTPS
$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
# Add Docker's official GPG key
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Set up the repository
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# Update source lists
sudo apt-get update
# Install Docker
sudo apt-get install docker-ce

물론 필요한 바이너리를 다운받고 압축을 푸는 작업, 그리고 그것을 PATH에 넣는 방식의 선택지도 있습니다. 가장 최신 버전에 맞는 방법은 여기 적혀 있습니다.

그 결과는?

Docker 엔진을 Windows와 WSL 양쪽에 설치했지만, 둘 다 구동하진 않았습니다. Windows 인스톨러는 고맙게도 Docker 엔진을 시작할 때 쓰는 Docker 바로 가기를 바탕 화면에 만들어놨습니다. 그리고 docker images를 PowerShell이나 Bash에서 호출할 수 있습니다.

PowerShell:

PS C:\> docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

아직까지 이미지를 아무 것도 만들지 않았지만, 괜찮습니다.

Bash:

$ docker images
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

전혀 만족스럽지 못하군요. 하지만 한 두 가지 과정을 더 거치면, 모두 잘 작동할 것입니다.

2. Windows Docker로 WSL의 Docker 연결하기

docker를 다른 장치의 엔진을 대상으로 구동하는 것은 꽤 쉬운데, Docker가 CLI가 연결될 수 있는 TCP 엔드포인트를 노출할 수 있기 때문입니다.

참고: 글을 처음 공개한지 얼마 되지 않아서 Docker 업데이트를 통해 이 TCP 엔드포인트는 기본적으로 꺼져 있습니다. (Mark님 알려주셔서 감사해요!) 활성화하려면, 작업표시줄에 있는 Docker 아이콘을 우클릭하여, 메뉴에서 설정을 들어갑니다. 그리고 “Expose daemon on tcp://localhost:2375 without TLS” 옵션을 켭니다 (보안 위험성에 유의합니다).

export PATH="$HOME/bin:$HOME/.local/bin:$PATH"
export PATH="$PATH:/mnt/c/Program\ Files/Docker/Docker/resources/bin"
alias docker=docker.exe
alias docker-compose=docker-compose.exe

이렇게 하면, 다음처럼 할 일은 Bash 상의 CLI가 Bash 상에는 없는 엔진 대신에 Windows에서 엔진을 실행하게 됩니다.

$ docker -H tcp://0.0.0.0:2375 images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

훨씬 낫군요!

이 상태를 지속하게 만드는 두 가지 방법이 있습니다. 위 명령을 별명으로 추가하거나, 아니면 더 나은 방법으로(Dave님의 추천), Docker가 호스트 엔진을 찾도록 환경 변수를 만들면 됩니다.

$ echo "export DOCKER_HOST='tcp://0.0.0.0:2375'" >> ~/.bashrc
$ source ~/.bashrc

이제, 도커 명령을 Bash에서 실행하면, 우리가 바라던 대로 작동하게 됩니다.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

미션 성공!


이 글에서 사용한 버전

물론, 이 방법이 사용하는 버전에 따라 되지 않을 수 있습니다. 이 블로그 포스트에서는 다음과 같은 버전을 사용하였습니다.

Windows

Windows 10 Pro Anniversary Edition (Version 1607, OS Build 14393.1066)
Windows 10 Pro Creators Update (Version 1703, OS Build 15063.138)

WSL Ubuntu

14.04.5 LTS

Docker on Windows

17.03.1-ce, build c6d412e

Docker on Ubuntu

17.03.1-ce, build c6d412e

출처: https://blog.jayway.com/2017/04/19/running-docker-on-bash-on-windows/

제로부터 시작하는 Git(형상관리툴) 라이프 1

Git을 써야 하는 이유

형상관리 버전 관리에서 가장 우수하다고 여겨지는 것은 Git이라 할 수 있을 것이다. Git은 다음과 같은 특징이 장점으로 꼽히고 있다.

  1. 파일 단위로 변경 내용을 추적하며, 스테이지 후 커밋-푸시 과정을 거치며 파일 단위로 업로드할 수 있다.
  2. 중앙 서버 중심이 아니다. 분산 저장을 한다.
    • Git은 분명 원격 서버를 갖고 있지만, 서버와 연결되어 있지 않더라도 로컬 커밋까지는 무난하게 할 수 있다. SVN은 원격 서버 연결을 잃으면 일체의 커밋을 할 수 없다.
    • 로컬에 쌓인 커밋을 추후에 푸시하면, 서버와 동기화가 이뤄진다.
  3. 거의 대부분의 경우 충돌을 유연하게 해결할 수 있다.
  4. 소스 보관 및 복제용으로 활용할 수 있다.
    • Github가 git을 활용한 대표적인 공개 서비스로, 여기에 Public으로 올리면 무료로 소스 코드를 공개한 것이며, 누구든지 clone할 수 있다.
    • Git을 Clone하면 저장소의 역사와 내용이 통째로 복사되어 서버 유무와 무관하게 재업로드하여 역사를 이어갈 수 있다.
  5. 커밋이 용량을 크게 더욱 차지하지 않으며, 언제든지 되돌리거나 다른 커밋을 체크아웃할 수 있다.
    • Branch를 분기하여 사람들마다, 혹은 기능마다 나눠서 준비된 것만을 Merge하면 만들다가 만 기능탓에 컴파일을 할 수 없는 불편한 일이 사라진다.
    • 새로운 기능이 문제를 일으키는 것 같으면, 과거의 커밋을 꺼내올 수 있고, 다른 Branch로 갈아탈 수 있다.
    • Checkout을 하면, 로컬의 파일이 모두 변경되는데 그렇다고 커밋했던 기존의 파일이 사라지는 것 또한 아니다. 프로젝트 폴더 내용을 임시폴더처럼 부담없이 변경할 수 있다.

한편, 형상관리 버전 관리를 경험해보지 않은 사람은 “구글 드라이브나 카카오톡으로 압축하여 공유하면 되지”라고 생각하기 쉽다. 이는 다음과 같은 이유로 피해야 한다.

  1. 같은 파일이 다수 난립하여 선후 관계가 혼란스럽다.
    (최종.zip, 최종.zip (1), 최종-진짜.zip이 쌓여간다고 상상해보자. 극혐)
  2. 프로젝트 파일 전체를 압축하고 복사(업로드/다운로드), 해제하는 불필요한 과정으로 시간 낭비과 수고가 심하다.
  3. 매 순간 무엇을 변경하였는지 불투명하다.
  4. 이전에 되던 기능이 망가진 경우, 그 원인을 찾기란 무척 어렵다.
  5. 누군가 안 된다고 호소할 때, 그 사람의 파일이 최신으로 모든 파일 내용이 일치하는지 알 길이 없다.

Git을 쓰기 위한 준비

Windows 환경에서 Git을 쓰기 위해서는 크게 두 가지 유의할 점이 있다.

  • 클라이언트에서의 고민
    • Git을 명령어로 쓰겠는가?
      • Git 바이너리는 분명 명령 프롬프트나 bash 등에서 작동하는 CLI 앱으로, 사용하기에 불편하지만, GUI에 없는 기능을 쓰기 위해서 꼭 존재해야 한다.
      • 일부 GUI Git은 별도로 바이너리를 넣어줄 필요가 있지만, 대체로 GUI만 쓰는 경우 Git 또한 설치할 필요는 없다. 하지만 위 이유로 둘 다 깔면 좋다.
    • Git을 편하게 쓸 GUI를 선택하자.
      • SourceTree가 한글화 지원과 깔끔한 환경으로 널리 쓰이고 있다. 그러나 기능면에서 아쉬운 점이 있다.
      • GitKraken은 본 글에서 소개할 앱으로, 풍부한 기능과 막강한 시각화를 보여주고 있다. 그러나 영문만을 지원하고 있다.
      • TortoiseGit은 탐색기와 결합이 뛰어나나 기능이 많지 않고 직관적이지 못하다.
      • eclipse의 eGit, Visual Studio의 git 등 내부 소스 관리 플러그인을 활용할 수 있다. 하지만 최소한의 기능만을 제공하며 UI도 직관적이지 못해서 git에 대한 오해를 키울 수 있으며, 충돌 등 문제 해결이 어렵거나 불가능한 경우가 있다. 매우 비추천한다.
  • 서버에서의 고민
    • 누구든지 git 바이너리를 이용하여 git server를 셋팅할 수 있다.
    • github와 bitbucket과 같은 웹 git을 이용할 수 있다.
      • github: Public의 경우 무료. Private는 팀원당 7달러 비용
      • bitbucket: Public 무료. Private도 5명 이내인 경우에는 무료.
    • Synology NAS에 git을 깔아 쓰면 SSH 프로토콜로 접속하여 사용할 수 있다.

Git for Windows 다운로드

Linux 환경에서는 기본적으로 깔려있는 경우가 많고(Ubuntu 등), 필요시에도 단순한 명령으로 설치할 수 있다.

Linux Git 다운로드 페이지

Git을 컴퓨터에서 설정하려면

GUI만 쓴다면 필수 사항은 아니지만 git 커맨드 라인의 사전 설정을 해둘 필요가 있다.

우선 위 링크에서 파일 다운로드를 모두 마치고 설치한다. PATH 설정이 적용되기 위해서는 켜져 있는 명령 프롬프트를 모두 종료한 다음 다시 켜고, 필요한 경우 시스템 재시작도 도움이 된다.

다음과 같은 메시지를 보았다면, 경로가 제대로 등록되지 않은 것이다.

> git
'git' is not recognized as an internal or external command,
operable program or batch file.

이렇게 뜨면 성공한 것이다.

> git
usage: git [--version] [--help] [-C ] [-c name=value]
           [--exec-path[=]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=] [--work-tree=] [--namespace=]
            []

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
   clone      Clone a repository into a new directory
   init       Create an empty Git repository or reinitialize an existing one

work on the current change (see also: git help everyday)
   add        Add file contents to the index
   mv         Move or rename a file, a directory, or a symlink
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index

examine the history and state (see also: git help revisions)
   bisect     Use binary search to find the commit that introduced a bug
   grep       Print lines matching a pattern
   log        Show commit logs
   show       Show various types of objects
   status     Show the working tree status

grow, mark and tweak your common history
   branch     List, create, or delete branches
   checkout   Switch branches or restore working tree files
   commit     Record changes to the repository
   diff       Show changes between commits, commit and working tree, etc
   merge      Join two or more development histories together
   rebase     Reapply commits on top of another base tip
   tag        Create, list, delete or verify a tag object signed with GPG

collaborate (see also: git help workflows)
   fetch      Download objects and refs from another repository
   pull       Fetch from and integrate with another repository or a local branch
   push       Update remote refs along with associated objects

'git help -a' and 'git help -g' list available subcommands and some
concept guides. See 'git help ' or 'git help '
to read about a specific subcommand or concept.

이제 기본 사용자 설정을 해보자. 아래 명령 한 번만 내려주면 커맨드 라인에서 git commit시 항상 먼저 설정된다.

> git config --global user.name "My Name"
> git config --global user.email [email protected]

한 번 쓰면 계속 쓰게 되는 GitKraken

나머지 기능은 이어서 적어보도록 하겠습니다.

알고리즘 탐구 – 인접한 원소의 위치 구하기

문제

U < V < W 또는 U > V > W일 때, 정수 V는 U와 W 사이에 있다.

비어 있지 않은 배열 A는 주어진 N개의 정수로 이뤄져 있는데, 숫자의 인덱스 (P, Q) 짝은 0 ≤ P < Q < N인 인접한 수가 A[P]와 A[Q] 사이에 없으며, A[P]≠A[Q]임을 나타낸다. 예를 들어, 배열 A에서는:

A[0] = 0
A[1] = 3
A[2] = 3
A[3] = 7
A[4] = 5
A[5] = 3
A[6] = 11
A[7] = 1

다음 인덱스 짝은 인접한 값을 갖고 있다.

(0,7), (1,4), (1,7), (2,4), (2,7), (3,4), (3,6), (4,5), (5,7)

예를 들어, 인덱스 4와 5는 인접한 값을 갖고 있는데, 왜냐하면 A[4] = 5와 A[5] = 3는 다르며, 배열 A에는 그 사이에 들어갈 값이 없다는 것이다. 즉, 숫자 4만이 사이에 들어갈 수 있으나 배열에 존재하지 않는다.

주어진 두 인덱스 P와 Q의 거리는 X ≥ 0에서는 abs(X) = X, X < 0에서는 abs(X) = -X일 때  abs(P-Q)로 정의된다. 예를 들어, 인덱스 4와 5 사이 거리는 1인데, 그 이유는 abs(4-5) = (5-4) = 1이기 때문이다.

함수를 작성하라:

class Solution { public int solution{int[] A); }

주어진 비어 있지 않은 배열 A는 N개의 정수로 이루어져 있으며, 인접한 값을 가진 배열의 가장 긴 거리를 반환한다. 이 함수는 인접한 인덱스가 없는 경우 -1을 반환해야 한다.

예를 들어, 주어진 배열 A는 다음과 같다:

A[0] = 1
A[1] = 4
A[2] = 7
A[3] = 3
A[4] = 3
A[5] = 5

이 함수는 다음 이유로 4를 반환해야 한다:

  • 인덱스 0과 4는 인접해있는데, 그 이유는 A[0] ≠ A[4]이며 배열이 A[0] = 1과 A[4] = 3 사이의 값을 갖고 있지 않기 때문이다.
  • 이들 인덱스의 거리는 abs(0-4) = 4이다.
  • 더 큰 수의 거리를 지닌 다른 인접한 인덱스 짝이 없다.

다음과 같이 가정한다:

  • N은 [1..40,000] 범위 내에 있다.
  • 배열 A의 각 요소는 정수이며, 범위 [-2,147,483,648..2,147,483,647] 내에 있다.

복잡도:

  • 기대되는 최악의 경우 시간 복잡도는 O(N*log(N))이다.
  • 기대되는 최악의 공간 복잡도는 O(N)이며 입력 공간 이후를 말한다 (입력 기호에 필요한 공간은 포함하지 않는다)

발상

  • 왼쪽부터 찾아서 그 값의 다음 인접한 수를 찾는 식으로 반복할까?
    • N개의 항목에 대해 반복하면서 N-1개의 반복을 다시 해야만 한다.
    • 더 좋은 방법이 있을 것이다.
  • 소트를 먼저 한 다음에 낮은 수부터 올라가면서 맞춰볼까?
    • 소트 알고리즘은 검증되어 있는 내부 라이브러리를 활용하면 더 좋을 것이다.
    • 같은 수를 건너뛰면 반복문이 한층 더 빠를 것이다.
    • 하지만 정렬하면 원래의 위치를 잃어버리잖아?
      • 원래의 위치는 왼쪽부터 차례로 원시적인 방법으로 찾으면 된다.
      • 찾는 순간 루프를 탈출하면 속도는 더욱 빠를 것이다.

풀이

import java.util.ArrayList;
import java.util.Arrays;

public class Question {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//int[] A = new int[] {0,3,3,7,5,3,11,1};
		//int[] A = new int[] {1,4,7,3,3,5};
		//int[] A = new int[] {1,1,1,1,1,1,1,1};
		
		//랜덤한 40000개의 int를 넣는 부분
		int[] A = new int[40000];
		for(int i = 0; i < A.length; i++) {
			A[i]=(int)Math.round(Math.random()*2147483647*2-2147483647);
		}
		
		//시간 계산 시작
		long startTime = System.nanoTime();
		System.out.println("Result: "+solution(A));
		System.out.println("Elapsed Time: "+(System.nanoTime()-startTime)/1000000.0+"ms");
	}
	
	private static int indexOfArray(int[] A, int val, boolean reverse) {
		if(reverse) {
			//뒤에서 찾기
			for(int i = A.length-1; i >= 0; i--) {
				if(A[i]==val) {
					return i;
				}
			}
		} else {
			//앞에서 찾기
			for(int i = 0; i < A.length; i++) {
				if(A[i]==val) {
					return i;
				}
			}
		}
		return -1;
	}
	
	private static int findPairDistance(int[] A, int min, int max) {
		//왼쪽 오른쪽 각각 min, max 검색
		int aleft = indexOfArray(A,min,false);
		int aright = indexOfArray(A,min,true);
		int bleft = indexOfArray(A,max,false);
		int bright = indexOfArray(A,max,true);
		return Math.max(Math.abs(aleft-bright),Math.abs(aright-bleft));
	}
	
	public static int solution(int[] A) {
		//소트 후 중복 제거
		int[] sorted = A.clone();
		Arrays.sort(sorted);
		/*for(int i = 0; i < sorted.length; i++) {
			System.out.print(sorted[i]+",");
		}*/
		//ArrayList alSel = new ArrayList<>();
		int max = -1;
		for(int i = 1;i < sorted.length; i++) {
			//전항과 현재항의 차이
			int cha = sorted[i]-sorted[i-1];
			if(cha >= 1) { //차이가 1 이상이면 정수 변화로 보고 계산
				//alSel.add(sorted[i-1]);
				//findPairDistance(A,A[i-1],A[i]);
				max = Math.max(max, findPairDistance(A,sorted[i-1],sorted[i]));
				//두 값에 대한 좌우 검색 최대 거리를 구한 다음 max보다 클 때만 기록
				//System.out.println(String.format("값: (%d,%d), 거리: %d",sorted[i-1],sorted[i],findPairDistance(A,sorted[i-1],sorted[i])));
			}
		}
		
		
		return max;
	}

}

SQL 뷰(View) 소개

뷰란, CREATE TABLE로 정의된 실제 테이블로부터 작성되는 가상 테이블을 말합니다. 뷰는 그저 가상 테이블일 뿐이므로, 내부의 데이터는 존재하지 않습니다. 뷰는 실제 테이블을 어떻게 보여줄까를 정의한 것이라고 볼 수 있습니다.

이미 사용하고 있습니다만, CREATE TABLE에서 정의된, 데이터가 들어 있는 테이블을 실제 테이블이라고 하며, 이 실제 테이블에서 만들어지는 가상 테이블을 뷰라고 부릅니다.

뷰의 장점

뷰의 실체는 SELECT 문에 의한 쿼리를 정의한 것입니다. 뷰에 접근하면, 정의된 쿼리가 실행되며, 실제 테이블에서 필요한 데이터가 나타납니다. 또한, 뷰에서 뷰를 정의하는 것도 가능합니다. 그러므로 미리 매번 입력하는 것이 귀찮고 복잡한 쿼리를 한 번 뷰로 정의해두면, 유저와 프로그램에서는 단순한 쿼리를 실행하는 것으로 해결됩니다.

이러한 개발 노력의 경감이라고 하는 관점 이외에, 보안면에서도 장점이 있습니다. 예를 들어, 실제 테이블의 데이터 속에 일반 유저에게 보이고 싶지 않은 것이 있는 경우, 실제 데이터에 액세스 권한을 일반 유저에게 제공하는 것은 불가합니다. 그러나 보이고 싶지 않은 데이터를 제외한 뷰를 정의하는 것으로, 일반 유저에게도 실제 테이블의 데이터를 이용하게 할 수 있게 됩니다.

뷰의 작성

뷰를 작성하기 위해서 CREATE VIEW 문을 이용합니다. 기본 구조는 다음과 같습니다.

CREATE VIEW 뷰 이름 [(칼럼명, 칼럼명, .....)] AS
SELECT文
[WITH CHECK OPTION];

뷰 이름 이후에는, 추출되는 데이터의 칼럼명을 기술합니다. 칼럼명을 생략한 경우, SELECT 문에서 지정한 칼럼의 이름이 그대로 사용됩니다. SELECT 문에서 연산자를 사용한 경우와 미리 칼럼명을 지정한 경우에 명시적으로 기술하는 것입니다.

뷰 이름과 칼럼명 다음에는, AS에 이어서 SELECT 문에 의한 쿼리를 기술합니다. 이 쿼리 결과가 이 뷰의 데이터라는 것입니다. [WITH CHECK OPTION]은 뷰 갱신에 관련되는 옵션입니다. 뷰의 갱신에 대해서는 아래에서 설명합니다.

이 문장의 SQL 샘플에서 앞장까지 쓰이고 있던 수주표, 고객표, 상품표를 실제 테이블로 사용합니다. sample.21-1에서 v_수주라고 하는 이름의 뷰를 정의하고, 마지막에 뷰의 내용을 확인하고 있습니다.

/* 뷰의 작성 */
CREATE VIEW v_수주 AS
SELECT JJ.수주번호, KK.고객이름, SS.상품명,
JJ.수주개수, JJ.납품일
FROM 수주표 JJ, 고객표 KK, 상품표 SS
WHERE JJ.고객코드 = KK.고객코드
AND JJ.상품코드 = SS.상품코드;
 
/* 확인 */
SELECT JJ.수주번호, KK.고객이름, SS.상품명,
JJ.수주개수, JJ.납품일
FROM 수주표 JJ, 고객표 KK, 상품표 SS
WHERE JJ.고객코드 = KK.고객코드
AND JJ.상품코드 = SS.상품코드;

정의한 뷰에서 특정 행과 열을 출력할 수 있습니다. sample.21-2는 정의한 v_수주에서, 수주개수가 100 이상인 경우를 선택하여, 그 고객 이름과 상품명 및 수주 개수를 출력하는 것입니다.
실행결과

고객명 상품명 수용자수
──────────── ────── ───────
KUROKIYA JUICE 300
ONSIDE BEER 200
KUSHINANA BEER 150
ONSIDE WINE 110
KUROKIYA TEA 250
KUSHINANA BEER 135
KUROKIYA BEER 290
KUSHINANA BEER 175

표준규격에 대해서

표준 SQL 규격에 대해서는, SQL89부터 가능합니다. SQL92에서 CHECK OPTION, LOCAL, CASCADE의 기능 확장이 행해집니다. SQL99에서 더욱 기능 강화가 이뤄져서, 일정 조건 하에서 뷰에서 실제 표의 데이터 갱신이 가능해졌습니다. 또한 SQL89에서 뷰를 작성할 수 있는 한편, DROP 스테이트먼트가 없는 탓에 삭제할 수 없습니다.

뷰의 삭제

뷰 삭제를 할 때는, 다음과 같이 SQL문을 기술합니다. (DROP 스테이트먼트 상세)

DROP VIEW 뷰 이름;

실습 과제

  1. 다음 테이블로 이하 조건에 맞는 쿼리를 만들어봅시다.
  • 이름을 하나의 칼럼으로 만들어서 fullname으로 지정
  • Birthdate가 2001-09-01보다 이전인 경우만 표시
id first_name last_name email birthdate added
1 Bonnie Medhurst [email protected] 1999-07-26 1982-05-01 21:32:19
2 Vincenza Streich [email protected] 2006-01-30 2000-07-15 18:19:18
3 Carter Kilback do’[email protected] 1998-12-07 1998-08-14 06:13:52
4 Mariano Stroman [email protected] 1996-06-18 2008-04-06 14:43:43
5 Deondre Kerluke [email protected] 1994-04-10 2008-06-26 22:02:19
6 Gia Towne [email protected] 1988-07-13 1982-03-22 03:16:39
7 Margarett Beahan [email protected] 2008-01-22 2010-09-12 08:59:33
8 Gilda Brekke [email protected] 1981-09-18 2016-04-14 01:17:38
9 Zackary Cummerata [email protected] 2001-05-27 2003-05-23 21:18:54
10 Kory Wiegand [email protected] 2010-03-16 1992-03-22 04:14:31
11 Vinnie Zboncak [email protected] 2016-06-23 2014-12-29 20:55:25
12 Carmella Bogan [email protected] 1978-06-10 1993-01-17 08:43:08
13 Vance Rice [email protected] 1996-10-09 1999-09-14 15:27:08
14 Coleman Maggio [email protected] 1999-11-22 2001-05-01 05:42:36
15 Patricia Zieme [email protected] 1978-11-18 1987-07-21 18:44:25
16 Jada Beer [email protected] 1991-07-17 1997-10-08 09:41:57
17 Kianna Torphy [email protected] 1994-03-17 2011-11-20 20:15:40
18 Maegan Harvey [email protected] 1979-07-18 2010-10-06 20:52:03
19 Winona Welch [email protected] 1974-10-28 2010-09-02 22:05:57
20 Queen Mosciski [email protected] 1983-05-23 1985-10-09 08:51:49

CREATE VIEW scit_view AS
SELECT (first_name || last_name) AS fullname, email
FROM scit_user
WHERE birthdate < to_date('2001-09-01','YYYY-MM-DD');

SELECT fullname, email FROM scit_view;
  1. WHERE에 지정된 조건에 맞는 아이템이 원래 테이블에서 변경되면, 뷰 결과는 어떻게 됩니까?
  2. Oracle을 포함하여, 최근 데이터베이스 시스템에서 INSERT, UPDATE, DELETE가 가능합니다만, 이러한 DML 조작이 불가능한 경우를 생각해봅시다.

 

이 본문은 Techscore 원문을 가공하여 발표를 위해 준비한 자료입니다.

excercise1

짧게 풀어보는 Java 급 테스트

가뜩이나 환절기에 콧물 시큰시큰이라 머리가 띵한데 Java 실력 체크를 위한 시험을 보게 되었습니다.

다들 풀 수 있는 수준으로 나온다고 하지만, 모두에게 그러리라는 법은 없기 때문에, 넉넉한 시간에도 불구하고 끙끙대시는 분들이 많았습니다.

문제는 총 8문제였습니다.

Java 문제 1. 일의 자리를 1로 바꾸는 코드를 작성하라.

문제 1

public class Exercise1 {

	public static void main(String[] args) {
		int num = 333;
		int num2 = (int)Math.round((double)(Math.floor((float)num*0.1f)))*10+1;
		System.out.println(num2);
	}

}

사실 num / 10 * 10이 훨씬 쉽긴 합니다만, 나름 이유가 있어서라고 생각했는데… 풀고나니 참 쓸데 없는 짓을 했구나 싶은 부분입니다.

어떤 분은 String으로 바꾸고 치환하고 Integer.parseInt() 했다고 하시네요. 아… 제가 머리가 굳었나봅니다. 세상은 참신한 방법이 널리고 널렸어요.

Read More

spring

[번역글] Spring MVC 모델과 세션 애트리뷰트의 이해

자바 웹 애플리케이션 개발자로서, 여러분은 요청 (HttpServletRequest)과 세션 (HttpSession) 범위를 바로 배우셨을 겁니다. 이들 범위와 데이터, 객체 다루기를 이해하는 것은자바에서 웹 애플리케이션을 디자인하고 빌드하는데 중요한 요소입니다. [리퀘스트와 세션의 범위에 대해서는 스택 오버플로우 게시물을 참조하면 빠르게 배울 수 있습니다]

Spring MVC 범위

Spring MVC에서 웹 애플리케이션을 시작했을 때, Spring 모델과 세션 애트리뷰트는 이해하기 어려웠습니다. 특히, HTTP 리퀘스트와 세션 범위, 거기서 애트리뷰트에 관해서 말입니다. Spring 모델 요소는 세션이나 요청에서 똑같이 나타날까요? 그렇다면, 어떻게 제어할까요? 이 글에서, Spring의 MVC 모델과 세션이 동작하는 것을 파헤치도록 하겠습니다.

Read More

프로그래밍이란?

사람이 프로그래밍 언어로 명령하여 컴퓨터를 기동하는 기술

하나 이상의 추상 알고리즘을 특정 프로그래밍 언어를 사용하여, 상세한 컴퓨터 프로그래밍으로 실체화하는 기술을 말한다.

소스 코드 → 컴파일러 → 기계어

JAVA의 탄생 배경

  • 1991년 Sun사에서 제임스 고슬린을 중심으로 가전제품에 사용하기 위한 언어의 제작
  • 특정 CPU에 의존하지 않기 위해 가상 머신을 사용하게 됨
  • 넷 발달과 함께 웹에 사용할 수 있는 언어가 되었다.

프로그램의 기초

프로그램이란

컴퓨터가 범용적인 기계가 된 것은 바로 프로그램(program) 때문이다. 프로그램은 컴퓨터를 위한 작업 지시서로서, 구체적으로 컴퓨터가 특정한 작업을 하기 위하 명령어의 리스트이다. 명령어란 CPU가 수행하는 기초적인 연산이다.

프로그래밍 언어

  • 소스 코드(source code): 원하는 작업을 텍스트로 기술한 것
  • 소스 파일(source file): 소스 코드가 파일에 저장된 것
  • 오브젝트 파일(object file): 컴파일러가 기계어로 변환하여 파일에 저장한 것