반응형

출처 : https://www.booksr.co.kr/product/9788970509716/

해싱이란?

출처 : https://www.google.com/url?sa=i&url=https%3A%2F%2Fmattlee.tistory.com%2F62&psig=AOvVaw3Dyg-yca14d4qX5RxerTE-&ust=1691834717419000&source=images&cd=vfe&opi=89978449&ved=0CA4QjRxqFwoTCICS8syt1IADFQAAAAAdAAAAABAD

해싱을 "물건을 정리하는 것"과 연결하는 것은 일종의 비유적인 표현일 수 있습니다. 이 비유를 통해 해싱의 개념을 더 쉽게 이해할 수 있을 수도 있습니다.

생각해보세요. 여러 종류의 물건을 정리할 때, 비슷한 물건들을 함께 묶어서 그룹화하고, 각 그룹에 고유한 식별자를 부여한다고 가정해봅시다. 이렇게 하면 특정 그룹에 속한 물건들을 찾거나 정리하는 작업이 훨씬 효율적이 될 것입니다.

해싱도 비슷한 개념을 따릅니다. 해싱 함수를 사용하여 다양한 데이터를 고정된 길이의 해시 값으로 변환합니다. 이 때 비슷한 속성이나 특징을 가진 데이터는 동일한 해시 값을 가지는 경향이 있습니다. 이렇게 해시 값은 데이터를 "그룹화"하거나 "정리"하는 역할을 합니다.

또한, 비슷한 입력이라도 해시 함수를 통과하면 해시 값은 완전히 다른 값으로 바뀝니다. 이런 점에서 해시 함수는 물건을 그룹화하면서 각 그룹을 고유하게 식별하는 것과 유사합니다. 

그러나 해싱이 물건을 실제로 정리하는 물리적인 작업은 아닙니다. 해싱은 주로 데이터 처리와 관련된 개념으로, 데이터의 빠른 검색, 정렬, 암호화 등에 활용되는 중요한 도구입니다.

 

해시함수

해시 함수는 임의의 크기를 가진 데이터를 고정된 길이의 값으로 변환하는 함수입니다. 이 변환된 값은 해시 값이라고 불리며, 주로 암호학, 데이터 정렬 및 검색, 데이터 무결성 검증 등에 사용됩니다.

해시 함수의 특징과 목적은 다음과 같습니다:

1. 일관성: 동일한 입력에 대해서는 항상 동일한 해시 값이 생성되어야 합니다.
2. 고르게 분포: 입력 공간의 다양한 값들이 고르게 해시 값으로 매핑되어야 합니다.
3. 일방향성: 해시 값으로부터 원래 입력 데이터를 역추적하기 어렵게 설계되어야 합니다.
4. 충돌 방지: 서로 다른 입력에 대해 같은 해시 값이 생성되는 충돌을 최소화해야 합니다.
5. 작은 입력 변화에 대한 큰 해시 값 변화: 입력의 작은 변화가 해시 값에 큰 변화를 가져오도록 설계되어야 합니다.

좋은 해시 함수를 설계하는 것은 중요한 작업입니다. 해시 함수의 안전성과 신뢰성이 사용처에 따라 큰 영향을 미칠 수 있기 때문입니다. 해시 함수의 선택은 데이터 무결성 검증이나 보안 시스템에서 중요한 역할을 합니다.

하지만 어떤 상황에서는 충돌이 발생할 수 있습니다. 충돌은 서로 다른 입력에 대해 같은 해시 값이 나타나는 상황을 말합니다. 충돌을 최소화하기 위해 해시 함수의 설계와 충돌 처리 메커니즘이 중요합니다.

대표적인 해시 함수로는 MD5, SHA-1, SHA-256 등이 있습니다. 그러나 보안 목적으로 사용할 때는 최신이고 안전한 해시 함수를 선택하는 것이 중요합니다. 이러한 알고리즘들은 주기적으로 검토되며, 취약점이 발견되면 보완됩니다.

 

제산함수

제산 함수 (Multiplicative Hash Function)는 해시 함수의 한 유형으로, 주로 해시 테이블 등에서 사용됩니다. 제산 함수는 입력 데이터를 정수로 변환하여 해시 값을 생성하는 방식을 사용합니다. 다음은 제산 함수의 기본 아이디어와 작동 방식에 대한 간단한 설명입니다.

제산 함수는 다음과 같은 공식을 사용하여 해시 값을 생성합니다:

```
hash(key) = (a * key + b) % M
```

여기서:
- `key`: 입력 데이터로부터 얻은 키(key) 값입니다.
- `a`와 `b`: 해시 함수에 사용되는 상수 값입니다.
- `M`: 해시 테이블의 크기로, 일반적으로 소수(prime number)로 선택됩니다.

제산 함수의 작동 방식은 다음과 같습니다:
1. 입력 데이터인 키(key)를 정수로 변환합니다.
2. 상수 `a`와 `b`를 사용하여 변환된 키에 선형 변환을 적용합니다.
3. 결과를 해시 테이블 크기 `M`으로 나눈 나머지 값을 최종 해시 값으로 사용합니다.

제산 함수는 일반적으로 제곱, 곱하기와 나누기의 조합 등 다양한 수학적 기법을 사용하여 설계됩니다. 이 함수를 사용하면 데이터가 해시 테이블의 여러 슬롯에 고르게 분배될 수 있습니다. 그러나 잘못된 상수 값 선택이나 해시 테이블 크기의 부적절한 선택 등으로 인해 충돌이 발생할 수 있습니다.

제산 함수는 간단하면서도 효과적인 해시 함수의 한 예시입니다. 그러나 보안 관련 목적으로 사용하기보다는 일반적인 데이터 저장 및 검색 시에 더 자주 활용됩니다.

 

폴딩함수

폴딩 함수(Folding Function)는 입력 데이터를 분할하고 조합하여 해시 값을 생성하는 해싱 알고리즘 중 하나입니다. 이 함수는 입력 데이터를 일정한 크기의 조각으로 나눈 후 이들을 조합하여 해시 값을 계산합니다. 폴딩 함수는 주로 큰 데이터를 해시 값으로 변환할 때 사용됩니다.

폴딩 함수의 기본 작동 방식은 다음과 같습니다:

1. 입력 데이터를 일정한 크기의 조각으로 나눕니다. 이 때 조각의 크기는 해시 테이블의 크기와 관련될 수 있습니다.
2. 각 조각에 대해 숫자를 할당하거나 각 조각을 숫자로 변환합니다.
3. 할당된 숫자나 변환된 숫자를 조합하여 최종 해시 값을 생성합니다.

폴딩 함수는 데이터의 길이와 해시 테이블의 크기 등에 따라 다양한 방식으로 구현될 수 있습니다. 예를 들어, 데이터를 더하거나 곱하는 방식으로 조합할 수도 있습니다. 여러 개의 조각이 생성될 때 이들을 XOR 또는 더하는 방식으로 합쳐 해시 값을 만들기도 합니다.

폴딩 함수는 주로 큰 데이터나 특정 유형의 데이터에 적합한 경우에 사용됩니다. 예를 들어, 전화 번호나 신용 카드 번호와 같은 긴 숫자를 해싱할 때 유용합니다. 그러나 보안 목적의 해싱에는 일반적으로 다른 해시 함수들이 더 많이 사용됩니다.

폴딩 함수의 중요한 부분은 데이터 조각을 어떻게 분할하고 조합할지에 따라 달라질 수 있습니다. 그렇기 때문에 사용하는 데이터와 해시 테이블의 요구 사항에 따라 적절한 폴딩 함수 디자인이 필요합니다.

 

중간 제곱 함수

중간 제곱 함수(Mid-square Method)는 해시 함수의 하나로, 입력 데이터의 제곱값의 중간 부분을 해시 값으로 사용하는 방법입니다. 이 함수는 입력 데이터를 정수로 변환하여 사용하며, 주로 간단한 해시 함수 예제로 사용되기도 합니다.

중간 제곱 함수의 작동 방식은 다음과 같습니다:

1. 입력 데이터를 정수로 변환합니다.
2. 이 정수의 제곱 값을 구합니다.
3. 제곱 값을 문자열로 변환한 후, 중간 부분의 일부를 해시 값으로 선택합니다. 이 선택된 부분이 해시 값입니다.

예를 들어, 입력 데이터가 1234라면 다음과 같은 단계를 거칠 수 있습니다:

1. 입력 데이터: 1234
2. 제곱 값: 1234 * 1234 = 1522756
3. 제곱 값 문자열: "1522756"
4. 중간 부분 선택: "227"

이 선택된 중간 부분 "227"이 해당 입력 데이터에 대한 해시 값으로 사용됩니다.

중간 제곱 함수는 단순하고 빠르게 구현할 수 있지만, 모든 상황에서 잘 작동하지는 않습니다. 특히 입력 데이터의 일부 중간 부분만을 사용하기 때문에 입력 데이터의 분포에 따라 해시 값 분포가 부적절할 수 있습니다. 이로 인해 충돌이 더 자주 발생할 수 있습니다.

중간 제곱 함수는 보안 목적으로 사용하기보다는 간단한 연습용 예제나 교육용으로 사용될 때 주로 사용됩니다. 실제로 보안이나 중요한 데이터 처리에는 다른 더 안전하고 고급스러운 해시 함수가 필요합니다.

 

비트 추출 방법

비트 추출 방법(Bit Extraction Method)은 해시 함수의 하나로, 입력 데이터에서 특정 비트들을 추출하여 해시 값을 생성하는 방법입니다. 이 방법은 입력 데이터의 특정 비트 패턴을 활용하여 해시 값을 계산합니다.

비트 추출 방법의 기본 작동 방식은 다음과 같습니다:

1. 입력 데이터를 이진 표현으로 변환합니다.
2. 이진 표현에서 특정 위치의 비트들을 추출합니다.
3. 추출한 비트들을 조합하여 해시 값을 생성합니다.

예를 들어, 입력 데이터가 1234 (10진수)일 때 다음과 같은 단계를 거칠 수 있습니다:

1. 입력 데이터: 1234
2. 이진 표현: 10011010010
3. 특정 비트 추출: 여기서, 예를 들어 2번째부터 5번째 비트를 추출한다면 "0011"이 추출됩니다.
4. 추출한 비트 조합: "0011"을 이용하여 해시 값 생성

비트 추출 방법은 입력 데이터의 특정 비트 패턴을 이용하여 해시 값을 생성하므로, 이러한 패턴이 데이터의 분포와 충돌을 발생시킬 가능성이 있습니다. 따라서 충돌을 최소화하려면 잘 선택된 비트 패턴이 필요합니다.

비트 추출 방법은 단순하고 빠르게 구현할 수 있지만, 해시 함수로서의 안정성과 보안성은 그리 높지 않습니다. 일반적으로 간단한 연습용 예제나 교육용으로 사용되며, 실제 보안 요구 사항에는 더 안전하고 복잡한 해시 함수가 필요합니다.

 

숫자 분석 방법

숫자 분석 방법(Number Analysis Method)은 해시 함수의 하나로, 입력 데이터가 숫자로 이루어진 경우에 사용되는 해싱 기법 중 하나입니다. 이 방법은 입력 데이터의 숫자들을 조합하여 해시 값을 생성합니다.

숫자 분석 방법의 기본 아이디어는 입력 데이터의 숫자들을 조합하여 해시 값을 만드는 것입니다. 일반적으로 숫자 분석 방법은 입력 데이터의 각 숫자를 일정한 위치에 배치한 후, 이들을 조합하여 해시 값을 생성합니다.

예를 들어, 입력 데이터가 123456 (10진수)이라면 다음과 같은 단계를 거칠 수 있습니다:

1. 입력 데이터: 123456
2. 각 숫자의 위치 지정: 예를 들어, 첫 번째 숫자는 1의 자리에, 두 번째 숫자는 10의 자리에, 세 번째 숫자는 100의 자리에 위치시킵니다.
3. 숫자 조합: 각 숫자를 해당 위치에 배치하고 이들을 조합하여 해시 값을 생성합니다. 이 예에서는 1 + 20 + 300 + 4000 + 50000 = 54321이 됩니다.

숫자 분석 방법은 입력 데이터가 숫자로 이루어진 경우에 사용되며, 간단한 연습용 예제나 교육용으로 활용될 수 있습니다. 그러나 일반적으로 안전한 해시 함수로서의 역할을 수행하기에는 부족합니다. 숫자의 배치 순서나 조합 방식에 따라서 충돌이 발생할 수 있으며, 충돌을 최소화하려면 신중한 선택과 분석이 필요합니다.

실제 보안이나 중요한 데이터 처리에는 더 강력하고 안전한 해시 함수가 필요합니다.

 

탐색키가 문자열일 경우

1. 아스키 코드

출처 : https://www.google.com/url?sa=i&url=https%3A%2F%2Fstepbystep1.tistory.com%2F10&psig=AOvVaw0KwXg5Jv6rqaWEL42EWLWI&ust=1691834389453000&source=images&cd=vfe&opi=89978449&ved=0CA4QjRxqFwoTCJiq9K-s1IADFQAAAAAdAAAAABAH

아스크코드를 활용하여 문자열을 해시 값으로 변환하는 방법은 일반적으로 가능합니다. 아스키 코드는 문자를 숫자로 표현하는데 사용되며, 문자열의 각 문자를 아스키 코드로 변환하여 이를 조합하여 해시 값을 생성하는 방식이 많이 활용됩니다.

다양한 방법 중 아스키 코드를 활용하여 문자열을 해시 값으로 변환하는 기본적인 예제를 살펴보겠습니다. 이 예제에서는 문자열의 각 문자의 아스키 코드 값을 더하는 방식을 사용합니다.

예를 들어, 문자열 "hello"를 해시 값으로 변환하는 과정은 다음과 같을 수 있습니다:

1. 문자열: "hello"
2. 아스키 코드 변환: 'h' (104) + 'e' (101) + 'l' (108) + 'l' (108) + 'o' (111) = 532
3. 해시 값: 532

이러한 방식으로 문자열의 각 문자의 아스키 코드 값을 더해 해시 값을 생성할 수 있습니다. 그러나 이러한 방법은 충돌이 발생할 가능성이 높습니다. 예를 들어, "hello"와 "ehlol"은 아스키 코드 합이 동일하므로 같은 해시 값이 생성됩니다.

따라서 실제로 문자열을 해시 값으로 변환할 때에는 해시 충돌에 대한 처리 방법을 고려하고, 더 안전하고 복잡한 해시 함수를 선택하거나 디자인하는 것이 좋습니다.

 

2.호너의 방법

호너의 방법(Horner's Method)은 다항식을 평가하는데 사용되는 기법 중 하나로, 문자열을 해싱하는 데에도 응용될 수 있습니다. 이 방법은 다항식을 빠르게 계산하기 위해 사용되지만, 문자열의 각 문자를 숫자로 변환하여 해시 값으로 활용하는데에도 유용합니다.

호너의 방법은 문자열을 해시 값으로 변환할 때 아스키 코드의 합을 사용하는 것보다 더 효율적인 방법입니다. 이 방법은 다항식을 계산하는데 사용되는 방식을 변형한 것으로, 다음과 같이 작동합니다:

1. 문자열을 하나의 수로 보고, 문자열의 각 문자를 다항식의 계수로 간주합니다.
2. 이 때의 문자열을 해시 값으로 활용합니다.

예를 들어, 문자열 "hello"를 해시 값으로 변환하는 과정은 다음과 같을 수 있습니다:

1. 문자열: "hello"
2. 다항식 계수로 간주: 'h' (104), 'e' (101), 'l' (108), 'l' (108), 'o' (111)
3. 해시 값 계산: (((104 * 31 + 101) * 31 + 108) * 31 + 108) * 31 + 111 = 994328

호너의 방법은 문자열을 다항식 계수로 간주하여 해시 값을 계산하므로, 일반적으로 좋은 해시 값을 생성하며 충돌을 줄이는데 도움이 될 수 있습니다. 하지만 충돌이 완전히 없는 해시 함수는 아니므로, 충돌 처리에 대한 방법도 고려되어야 합니다.

이 방법은 문자열을 효율적으로 해시 값으로 변환하는데에 사용될 수 있으며, 문자열 데이터를 다룰 때 다양한 상황에 따라 적용될 수 있는 방법 중 하나입니다.

 

개방 주소법(Open Addressing)

출처 : https://www.google.com/url?sa=i&url=https%3A%2F%2Fwordrow.kr%2F%25EC%259D%2598%25EB%25AF%25B8%2F%25EA%25B0%259C%25EB%25B0%25A9%2520%25EC%25A3%25BC%25EC%2586%258C%25EB%25B2%2595%2F&psig=AOvVaw2_Lb2CHbqlHR6QEmY_QdyS&ust=1691833926420000&source=images&cd=vfe&opi=89978449&ved=0CA4QjRxqFwoTCIDWwOyq1IADFQAAAAAdAAAAABAD

해시 테이블에서 충돌이 발생했을 때 충돌된 항목을 해결하기 위한 방법 중 하나입니다. 충돌이란 서로 다른 키가 같은 해시 값에 매핑되는 상황을 말합니다. 개방 주소법은 이러한 충돌을 다른 방식으로 처리하여 해시 테이블 내에서 충돌을 해결하려는 목적을 가집니다.

개방 주소법은 다음과 같은 방식으로 작동합니다:

1. 충돌이 발생한 슬롯에 다른 슬롯을 찾아 비어있는 슬롯에 항목을 저장합니다.
2. 이때 사용되는 슬롯을 찾는 방법은 다양한데, 대표적으로 선형 탐사(Linear Probing), 이차 탐사(Quadratic Probing), 이중 해싱(Double Hashing) 등이 있습니다.

개방 주소법의 주요 장점은 해시 테이블 내부의 메모리 낭비를 줄일 수 있다는 점입니다. 충돌이 발생했을 때 같은 슬롯에 대해 연결 리스트나 체이닝 방식을 사용하는 방법보다 메모리를 더 효율적으로 사용할 수 있습니다.

그러나 개방 주소법은 클러스터링이라는 문제를 발생시킬 수 있습니다. 클러스터링은 해시 테이블 내에서 항목들이 서로 연속적으로 위치하는 현상으로, 성능 저하를 초래할 수 있습니다. 또한, 충돌을 해결하는 방식에 따라 성능이 달라질 수 있습니다. 일부 슬롯에 항목이 밀집되어 검색 성능이 저하되는 등의 문제가 발생할 수 있습니다.

개방 주소법은 충돌 처리를 위한 하나의 접근 방식이며, 그 특성에 따라 다양한 방식을 적절히 선택하여 사용해야 합니다.

 

1. 선형 조사법(Linear Probing)

해시 충돌이 발생했을 때 충돌된 슬롯의 다음 슬롯을 차례로 검사하여 비어있는 슬롯을 찾아 해시 값을 저장하는 방법입니다. 선형 조사법은 간단하고 구현하기 쉬우며, 메모리 절약에 도움이 될 수 있습니다.

선형 조사법의 작동 방식은 다음과 같습니다:

1. 충돌이 발생한 슬롯의 다음 슬롯부터 차례로 검사합니다.
2. 비어있는 슬롯을 찾을 때까지 검사를 진행합니다.
3. 비어있는 슬롯을 찾으면 거기에 해시 값을 저장합니다.

선형 조사법의 장점은 메모리 낭비를 줄일 수 있다는 점입니다. 모든 항목을 해시 테이블의 연속된 슬롯에 저장할 수 있기 때문에 빈 슬롯을 찾기까지의 검색이 비교적 빠르게 이루어집니다.

하지만 선형 조사법은 클러스터링이라는 문제를 발생시킬 수 있습니다. 클러스터링은 해시 테이블 내에서 항목들이 서로 연속적으로 위치하여, 클러스터가 형성되어 검색 성능이 저하되는 현상을 의미합니다. 또한, 충돌이 발생한 슬롯 주위에 밀집된 항목들로 인해 성능이 저하되는 경우가 발생할 수 있습니다.

선형 조사법은 간단하면서도 효율적인 방법 중 하나이지만, 클러스터링과 성능의 변화에 대한 고려가 필요합니다. 해시 테이블의 크기나 사용되는 해시 함수에 따라 성능이 달라질 수 있습니다.

 

2. 이중 해싱법(Double Hashing)

충돌이 발생했을 때 두 번째 해시 함수를 사용하여 다음 슬롯을 선택하는 방법입니다. 이중 해싱법은 선형 조사법과 비슷한 원리를 사용하지만, 다른 해시 함수를 이용하여 충돌을 해결하는 차이가 있습니다.

이중 해싱법의 작동 방식은 다음과 같습니다:

1. 충돌이 발생한 슬롯의 다음 슬롯을 선택합니다.
2. 다른 해시 함수를 사용하여 추가적인 이동 거리를 결정합니다. 이동 거리는 다른 해시 함수의 결과에 따라 정해집니다.
3. 이동 거리만큼 다음 슬롯을 차례로 검사하여 비어있는 슬롯을 찾습니다.
4. 비어있는 슬롯을 찾으면 거기에 해시 값을 저장합니다.

이중 해싱법은 충돌을 좀 더 균등하게 분산시킬 수 있는 장점이 있습니다. 다른 해시 함수를 사용하여 이동 거리를 결정하므로, 해시 값의 분포를 조절할 수 있어서 클러스터링 문제를 완화할 수 있습니다.

하지만 이중 해싱법도 해시 함수의 선택이나 충돌 처리 방식에 따라 성능이 달라질 수 있습니다. 또한, 다른 해시 함수를 사용하기 때문에 추가적인 연산이 필요하며, 이에 따른 성능 저하가 발생할 수 있습니다.

이중 해싱법은 선형 조사법의 한계를 극복하고자 하는 시도로, 충돌을 해결하는 다양한 개방 주소법 중 하나입니다. 적절한 해시 함수와 조절된 이동 거리 선택을 통해 충돌을 효과적으로 관리할 수 있습니다.

 

3. 이차 조사법(Quadratic Probing)

충돌이 발생했을 때 이차 함수를 사용하여 다음 슬롯을 선택하는 방법입니다. 이차 조사법은 선형 조사법과 다른 방식으로 충돌을 해결하는데 사용됩니다.

이차 조사법의 작동 방식은 다음과 같습니다:

1. 충돌이 발생한 슬롯의 다음 슬롯을 선택합니다.
2. 이차 함수를 사용하여 추가적인 이동 거리를 결정합니다. 이동 거리는 이차 함수에 의해 계산됩니다.
3. 이동 거리만큼 다음 슬롯을 차례로 검사하여 비어있는 슬롯을 찾습니다.
4. 비어있는 슬롯을 찾으면 거기에 해시 값을 저장합니다.

이차 조사법은 해시 테이블 내에서 클러스터링을 완화할 수 있는 장점이 있습니다. 이차 함수를 사용하여 이동 거리를 계산하므로, 동일한 충돌 슬롯에서 시작하는 항목들이 서로 다른 이동 거리를 가지며 해시 테이블 내에서 분산되게 됩니다.

하지만 이차 조사법도 해시 함수의 선택과 이차 함수의 설계에 따라 성능이 달라질 수 있습니다. 이차 함수의 선택에 따라 이동 거리가 결정되므로, 충돌을 효과적으로 관리하기 위해서는 적절한 이차 함수를 선택하는 것이 중요합니다.

이차 조사법은 선형 조사법과 이중 해싱법과 함께 충돌을 해결하는 방법 중 하나입니다. 각각의 방법은 특성에 따라 장단점이 있으며, 상황과 요구 사항에 따라 적절한 방법을 선택하여 사용해야 합니다.

 

관심이 있으신 분들에게 유용한 정보였길 바라며

다음은 14장 나머지 내용(체이닝, 해싱의 성능 분석 등등...)을 가져오도록 하겠습니다.

반응형

+ Recent posts