소개
소매업체의 상품 파일이 정리되었고 접근도 가능합니다. 이제 첫 실습의 질문에 답할 수 있습니다. 어떤 상품 이름이 가장 자주 등장할까요? 몇 줄은 손으로 셀 수 있지만 파일이 계속 늘어나면 반복 가능한 계산이 필요합니다.
MapReduce는 배치 계산을 구성하는 방법입니다. Map은 입력 기록을 키/값 쌍으로 바꾸고, Shuffle은 같은 키의 값을 모으며, Reduce는 각 키의 값을 결과로 결합합니다. WordCount에서는 상품 이름이 키이고 한 번 등장할 때마다 값 1을 더합니다. 단어 집계는 데이터 흐름을 보여주기 위한 작은 예제이며 완전한 판매 분석 시스템은 아닙니다.
준비된 학습 도구로 이 단계들을 살펴본 뒤, 같은 입력에 실제로 미리 컴파일된 Hadoop WordCount 프로그램을 실행합니다. 학습 도구는 프로세스 하나에서 알고리즘 단계를 출력하며 분산 실행의 추적 기록은 아닙니다. Hadoop은 로컬 모드로 실행하므로 계산에 집중한 다음, 다음 실습에서 같은 알고리즘을 YARN으로 옮길 수 있습니다. Java나 Python 프로그래밍은 필요하지 않습니다.
상품 이름을 키/값 쌍으로 바꾸기
이 단계에서는 입력을 확인하고 각 상품의 등장을 Map 단계에서 추적합니다.
로컬 작업 공간에서 시작합니다.
cd /home/labex/project
입력 여섯 줄을 읽습니다.
cat /home/labex/project/data/product-words.txt
예상 텍스트는 다음과 같습니다.
notebook pen
notebook folder
pen pen
folder notebook
notebook
folder pen
잠시 멈추고 상품 하나를 손으로 세어 보세요. notebook은 네 줄에서 한 번씩 등장합니다. pen은 셋째 줄에서 두 번 등장하는 것을 포함해 총 네 번이고 folder는 세 번입니다. 프로그램도 같은 합계를 출력해야 합니다.
**키/값 쌍(key/value pair)**은 이름과 값을 연결합니다. 이 알고리즘에서 Map은 등장할 때마다 (product, 1)을 내보냅니다. pen이 두 번 있으면 입력 한 줄당 쌍 하나가 아니라 별도의 쌍 두 개를 만듭니다.
제공된 wordcount-stages 실행 파일은 단계 이름과 로컬 입력 파일을 받습니다. map 보기를 사용합니다.
/home/labex/project/tools/wordcount-stages map /home/labex/project/data/product-words.txt
출력은 다음과 같이 시작합니다.
notebook 1
pen 1
notebook 1
folder 1
각 키와 값 사이의 간격은 탭입니다. 상품이 등장할 때마다 하나씩, 총 열한 쌍이 있습니다. 이 도구는 알고리즘을 보여줄 뿐 Hadoop 서비스를 시작하거나 태스크를 예약하지 않습니다. 단계 출력을 저장합니다.
/home/labex/project/tools/wordcount-stages map /home/labex/project/data/product-words.txt > /home/labex/project/output/map-pairs.txt
입력의 표현 방식이 바뀌었습니다. 전체 줄이 상품별로 묶을 수 있는 개별 집계 항목이 되었습니다.
집계 항목을 묶고 Reduce로 합치기
이 단계에서는 쌍이 Shuffle과 Reduce를 거치는 과정을 따라가고 출력을 손으로 예상한 값과 연결합니다.
Map은 집계 항목을 각각 내보냅니다. 상품별 합계를 내려면 그 상품의 항목들이 모여야 합니다. **셔플과 정렬(shuffle and sort)**은 키별로 쌍을 정리하여 리듀서가 특정 상품의 값을 받을 수 있게 합니다. 분산 작업에서는 태스크 사이의 데이터 전송이 포함될 수 있지만, 학습 도구는 묶인 값만 표시합니다.
묶인 값을 확인합니다.
/home/labex/project/tools/wordcount-stages shuffle /home/labex/project/data/product-words.txt
예상되는 그룹별 값은 다음과 같습니다.
folder 1,1,1
notebook 1,1,1,1
pen 1,1,1,1
키는 정렬되어 있습니다. 쉼표로 구분된 1은 여전히 원래 입력에서 한 번 등장한 것을 뜻하며 새로운 기록이 아닙니다. 그룹화 결과를 저장합니다.
/home/labex/project/tools/wordcount-stages shuffle /home/labex/project/data/product-words.txt > /home/labex/project/output/shuffled-values.txt
Reduce는 각 키의 값을 결합합니다. 여기서는 정수를 더합니다. 다른 애플리케이션에서는 값을 다른 방식으로 결합할 수 있습니다. MapReduce는 개수 세기에만 한정되지 않습니다.
Reduce 결과를 확인합니다.
/home/labex/project/tools/wordcount-stages reduce /home/labex/project/data/product-words.txt
예상 결과는 다음과 같습니다.
folder 3
notebook 4
pen 4
이 값을 1단계에서 손으로 센 개수와 비교하세요. 다음에 실제 Hadoop 애플리케이션과 비교할 수 있도록 결과를 저장합니다.
/home/labex/project/tools/wordcount-stages reduce /home/labex/project/data/product-words.txt > /home/labex/project/output/teaching-counts.txt
원래 입력에서 서로 다른 줄에 있더라도 각 키의 모든 등장이 결과에 반영됩니다. 그래서 Map과 Reduce 사이에 그룹화 단계가 필요합니다.
실제 Hadoop WordCount 프로그램 실행하기
이 단계에서는 미리 컴파일된 Hadoop 예제를 로컬 모드로 실행하여 같은 집계 작업을 수행합니다.
JAR는 Java 프로그램 코드를 묶은 파일입니다. Hadoop과 예제 JAR가 이미 설치되어 있으므로 코드를 컴파일할 필요가 없습니다. hadoop jar는 지정한 JAR를 실행하고, wordcount는 그 안의 WordCount 예제를 선택합니다. 아래의 -D 설정 두 개는 이번 실행에서 로컬 실행 프레임워크와 로컬 파일 시스템을 선택합니다. 마지막 두 인수는 입력 파일과 새 출력 디렉터리입니다.
hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.5.0.jar wordcount -Dmapreduce.framework.name=local -Dfs.defaultFS=file:/// /home/labex/project/data/product-words.txt /home/labex/project/output/local-wordcount
프롬프트가 돌아올 때까지 기다리세요. Hadoop이 진행 및 진단 메시지를 출력합니다. 경로, 식별자와 소요 시간은 달라집니다. 이것은 YARN 애플리케이션이 아니라 로컬 실행기를 사용하는 실제 Hadoop 프로그램입니다. 실습은 HDFS나 YARN 서비스를 시작하지 않으며 입력과 출력이 모두 로컬에 있습니다.
로컬 출력 디렉터리의 목록을 확인합니다.
ls /home/labex/project/output/local-wordcount
_SUCCESS 표시 파일과 part-... 결과 파일이 보여야 합니다. _SUCCESS는 출력이 성공적으로 완료되었음을 나타내고, 결과 파일에는 확인해야 할 데이터가 들어 있습니다. 로컬 셸의 part-* 패턴으로 결과 파일을 선택합니다. 내용을 합쳐 sort에 전달하면 안정적으로 비교할 수 있습니다.
cat /home/labex/project/output/local-wordcount/part-* | sort > /home/labex/project/output/hadoop-counts.txt
학습 도구의 집계와 비교합니다.
diff /home/labex/project/output/teaching-counts.txt /home/labex/project/output/hadoop-counts.txt
차이가 나타나지 않아야 합니다. 설명한 알고리즘을 실제 프로그램 출력과 연결했습니다. 이번 실행의 출력 디렉터리가 이미 있다면 무작정 삭제하거나 반복 제출이 덮어쓸 것이라 생각하지 말고 완료된 파일을 확인하세요.
나중에 중요한 구분이 하나 있습니다. HDFS 블록은 바이트를 저장하고, **입력 분할(input split)**은 입력 작업의 단위를 설명하며, **태스크(task)**는 작업을 실행합니다. 이들은 관련이 있지만 항상 일대일로 대응하지는 않습니다. 결과 파일은 처리 태스크의 출력이며 원래 저장 블록의 사본이 아닙니다.
입력 하나의 변화를 예상하고 테스트하기
이 단계에서는 작업 사본에 상품 하나를 추가하고 어느 결과가 바뀌는지 확인합니다.
읽기 전용 원본 입력은 그대로 유지합니다. 로컬 cat과 >로 새 쓰기 가능한 작업 사본을 만듭니다. 여기의 두 경로는 모두 로컬이며 바꿀 파일은 출력 파일입니다.
cat /home/labex/project/data/product-words.txt > /home/labex/project/output/changed-product-words.txt
notebook을 한 번 추가하면 새 개수가 어떻게 될지 예상해 보세요. 해당 합계만 4에서 5로 늘어나야 합니다. printf는 제공한 텍스트를 출력하고 \n은 줄바꿈을 뜻하며, >>는 기존 내용을 바꾸는 대신 뒤에 출력을 추가합니다.
printf 'notebook\n' >> /home/labex/project/output/changed-product-words.txt
바뀐 입력을 확인합니다.
cat /home/labex/project/output/changed-product-words.txt
마지막에 새 줄 하나가 있어야 합니다. 입력과 출력 경로만 바꿔 같은 Hadoop 프로그램을 실행합니다.
hadoop jar /opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.5.0.jar wordcount -Dmapreduce.framework.name=local -Dfs.defaultFS=file:/// /home/labex/project/output/changed-product-words.txt /home/labex/project/output/changed-wordcount
실제 결과를 정렬하여 읽습니다.
cat /home/labex/project/output/changed-wordcount/part-* | sort
예상 결과는 다음과 같습니다.
folder 3
notebook 5
pen 4
새 Map 쌍은 notebook 그룹에 속하므로 해당 Reduce 합계만 바뀝니다. 이제 명령의 성공을 알아보는 데 그치지 않고 결과를 설명할 수 있습니다. 다음 실습에서는 알고리즘과 집계 규칙을 유지하면서 HDFS에서 입력을 제공하고 YARN으로 실행 자원을 관리합니다.
요약
상품의 등장을 Map 쌍으로 추적하고, Shuffle로 값을 묶으며, Reduce로 합쳤습니다. 실제 Hadoop WordCount 결과는 손으로 계산한 값 및 학습 도구와 일치했으며, 입력에 항목 하나를 추가했을 때 예상대로 바뀌었습니다.
로컬 실행기로 알고리즘에 집중했습니다. 다음에는 같은 알고리즘을 유지하면서 실제 YARN 애플리케이션이 HDFS 입력을 읽고 HDFS 결과를 만드는 방식을 배웁니다.



