List, Map, Set - Collection

JAVA 2015. 8. 29. 16:00

리스트, 맵, 셋은 콜렉션 클래스를 상속받은 클래스들이다.

 

List 

- 수집 순서가 있음

- 동일한 데이터에 대한 중복 입력이 가능

- 순차적인 대량의 데이터를 액세스하거나 입력할 때 유리한 방식

List분류
 
ArrayList
 
- capacity는 수용할 수 있는 데이터의 개수를 의미
 
- 데이터가 늘어나게 되면 capacity가 동적으로 확장됨.

- 크기를 지정하지 않으면 capacity는 기본 10이다.
- 데이터를 10개 이상 사용한다면 무조건 10보다는 크게 잡아놔야 된다. 그래야
동적으로 capacity가 늘어나면서 수행되는 오버헤드를 줄일 수 있다.
- 데이터의 삽입, 삭제가 좋지 않다.(배열들을 뒤로 밀거나 당겨야 하므로)
 
Vector
- ArrayList와 거의 동일. 다만 StringBuilder와 StringBuffer의 
차이처럼 동기화를 지원하느냐 하지 않느냐의 차이
 
LinkedList
- capacity의 개념이 없다.
 
- 데이터를 삽입할 때는 주소값만 연결하면 되므로 고정된 크기의 연속된 집합인 
ArrayList에 비해 삽입 삭제가 용이
 
- 검색 할 때는 처음부터 순차적으로 접근해야 하므로 속도가 느리다.
 
 

cs


Map

Key & Value 형태의 자료구조

- 수집의 순서를 기억하지 않음

- 동일한 키값을 중복하여 입력 할 수 없음


Set

- 중복데이터의 입력을 불허

- 순서가 없다.

- 중복되지 않은 수(데이터)를 구할 때 용이하다.

- 집합의 개념

'JAVA' 카테고리의 다른 글

Java finalize  (0) 2015.10.26
Call By Value vs Call By Reference  (0) 2015.09.14
자바 8 특징  (0) 2015.08.29
volatile 키워드 vs synchronized 키워드  (0) 2015.08.29
인스턴스 메소드 vs 클래스(스태틱) 메소드  (0) 2015.08.25
Posted by slender ankles
,

자바 8 특징

JAVA 2015. 8. 29. 15:58

자바 8의 특징은 무엇인가?

1) 람다식의 출현

람다식을 간략히 정리하면 변수에 로직을 대입하는 것을 말한다.


2) foreach 메소드의 등장

foreach는 자바스크립트에서 보았듯이 객체를 전달하여 index를 지정하여 iteration하는 것이 아니라 array나 list등을 전달하여 자동적으로 순회하게끔 하는 것이다. 



[참고]JIT컴파일러란 무엇인가?

Just In Time 컴파일러라는 뜻으로 인터프리터의 장점과 컴파일러의 장점을 모두 활용하여 사용하는 것입니다. 일부는 컴파일된 기계어를 만들고, 일부는 바이트 코드를 해석하는 것을 통해 번역속도와 실행속도의 장점을 취하는 방법입니다.

[참고] 컴파일러 vs 인터프리터

컴파일러는 번역속도가 느린 대신에 실행 속도가 빠르고 (전체를 기계어로 번역해놓기 때문에 실행속도가 빠름)

인터프리터는 번역속도가 빠른 대신에 실행 속도가 느리다.(번역한 코드를 한줄한줄 해석하여 실행하기 때문)


람다식

람다식은 무엇인가? 

변수에 로직을 대입할 수 있는 문법을 말한다. 기존의 익명함수의 사용을 보완하여 더 간결하고 가독성 좋은 코드를 만들 수 있다. 

람다식을 이해해보자.

참조 : http://jinson.tistory.com/208

위의 참조에서 좋은 글귀를 보고 나름대로 이해하고 해석해서 다시 재작성해본다. 

람다식이 필요한 이유를 다음과 같이 설명해주고 있다. 

우선 리스트와 리스트의 모든 원소를 이터레이션하는 코드를 작성해보자.

1
2
3
4
5
List<Integer> numbers = Arrays.asList(123456); 
 
for (int number : numbers) {
    System.out.println(number);
}
cs

우리는 이러한 리스트를 순회할 때 간단히 for문을 통해서 로직을 수행하는데 여기에 숨겨진 깊은 뜻이 있다고 한다. 

딸과 함께 거실에 떨어져있는 장난감을 주울려고 한다. 

나: "소피아, 장난감 정리하자. 땅에 어떤 장난감이 있지?"

소피아: "어. 공이 있네"

나: "그래. 공을 박스에 넣자. 땅에 또 뭐가 있지?"

소피아: "어. 인형이 있지"

나: "그래. 인형을 박스에 넣자. 땅에 또 뭐가 있지?"

소피아: "어. 책이 있네"

나: "그래. 책을 박스에 넣자. 땅에 또 뭐가 있지?"

소피아: "아니. 아무것도 없어"

나: "잘했네. 이제 다 했다"

사실 바닥에 있는 장난감을 주워라고 한 마디로도 이해하고 실행할 수 있는 것이 사람이지만 실제로 다음과 같은 과정이 가지고 오는 이점 또한 있다. 소피아는 양손에 장난감을 들어 박스에 넣을 수도 있고, 박스로부터 가벼운 것부터 나를 수도 있을 것이라는 것이다. 즉 내부 이터레이션을 수행 할 수 있다는 것이다. 즉 JIT컴파일러가 내부적으로 병렬화하여 원소 처리를 최적화해서 처리할 수도 있다는 말이다. 


다음의 예를 보자.

자바 8 이전에는 내부이터레이션을 사용하기 위해서는 이름 없는 내부클래스를 만들어야 했다. 

1
2
3
4
5
numbers.forEach(new Consumer<Integer>() {
    public void accept(Integer value) {
        System.out.println(value);
    }
});
cs

반복문을 순회하면서 새로이 만들어진 consumer객체의 accept를 정의하여 호출하고 있다.

위의 코드를 자바 8에서의 람다식을 이용해서는 다음과 같이 처리할 수 있다. 


1
numbers.forEach((Integer value) -> System.out.println(value));
cs


화살표의 왼쪽은 매개 변수 목록이고, 오른쪽은 몸체이다. 컴파일러는 내부적으로 람다식을 분석하여 Consumer클래스의 미구현된 메소드(즉, accept 메소드)와 동일한 타입인지 검사하여 람다식을 마치 consumer인터페이스를 구현한 클래스인 것처럼 활용한다. 

내부적으로 accept인지를 분석한다고 했으므로 컴파일러는 분석능력이 있는 것이다. 다음과 같이 인자를 생략해도 가능하다고 한다. 

1
numbers.forEach(value -> System.out.println(value));    // 식(1)
cs

이 문장 역시도 더 줄일 수 있다. 자바 8에서 새로이 등장할 메소드 참조(method reference)를 활용하면

더 간단하게 만들 수도 있다. 자바 8에서 도입될 :: 구문을 활용하여 다음과 같이 정적 메소드나 인스턴스 메소드를 참조할 수 있다. 

1
numbers.forEach(System.out::println);  // 식(2)

cs


람다식은 왜 필요한가?

간단히 말하면 익명함수를 사용할 것이라면, 복잡하지 않게 간결함을 제공해주겠다는 것이 그 필요 이유라고 할 수 있다.


Map의 HashCollision 처리 변화

Java 8에서도 역시 해시맵의 충돌을 Seperate Chaining 방식을 통해 해결한다. 하지만 이전과 다르게 해시충돌이 일어난 리스트의 개수가 8개 이상이 되면 링크드 리스트가 아닌 트리로 바꾼다. 그리고 6개까지 줄어들면 다시 링크드 리스트로 바꾼다.

왜 하나의 수를 경계로 삼지 않고 해시충돌의 수를 8개, 6개로 하는가 하면 데이터의 수가 하나를 경계로 왔다갔다할 때는 리스트에서 트리로 바꾸거나 트리에서 리스트로 바꾸는 오버헤드가 증가하기 때문에 이렇게 로직을 구성한다.








Posted by slender ankles
,

volatile과 synchronized 키워드. 무엇을 하는 녀석들인가?


volatile과 synchronized 키워드 멀티스레드 환경에서 읽고, 쓰기에 대해서 원자성을 보장해주는 동기화 도구입니다. 


그렇다면 두 키워드의 차이는 무엇인가?


차이점을 간략히 한 줄로 설명하자면, volatile은 변수에 한해서만 동기화를 해주는 도구이며, synchronized는 작업에 대해서 동기화를 지원해주는 도구입니다.

한줄만으로는 이해하기 힘들것이므로 가볍게 예를 하나 들어보겠습니다. 

long stat = 324L;

위와 같은 변수 선언에서의 stat에 대한 volatile키워드는 stat에 대해서 서로 다른 스레드로부터 읽고 쓰기에 대한 원자성을 보장해줍니다. 스레드 A, 스레드 B가 읽고 쓰면서 같은 변수에 대해서 다른 값을 읽어가는 것을 방지해주죠.

int value = stat + 10;

위와 같은 경우가 조금 다릅니다. 

내부적으로 JVM은 value 변수를 읽어오고, stat 변수를 읽어오며, 10을 더하는 동작이 분리되어 있습니다. 이 같은 경우 어떤 스레드가 stat에 10이 더해진 변수 value를 읽어 갈 수도 있고, 그렇지 않을 수도 있다는 것입니다. 


하지만 synchronized키워드는 작업 자체에 대해 원자성을 보장해주는 도구이므로 이 같은 문제를 해결 할 수 있습니다. 

이 것이 synchronized와 volatile키워드의 차이인 것입니다. 


'JAVA' 카테고리의 다른 글

List, Map, Set - Collection  (0) 2015.08.29
자바 8 특징  (0) 2015.08.29
인스턴스 메소드 vs 클래스(스태틱) 메소드  (0) 2015.08.25
자바 Null Pointer Exception막는 방법  (0) 2015.08.18
자바 제네릭(Generic)이란?  (0) 2015.08.06
Posted by slender ankles
,


'JAVA' 카테고리의 다른 글

자바 8 특징  (0) 2015.08.29
volatile 키워드 vs synchronized 키워드  (0) 2015.08.29
자바 Null Pointer Exception막는 방법  (0) 2015.08.18
자바 제네릭(Generic)이란?  (0) 2015.08.06
자바 리플랙션(Reflection) API  (0) 2015.08.05
Posted by slender ankles
,

어떻게 구해야 하나 고민을 쫌 했는데 이리저리 생각해보다가

너무 작게 생각하지 않고 전체 게임에서 도출 해 낼 수 있는 점수와 실제 팀들이 받은 점수들을 비교하면 답을 구할 수 있을 것 같았다. 


조금 더 자세히 설명해보자면

이기면 3점, 비기면 1점, 지면 0점의 스코어를 각 팀들이 가져간다고 했다. 

경기는 두 개의 팀이 있어야만 이루어지는 것이다. 그렇다면 한 경기에서 

이기거나 지는 경기에서는 두 팀 중 어느 한팀이 3점을 반드시 가져가게 된다. 

하지만 비기게되면? 두 팀은 각자 1점씩을 가져가게 되어 2점이 발생하게 된다. 

대회 주최측 입장이라면 이기거나 지는 게임은 3점, 비기는 게임은 원래 발생할 수 있는 점수에서 1점이 부족하게 발생한다. 


모든 경기의 수에서 3점을 곱해준 값은 대회측에서 모든 경기에서 발생할 수 있는 승점을 의미하며, 

모든 경기에서의 승점 - 실제 각 팀들의 점수들의 합 = 예상치에서 손실된 점수(비긴 경기의 승점)

을 의미한다. 한 개의 비긴 경기는 이기거나 진 경기와 1점 차이가 나므로 

위의 계산 값이 비긴 경기의 수를 의미한다. 


설명을 잘 못해서 쉬운 문제를 어렵게 설명한 듯하지만 실제로는 간단하게 풀 수 있는 문제다. 


'알고리즘문제풀이' 카테고리의 다른 글

더블릿_rprime  (0) 2015.08.20
2591_숫자카드  (0) 2015.05.01
2564_경비원  (0) 2015.04.30
2565_전깃줄  (0) 2015.04.29
2505_두번뒤집기  (0) 2015.04.28
Posted by slender ankles
,

서로 소라는 단어에 대해서 로직을 생각해내는 것이 핵심인 문제 같다. 

더 좋은 방법이 있을 수도 있지만(서로소의 성질을 이용해서 답을 도출해내는 등등)

나는 단순하고 무식하게 풀었다. 


두 숫자 input_a, input_b가 있다면

1) 두 숫자 중에 더 작은 수를 찾아냈다.

=> 작은 숫자의 약수를 구하는 이유는 작은 숫자가 큰 숫자보다 for문을 조금이라도 덜 돌수있기때문이다. 큰상관은 없다.

2) 1부터 작은 수까지 for문을 돌면서 작은 수의 약수를 모두 구해서 배열에 담아 두었다. 

3) 큰 숫자를 구해진 작은 수의 약수들로 나누어보아서 나누어지면 두 수는 서로소가 아니다.

어느 숫자로도 나누어지지 않으면 두 수는 서로소이다. 

물론 구해진 약수 중 1은 제외이다. 1은 어느 숫자라도 약수로 가지기 때문이다.


답이 제대로 나온다. 

이렇게 1000까지는 다소 후한 제약조건이 있는 경우에는 위와 같은 방법으로도 충분히 풀 수 있으므로 

크게 고민 할 필요가 없다. 

다만 숫자가 커지거나 하면 다른 방법을 생각해봐야 한다.  

'알고리즘문제풀이' 카테고리의 다른 글

더블릿_worldcup  (0) 2015.08.20
2591_숫자카드  (0) 2015.05.01
2564_경비원  (0) 2015.04.30
2565_전깃줄  (0) 2015.04.29
2505_두번뒤집기  (0) 2015.04.28
Posted by slender ankles
,

자바 Null Pointer Exception막는 방법

참조 : http://www.jpstory.net/2014/02/avoid-nullpointerexception/


NPE, Null Pointer Exception 이란?

Null값 때문에 발생하는 Runtime Exception입니다. 

null인 객체에 접근하여 발생하는 예외도 있지만, 그 값이 모호한 경우에 다양한 버그를 만들어냅니다.

예를 들어, 메소드의 호출결과로 null이 반환되었다면 데이터가 없는 것인지, 아니면 메소드의 로직이 실패한 것인지를 정확히 판단하기 힘듭니다. 

어떤 특정한 상황에서 개발자가 일부러 null값을 집어넣을 수도 있기 때문에 null값이 반드시 에러다. 라고는 말할 수 없습니다.

어쨌든 이러한 애매모호한 런타임에러는 디버깅하기 힘들기 때문에, 코드를 작성 할 때 신중히 작성할 필요가 있습니다.

매번 느끼지만 고민을 많이하는 개발자만큼 능력있는 개발자는 없는 것 같습니다. 시간에 쫓기거나 하면서 코딩하는 것이 

얼마나 좋지 않은 것인지에 대해서 매번 깨닫습니다.


Null Pointer Exception을 예방하는 코딩습관에 대해서 설명합니다. 

1) Equals 메소드 사용시

문자열 비교시 non-null String 기준으로 비교합니다. 

equals 메소드는 symmetric하므로 a.equals(b)와 b.equals(a)가 동일합니다. 

절대 널이 발생하지 않는 문자열이 있다면 이를 주 객체로 지정해주는 것이 좋습니다. 


2) toString()보다는 valueOf()를 사용할 것

3) 메소드에서 return null을 사용하지 않기


4) null을 파라미터로 넘기지 말 것


5) 불필요한 autoboxing, unautoboxing 피하기 & Object보다는 기본형 사용하기

6) chaining 메소드 호출 자제하기


Library를 통해서 null pointer exception을 처리해주는 방법

이 사실 더 좋은 방법이라고 생각합니다. 

Apache Commons lang, Google Guava(예전 Google Collections) 등 null safe한 method를 이용하는 방법입니다.

1) Apache Commons의 StringUtils

String의 null 체크를 간단히 할 때 많이 사용하는 클래스입니다. StringUtils.isNotEmpty(), isBlank(), isNumeric(), isWhiteSpace() 등이 있죠.



2) Guava의 Optional 클래스 이용하기

Optional는 nullable한 T를 non-null 값으로 대체시키기 위한 방법인데요. (말이 어렵죠?)
Optional 객체는 non-null인 T reference를 포함하거나 아무것도 포함하고 있지 않습니다.

한마디로 Optional 객체는 명시적으로 null 값을 갖지 않는다는거죠.
NullObject Pattern을 일반화시켰다고나 할까요? 바로 이 점을 이용해서 NPE를 예방합니다.

– absent : 아무 것도 포함하고 있지 않은 상태
– present : non-null 값을 갖은 상태

1) Optional 객체의 생성 (static 메소드)

Optional.of(T)
– T로 받은 non-null 값을 포함하는 Optional 객체 반환, T가 null 일 경우 NPE 발생
Optional.absent()
– 아무것도 포함하고 있지 않는 absent Optional 객체 반환
Optional.fromNullable(T)
– T로 받은 값이 non-null일 경우 present로, null일 경우 absent로 처리한 Optional 객체 반환

2) Optional 객체를 다루기 위한 메소드

boolean isPresent()
– Optional 객체가 non-null 인스턴스를 포함할 경우 true 반환
T get()
– Optional 객체가 present 일 경우 포함하고 있는 인스턴스를 반환, absent일 경우 IllegalStateException 발생
T or(T)
– Optional 객체의 present 값을 반환. 만일 값이 없을 경우 명시한 T를 반환 (기본값)
T orNull()
– Optional 객체의 present 값을 반환, 만일 값이 없을 경우 null을 반환. fromNullable의 역임
Set asSet()
– Optional 객체에서 포함하고 있는 인스턴스의 변경 불가능한 싱글톤 Set을 반환. 만일 인스턴스가 없다면 변경불가능한 Empty set을 반환

3) Guava의 Preconditions 또는 NullPointerTester 클래스 이용하기


Nullness Anotation 활용하기

메소드의 return값 또는 파라미터의 null 허용여부를 Annotation을 이용하여 지정합니다. 코딩 습관 들이기 3, 4번 항목을 제약하기 위해 사용하는데요.

IDE에서 지원하는 @Nullable, @NotNull 등의 Annotation을 사용하면 코드에서 NPE 발생 가능여부를 미리 경고해줍니다. 또 해당 Annotation 제약사항을 위반했을 경우 컴파일시 NPE가 아닌 IllegalArgumentException 또는 IllegalStateException이 발생됩니다. Argument로 NotNull이어야 한다고 정했는데 Null이 들어왔다면 의미상 NPE보다는 잘못된 Argument가 맞겠죠?

현재 ItelliJ, Eclipse IDE 및 Find Bugs에서는 서로 다른 Annotation 라이브러리를 사용하는데요. JCP에 Software Defect Detection하기 위한 Annotation이 JSR-305로 요청 중이나 현재 dormant(중단) 상태네요. 언제 JDK에 포함될런지는 모르겠네요 :'(

Posted by slender ankles
,

데이터베이스의 정규화란 무엇이며, 왜 필요한가?

데이터베이스의 정규화란 관계형 데이터베이스를 설계할 때나오는 개념입니다. 

관계형 데이터베이스란 쉽게 말해서 실제 존재하는 개념을 개체(Entity)로 만들어 개체간의 관계(Relationship)를 만들어주는 것을 말합니다. 

학생이라는 Entity와 관계(Relation)된 Entity에 대해서 예를 들어보자면 스터디그룹, 전공학과일 것입니다. 

이렇게 각 개체와 개체간의 관계를 테이블 등으로 표현하는 것을 데이터베이스라고 합니다. 


예를 들어 학교라는 시스템을 데이터베이스로 표현한다면 우선 학생이란 개체(Entity)가 필요할 것입니다. 

학생이라는 Entity에는 <이름>, <나이>, <학번>, <전공>과 같은 속성들을 가지게 될 것입니다. 

이를 토대로 학생 테이블에 데이터가 구성하게 되면 

 이름

나이 

학번 

전공 

 김아무개

21 

201501012 

컴퓨터공 

이런식의 하나의 표, 그러니까 테이블이 만들어 질 것입니다. 

김아무개 뿐만 아니라 홍길동의 데이터가 추가되면 김아무개의 다음 행에 홍길동과 함께 한 행을 채우게 되겠죠. 

여기서 학생이라는 개념을 테이블(다른 말로, 릴레이션, Relation)

이름, 나이, 학번, 전공를 열(다른 말로, 어트리뷰트, Attribute)

그리고 김아무개의 정보가 담긴 한 행을(다른 말로, 튜플, Tuple)이라고 합니다. 

또, 전공이라는 열을 예로 들어보면 컴퓨터공, 경영학, 기계공학... 등등 채워질 수 있는 내용들이 있게 됩니다.

이 속성을 이루는 값들의 집합을 도메인(Domain)이라고 합 니다. 

테이블 = 릴레이션, 열 = 어트리뷰트 .... 짜증납니다. 똑같은 개념에 대한 단어가 여러 가지입니다. 


아무튼 이렇게 누구나 알 법한 데이터베이스에 대한 기초상식에 대해서 이야기 한 이유는 

데이터베이스를 설계하면서 필요한 정규화의 개념에 대해서 이야기하고 싶어서 입니다.

학생 테이블 뿐만 아니라 수강생 테이블을 하나 더 생각해봅니다. 

수강생 테이블에는 

<학번>, <이름>, <나이>, <전공>, <재수강여부> 등등의 정보가 들어갈 수 있겠죠

학번 

이름 

나이 

전공 

재수강여부 

201501012

김아무개 

21 

컴퓨터공 

True

201502039

홍길동

22 

경영학과 

False


뭔가 비효율적이지 않나요?

학교 시스템이라는 전체 시스템에서 학생, 수강생의 예만 들어봐도 저렇게 중복되는 정보가 있습니다. 

<학번>, <이름>, <나이>, <전공> 등은 학생 테이블이나 수강생 테이블에 중복되어 존재하게 됩니다. 

그렇지만 학생이라는 객체와 수강생이라는 객체는 엄연히 분리되어 할 개념이긴 한데 말이죠.

비효율적이라고 말한 이유는 간단합니다. 테이블이 수정되거나 삽입 될 때에는 모든 테이블에 걸쳐서 연쇄적으로 수정되거나 삽입되어야 합니다. 단 두가지의 테이블만 봐서 그렇지 어떠한 시스템에서는 이런식으로 데이터베이스가 짜져있다면 최소 수십개의 테이블에 데이터를 삽입하던지 수정해야 될 것입니다. 데이터의 일관성을 유지하기 위해서 말이죠. 


이러한 상황을 해결하기 위해 정규화(Nomalization) 라는 것이 필요한 것입니다. 

기본적으로 정규화란 잘못설계된 데이터베이스의 구조를 더 작은 속성으로 쪼개어 바람직한 구조로 만드는 과정입니다. 

* 여기서 번외로 하나 설명해보자면, 결국 정규화 과정을 거치게 되면서 한데 뭉쳐있던 테이블을 더 잘게 쪼개게 되어 테이블의 수가 더 많아지게 됩니다. 이렇게 쪼개어진 정보에서 의미있는 정보를 추출해내기 위해서는 서로 합치는 과정을 통해 출력 결과를 도출해내는 연산이 필요한데, 이를 관계형 데이터베이스에서는 JOIN이라고 부릅니다. 이 JOIN 연산시 상당히 큰 부하를 가져오게 됩니다. 물론 그렇다고 정규화를 안한 데이터베이스를 사용하진 않습니다. 보통 성능과 이상증상의 제거를 고려하여 적당한 선에 결정합니다.(Trade Off)


정규화의 방법에는 여러가지가 있습니다. 

1NF, 2NF, 3NF, BCNF, 4NF, 5NF 등 많이 있으나 (NF = Normal Form, 정규형) 성능상의 이슈등을 고려해 보통 3NF나 BCNF정도에서 멈춘다고 합니다. 

(성능을 위해 이미 정규화된 테이블을 합치는 것을 역정규화라고 합니다)


제1 정규화(= 1NF)

모든 속성은 원자값을 가진다. 하나의 컬럼에는 두 개의 값이 들어 갈 수 없다는 것입니다. 

이름

취미

니콜라스

자전거, 독서

위의 테이블은 니콜라스라는 사람이 가지는 취미가 자전거, 독서인데, 한 컬럼에 두 개의 값이 들어가있습니다. 이러한 구조는 제1정규화의 대상입니다. 다음과 같이 수정합니다.

이름

취미

니콜라스

자전거

니콜라스

독서


제2 정규화(= 2NF)

Key 외의 다른 컬럼들은 Key에만 의존적이어야 한다. (완전 함수 의존) 

이 말이 처음에는 잘 이해가 안됐는데, 쉽게 정리해보자면 

키(중심이자 유일한 성질을 갖는 컬럼) 이외의 일부 컬럼에 의해 결정되는 컬럼들이 있으면 

안된다는 말이다. 

예를 들어 학교라는 테이블을 생각해보자.

<"학교"테이블>

학번

학생이름

학년

학과

수강과목

학점

교수

개설학과

key값이 학번, 수강과목에 있다. 학번과 수강과목을 통해 행의 유일성은 보장 할 수 있겠지만 제2정규화를 만족할 수 없다. (키에 의존적이지 않은 컬럼들이 존재한다)

학생이름과 학년 학과는 학번에 종속적인 컬럼입니다. 종속적이라는 것은 학번이라는 값을 통해 결정되는 컬럼을 뜻합니다.

의존적이라는 말이 오히려 더 이해하기 쉬운 듯하지만 혼용해서 사용하겠습니다. 

이에 반해 학점, 교수, 개설학과는 수강과목에 종속적인 컬림입니다. 결국 학점, 교수, 개설학과는은 학번에 의존적인 컬럼이 아니라는 이야기입니다. 마찬가지로 학생이름, 학년, 학과도 수강과목에 의존적이지 않은 컬림이죠.

다음과 같이 수정해야 합니다.

<"학생"테이블>

학번

학생이름

학년

학과


<"수강과목"테이블>

수강과목

학점

교수

개설학과

<"수강"테이블>

학번

수강과목

이와같이 변하면 각 컬럼들은 해당 테이블의 키값에만 종속적이게 됩니다.

제3 정규화(= 3NF)

기본키에 의존하지 않고, 일반키에 의존적인 컬럼들을 제거합니다.

보통 책에는

"이행종속이 있으면 안된다. 단, Key가 아닌 어느 속성이 Key의 일부를 결정지을 수 있다면 3NF를 만족"

"이행종속이란? A->B, B->C 결정하는 경우 A->C를 결정" 이렇게 설명되어 있는데

이게 도대체 무슨말인가...싶습니다. 쉽게 이해가 되지 않습니다. 

첫 번째 줄이 더 이해 잘 될 것 같습니다. 


기본키에 의존하는 키에 또 다른 컬럼이 의존하는 것. 즉 A -> B, B -> C 와 같이 설명한 것을 이해할 수 있겠습니다.


제2정규화된 결과에서 수강과목 테이블에 주목합니다. 수강과목 학점 교수 개설학과로 이루어져 있습니다. 

교수는 수강과목에 의존적인 테이블 컬럼이고, 개설학과는 교수에 의존적인 테이블 컬럼입니다. 즉, 제3정규화의 대상이라는 말입니다. 다음과 같이 바꾸어줍니다. 

<"학생"테이블>

학번

학생이름

학년

학과

<"수강과목"테이블>

수강과목

학점

교수

<"교수"테이블>

교수

개설학과

<"수강"테이블>

학번

수강과목


이렇게 하면 3NF를 만족한다.(이행종속이 없다)


BCNF

BCNF의 주요 내용은 모든 결정자는 반드시 Key이어야 한다는 것입니다. 

1NF에서 곧 바로 BCNF 정규화가 가능합니다. 

학번 -> 이름, 학년, 학과

과목 -> 학점, 교수

교수 -> 개설학과

이렇게 키를 규정할 수가 있습니다. 


제 4정규화

함수종속이 아닌 다치 종속 제거


제 5정규화

후보키를 통하지 않은 조인 종속성을 제거






'Database' 카테고리의 다른 글

데이터베이스의 인덱스 자료구조 B-TREE  (2) 2015.09.02
트리거(Trigger)  (0) 2015.09.02
Posted by slender ankles
,

GET과 POST 요청 방식의 차이는 무엇인가?

URL에 데이터가 있는 것은 GET방식, URL에 데이터가 없고 메시지 본문에 있는 것은 POST방식


GET요청의 특징

- URL에 데이터를 포함 - 데이터 조회에 적합

- 바이너리 및 대용량 데이터 전송 불가

- 요청라인과 헤드 필드의 최대 크기

  * HTTP 사양에는 제한사항 없음

  * 대용량 URL로 인한 문제 발생 => 웹 서버에 따라 최대 크기 제한

  * 마이크로소프트 IIS 6.0 16KB

  * APACHE 웹 서버 8KB


GET요청의 데이터 전달 형식은 어떻게 되는가?

서비스 주소 ? V1 = 23 & V2 = 15

서비스주소와 데이터를 ? 라는 문자를 이용해서 구분한다.

예) http://www.naver.com?v1=23&v2=15


GET 요청의 장점은 무엇인가?

URL에 데이터가 섞여 있기 때문에 결과 화면을 다른 사람들과 공유 할 수 있다. 

링크를 클릭하게 되면 바로 결과화면을 볼 수 있다.


GET 요청의 문제점은 무엇인가?

(1) 보안에 좋지 않다.

주소에 데이터가 섞여있기 때문에 사용자의 로그인이나 중요 정보 요청에서 데이터가 밖으로 보인다.

그렇기 때문에 보안상의 이슈가 발생 할 수 있다. 


(2) 바이너리 데이터를 전송 할 수 없다.

파일의 데이터는 URL에 붙여서 전송 할 수 없다.

BASE 64라는 인코딩 방식을 통해 바이너리 데이터를 문자화해서 보낼 수도 있지만, URI나 헤더 정보가 너무 크면

웹 서버에서 처리 할 수 없다.

이런 것은 POST를 통해 전송해야 한다.


POST요청의 특징

- URL에 데이터가 포함되지 않음 => 외부 노출 방지

- 메시지본문에 데이터 포함 => 실행 결과 공유 불가

- 바이너리 및 대용량 데이터 전송 가능


POST요청의 요청은 어떻게 이루어지는가?

요청라인과 요청헤더 다음에 공백라인이 있고 그 다음에 메시지 본문(Message Body)라 불리는 부분에 데이터가 위치해서 전송된다.


POST요청의 장점은 무엇인가?

입력값을 URL에 노출 시키지 않는다. 당연히 보안상으로 GET에 비해 좋다.

폼 태그를 통해 보내진 POST데이터는 Content-Length 와 Content-Type 등으로 구분한다.

Content-Type은 기본적으로 application/x-www-form-urlencoded형식으로 인코딩되어 보내진다.


POST요청의 문제점은 무엇인가?

(1) 요청 결과를  공유 할 수 없다.

즐겨찾기, 메일 등으로 그 결과값을 공유 할 수 없다.

POST요청은 데이터를 메시지 본문에 붙여서 전송하기 때문이다.


(2) GET방식과 마찬가지로 POST도 데이터를 전달 할 때 '이름=값&이름=값'형태로 보내진다.

결국 문자데이터를 보낼 때는 상관없지만 바이너리 데이터 등을 전송할 때는 이러한 '='이나 '&'값이 섞여 있을 수 있기 때문에 문제가 발생할 수 있다.

그래서 바이너리 데이터 등을 보낼 때는 멀티 파트 인코딩 방식을 통해 보내야 한다.


멀티 파트 인코딩 방식은 어떨때 사용하며 그렇게 사용하는 이유는 무엇인가?

POST형식 역시 데시지 본문에 '이름=값&이름=값'형태로 보내지기 때문에 

바이너리 데이터에 혹시 = 이나 &가 섞여있으면 문제가 발생 할 수 있다.

그래서 멀티 파트 인코딩 방식을 사용하여 요청정보와 데이터를 확실히 구분 할 수 있게 한다.

예를들어 <form>태그의 enctype 속성을 'multipart/form-data'로 지정해서 file 전송을 할 수 있게 합니다.

'네트워크' 카테고리의 다른 글

동기 vs 비동기  (0) 2015.10.06
빅 엔디안(Big Endian) vs 리틀 엔티안(Little Endian)  (0) 2015.09.14
HTTP 와 HTTPS  (0) 2015.08.08
HTTP 프로토콜  (0) 2015.08.08
쿠키와 세션의 차이  (0) 2015.08.08
Posted by slender ankles
,

HTTP 와 HTTPS

네트워크 2015. 8. 8. 01:32

https는 전자상거래에서의 보안을 위해서 개발한 통신 레어이다.

SSL은 전송계층 프로토콜이기 때문에, 응용 계층의 어떠한 프로토콜이라도 암호화해서 보낼 수 있다.

HTTP는 기본적으로 평문 데이터 전송을 원칙으로 하기 때문에 개인의 프라이버시와 관련된 보안적으로는 활용하기 힘들다.

HTTPSSSL레이어 위에 HTTP를 통과시키는 방식이다. 평문의 HTTP문서는 SSL레이어를 통과하면서 암호화돼서 목적지에 도착하고, 목적지에는 SSL레이어를 통과하면서 복호화돼서 웹브라우저에 전달된다.

  

- HTTP와 다른점?

HTTPS는 인증서를 이용해서, 접속사이트를 신뢰할 수 있는지 평가할 수 있다.

HTTPSHTTP에 비해 느리다

'네트워크' 카테고리의 다른 글

빅 엔디안(Big Endian) vs 리틀 엔티안(Little Endian)  (0) 2015.09.14
GET방식 과 POST방식  (0) 2015.08.08
HTTP 프로토콜  (0) 2015.08.08
쿠키와 세션의 차이  (0) 2015.08.08
DNS서버  (0) 2015.08.08
Posted by slender ankles
,