반응형

1. 서론

이번 포스팅에서는 간단히 Hadoop의 hdfs와 mapreduce를 진행해보겠습니다.

2. hdfs

hdfs 는 기본적으로 알고계신 파일 시스템이라고 보셔도 무방합니다.

단, hdfs는 설정값에 따라 replication과 파일을 block 단위로 관리합니다.

간단히 진행할 hdfs 의 명령어는 아래와 같습니다.

 

  • cat 
  • appendToFile
  • ls
  • copyFromLocal
  • copyToLocal
  • count
  • cp
  • du
  • expunge
  • get
  • getfacl
  • getmerge
  • mkdir
  • moveFromLocal
  • mv
  • put
  • rm
  • rmr
  • setfacl
  • setfattr
  • setrep
  • stat
  • tail
  • test
  • text
  • touchz

먼저 위 명령어들을 알아보기 전에 간편히 작업하기 위해

아래 사진과 같이 hdfs 권한 검사의 체크를 제거해주세요.

파일 권한 체크를 해제하는 옵션입니다.

 

1) cat

 

리눅스의 cat과 동일합니다.

 

아래는 sample.txt 파일을 cat으로 확인한 예제입니다.

 

2) appendToFile

 

Local 파일을 hdfs 파일에 append 하기위한 명령어

 

아래는 로컬의 young이 들어있는 sample2.txt 파일을 hdfs의 sample.txt 에 append한 후 cat으로 확인하는 예제입니다.

 

3) ls

 

특정 디렉토리의 파일, 디렉토리를 보여주는 명령어

 

아래는 ls 명령어 예제입니다.

 

 

4) copyFromLocal

 

로컬 파일을 hdfs 로 복사하는 명령어 입니다.

 

아래는 로컬 sample3.txt 파일을 hdfs에 복사하는 예제입니다.

 

 

5) copyToLocal

 

이번엔 반대로 hdfs에 있는 파일을 로컬로 복사하는 명령어 입니다.

 

아래는 hdfs의 sample.txt 파일을 로컬로 복사하는 예제입니다.

 

6) count

 

hdfs의 디렉토리, 파일의 갯수를 카운트하여 보여주는 명령어 입니다.

 

아래는 /user/young의 count한 결과 사진입니다.

 

count는 [디렉토리 갯수, 파일 갯수, 전체 사이즈] 로 보여줍니다.

 

7) cp

 

cp는 hdfs내에서 복사하는 경우 사용하는 명령어입니다.

 

아래는 /user.young의 sample.txt 파일을 /user/geonyeong 디렉토리로 복사한 예제입니다.

 

 

8) du

 

특정 디렉토리 혹은 파일의 사이즈를 보여줍니다.

 

아래는 /user/young의 사이즈를 보여주는 예제입니다.

각 파일의 사이즈와 replication * 파일 size 인 총합도 보여줍니다.
아래 예제의 경우에는 replication이 3으로 filesize * 3이 노출되게 됩니다.

 

9) expunge

 

완전 삭제입니다.

 

hdfs dfs -expunge

 

 

 

 

 

반응형

 

 

 

 

 

 

 

10) get

 

copyToLocal과 같은 명령어입니다.

 

아래는 get 명령어의 예제입니다.

 

 

11) getfacl

 

hdfs의 특정 디렉토리 혹은 파일의 ACLs를 보여주는 명령어입니다.

 

아래는 getfacl 명령어의 예제입니다.

 

 

12) getmerge

 

hdfs의 파일을 append한 후 로컬로 다운로드받는 명령어입니다.

 

아래는 예제입니다.

 

 

13) mkdir

 

디렉토리를 생성하는 명령어

 

아래는 예제입니다.

 

 

14) moveFromLocal

 

로컬파일을 hdfs에 올립니다.

copy가 아닌 mv로 로컬 파일은 삭제됩니다.

 

아래는 예제입니다.

 

 

15) mv

 

hdfs 상에서 mv 명령어 입니다.

 

아래는 예제 입니다.

 

 

 

16) put

 

copyFromLocal 명령어와 동일합니다.

 

 

17) rm

 

hdfs 파일을 삭제 합니다.

 

아래는 예제입니다.

 

18) setfacl

 

hdfs의 파일, 디렉토리의 ACLs를 setting 하는 명령어입니다.

 

19) test

 

파일이 존재하는지 체크하는 명령어입니다.

아래는 명령어 옵션값입니다.

 

-e : 파일이 존재하면 return 0

-z : 파일 길이가 0이면 return 0

-d : 디렉토리면 return 0

 

아래는 예제입니다.

 

 

3. mapreduce

mapreduce를 수행하기 위해선 mapper와 reducer가 있는 빌드된 fat jar가 있어야합니다.

1. mapper만 존재해도 됩니다.
2. spring의 boot jar는 안됩니다. 이유는 맵리듀스가 mapper와 reducer의 full packager경로로 찾아야 하는데 boot jar의 경우에는 찾을 수 없기 때문입니다.

저는 mapreduce의 대표적인 예제인 wordcount를 진행하도록 하겠습니다.

 

우선 아래와 같이 예제 jar를 다운 및 압축을 해제합니다.

 

wget http://www.java2s.com/Code/JarDownload/hadoop-examples/hadoop-examples-1.2.1.jar.zip
unzip hadoop-examples-1.2.1.jar.zip

 

그후, 저는 아래와 같은 파일을 hdfs:/user/young에 올렸습니다.

 

 

이제 아래와 같이 wordcount 작업을 yarn에게 제출합니다.

 

hadoop jar <jar path> <main class> [input file path] [output directory path]

 

hadoop jar hadoop-examples-1.2.1.jar wordcount /user/young/sample.txt /user/young2

 

그럼 이제 아래와 같이 mapreduce 작업이 진행됩니다.

 

 

작업이 모두 완료되면 /user/young2에 결과 파일이 생성된것을 볼 수 있습니다.

 

 

파일 내용은 아래와 같이 wordcount 결과입니다.

 

 

4. 마무리

이번 포스팅에서는 hadoop의 hdfs와 mapreduce에 대해 간단한 예제를 진행하였습니다.

다음 포스팅에서는 hadoop 서비스 중 하나인 hive에 대해 간랸히 소개 및 예제를 진해하도록 하겠습니다.

 

반응형

'BigData > Hadoop' 카테고리의 다른 글

(4) Hive  (0) 2020.03.10
(2) Hadoop 설치  (0) 2020.03.05
(1) Hadoop에 대해  (0) 2020.03.04
반응형

1. 서론

이번 포스팅에서는 Hadoop Cluster 설치를 진행하겠습니다.

 

Hadoop 설치는 직접 각 서버에 들어가, Hadoop 패키지를 다운받아 모든 설정파일을 직접 수정하여 설치 할 수 있습니다.

 

하지만, 너무 번거롭고 설정 파일을 잘못 세팅하면 제대로 Hadoop Cluster 설치가 되지 않습니다.

 

이런 까다로운 설치로 인해, Hadoop Cluster 설치 및 관리를 간편하게 제공하는 서비스가 별도로 있습니다.

 

해당 서비스를 제공하는 기업은 아래 2가지가 있습니다.

 

  • Cloudera
  • Hortonworks

 

저는 위 2가지 중 Cloudera 기업의 Cloudera Manager를 통해 Hadoop Cluster 구축을 진행하도록 하겠습니다.

 

참고로, 2019년 1월 Hortonworks는 Cloudera로 합병이 되었습니다.

 

2. Hadoop Cluster 설치

저는 총 4대로 Hadoop Cluster를 구축하도록 하겠습니다.

추가로, sudo가 가능한 계정으로 진행하겠습니다.

 

1) 터널링

 

먼저, 각 서버들을 터널링해야 합니다.

 

ssh-keygen

 

1. ssh-keygen 명령어를 통해 각 서버에 public_key (id_rsa.pub)와 private_key (id_rsa)를 만들어 줍니다. (key 는 ~/.ssh 디렉토리에 생성됩니다.)

 

2. 각 서버의 public_key를 ~/.ssh/authorized_keys 파일에 추가해줍니다.

 

아래와 같이 authorized_keys 파일에 각 서버의 public_key 정보를 넣어주었습니다.

각 서버에도 동일하게 적용하여 줍니다.
mr 수행 시 각 데이터 노드는 연결해야 하기때문에 모든 노드는 터널링이 되어있어야합니다.

 

 

3. 수동 터널링 진행

 

처음 ssh 터널링 진행시 yes or no를 물어보는 구문이 나오며, yes를 통해 터널링이 이루어져야 합니다.

이를 위해서, 최초 한번 수동으로 터널링을 진행해야 합니다.

 

아래와 같이 스크립트를 만들어 진행하였습니다.

 

2)  symbolic link

 

cloudera manager은 hdfs, mapreduce 등 서비스들의 default 경로를 root directory 하위에 잡게됩니다.

 

대부분의 서버는, root가 아닌 별도 디렉토리에 disk가 넉넉히 마운트가 되어 있습니다.

 

저의 경우에도 아래와 같이 root에는 10GB만이 마운트되어 있는 조그만 VM을 사용하고 있어,

symbolic link를 걸어주도록 하겠습니다.

 

 

저는 아래와 같이 스크립트를 만들었습니다.

sudo mkdir -p /home1/irteam/opt/cloudera
sudo mkdir -p /home1/irteam/var/log
sudo mkdir -p /home1/irteam/var/lib
sudo mkdir -p /home1/irteam/dfs
sudo mkdir -p /home1/irteam/yarn
sudo mkdir -p /home1/irteam/impala
sudo mkdir -p /home1/irteam/var/log/cloudera-scm-alertpublisher
sudo mkdir -p /home1/irteam/var/log/cloudera-scm-eventserver
sudo mkdir -p /home1/irteam/var/lib/cloudera-scm-eventserver
sudo mkdir -p /home1/irteam/var/log/cloudera-scm-firehose
sudo mkdir -p /home1/irteam/var/lib/cloudera-host-monitor
sudo mkdir -p /home1/irteam/var/lib/cloudera-service-monitor
sudo mkdir -p /home1/irteam/var/log/hadoop-hdfs
sudo mkdir -p /home1/irteam/var/log/hive
sudo mkdir -p /home1/irteam/var/log/hue
sudo mkdir -p /home1/irteam/var/log/oozie
sudo mkdir -p /home1/irteam/var/log/spark
sudo mkdir -p /home1/irteam/var/log/hadoop-mapreduce
sudo mkdir -p /home1/irteam/var/lib/hadoop-yarn/yarn-nm-recovery
sudo mkdir -p /home1/irteam/var/log/hadoop-yarn
sudo mkdir -p /home1/irteam/var/lib/zookeeper
sudo mkdir -p /home1/irteam/var/log/zookeeper
sudo mkdir -p /home1/irteam/tmp

sudo ln -s /home1/irteam/opt/cloudera /opt/cloudera
sudo ln -s /home1/irteam/var/log/ /var/log
sudo ln -s /home1/irteam/var/lib/ /var/lib
sudo ln -s /home1/irteam/dfs/ /dfs
sudo ln -s /home1/irteam/yarn/ /yarn
sudo ln -s /home1/irteam/impala/ /impala
sudo ln -s /home1/irteam/var/log/cloudera-scm-alertpublisher /var/log/cloudera-scm-alertpublisher
sudo ln -s /home1/irteam/var/log/cloudera-scm-eventserver /var/log/cloudera-scm-eventserver
sudo ln -s /home1/irteam/var/lib/cloudera-scm-eventserver /var/lib/cloudera-scm-eventserver
sudo ln -s /home1/irteam/var/log/cloudera-scm-firehose /var/log/cloudera-scm-firehose
sudo ln -s /home1/irteam/var/lib/cloudera-host-monitor /var/lib/cloudera-host-monitor
sudo ln -s /home1/irteam/var/lib/cloudera-service-monitor /var/lib/cloudera-service-monitor
sudo ln -s /home1/irteam/var/log/hadoop-hdfs /var/log/hadoop-hdfs
sudo ln -s /home1/irteam/var/log/hive /var/log/hive
sudo ln -s /home1/irteam/var/log/hue /var/log/hue
sudo ln -s /home1/irteam/var/log/oozie /var/log/oozie
sudo ln -s /home1/irteam/var/log/spark /var/log/spark
sudo ln -s /home1/irteam/var/log/hadoop-mapreduce /var/log/hadoop-mapreduce
sudo ln -s /home1/irteam/var/lib/hadoop-yarn/ /var/lib/hadoop-yarn
sudo ln -s /home1/irteam/var/log/hadoop-yarn /var/log/hadoop-yarn
sudo ln -s /home1/irteam/var/lib/zookeeper /var/lib/zookeeper
sudo ln -s /home1/irteam/var/log/zookeeper /var/log/zookeeper

sudo chmod -R 777 /home1/irteam

 

cloudera에서 default경로로 사용하고 있는 /var/log, /var/lib 등을 home1/irteam 디렉터리 하위로 link를 생성했습니다.

 

3) /etc/hosts 수정

 

/etc/hosts에 각 서버의 ip와 hostname을 등록해 줍니다.

 

저는 아래와 같이 등록해주었습니다.

 

 

 

 

 

반응형

 

 

 

 

 

 

 

 

4) cloudera manager installer binary 다운로드 및 실행

 

이제 사전준비는 끝났습니다.

실제로 Cloudera Manager를 다운받아 실행하도록 하겠습니다.

 

저는 6.3.0 버전을 다운받아 진행하도록 하겠습니다.

(저는 4번 서버에서 실행하도록 하겠습니다.)

 

아래와 같이 다운로드 및 실행하여 주세요.

wget https://archive.cloudera.com/cm6/6.3.0/cloudera-manager-installer.bin
chmod 755 cloudera-manager-installer.bin
sudo ./cloudera-manager-installer.bin

 

 

실행한다면 아래와 같이 뜰것입니다.

 

모두 next 및 yes를 눌러 설치를 진행해 주세요.

 

 

위의 설치 진행이 끝난다면 7180 port로 web ui에 접근할 수 있습니다. ( default id, password는 admin/admin 입니다. )

 

아래는 ui에 최초 접근했을때의 화면입니다.

 

 

admin/admin으로 로그인 후 next를 눌러 넘어가줍니다. ( edition을 선택하는 화면에서는 무료를 선택합니다. )

 

계속 next를 누르다 보면 Specify Hosts 부분이 나오게됩니다.

 

여기에서는 각 서버들을 입력해줍니다.

 

저의 경우는 1~3번 서버만 설치진행하도록 하겠습니다. ( 4번 서버는 manager 전용 서버로 사용하기 위해서 입니다. )

 

 

각 서버를 line by line으로 입력하여 검색버튼을 누르면 검색됩니다.

 

그 후, cloudera manager에서 default로 권장하는 parcel와 cdh 버전을 선택하여 next 해줍니다.( 기본적으로 선택되어져 있습니다. )

 

이제 설치하기 위해 각 서버에 접근하기 위해 위에서 ssh 터널링 했던 정보를 넣습니다.

 

아래와 같이 계정은 sudo가 가능한 계정을 기입하며, cloudera manager가 설치된 서버의 private key 파일을 업로드합니다.

 

 

입력 후 next 버튼을 누릅니다.

 

아래와 같이 각 서버에 설치가 진행되는 화면으로 이동하게 됩니다.

 

 

agent가 설치가 되었으면 next를 눌러 parcel도 설치를 진행합니다.

parcel까지 설치가 완료되었다면 Inspect Cluster가 나옵니다.

 

여기서 I understand the risks, let me continue with cluster setup. 를 선택하여 설치를 진행해주세요.

 

이제 Select Services화면이 나오고, 여기는 제가 설치할 서비스들을 선택하는 화면입니다.

 

저의 경우, 향후 spark를 사용할것을 고려하여 Data engineering을 선택하겠습니다.

 

 

다음은 각 호스트별로 어떤 서비스를 실행시킬지 선택하는 화면입니다.

 

아래와 같습니다.

 

 

이후, 계속 next를 눌러 서비스를 설치 및 실행시켜줍니다.

(중간에 DB 설정이 있는데 기본으로 내장되어 있는 posrgresql을 사용하였습니다.) 

 

이제 설치가 완료되었습니다.

 

설치가 완료된다면 아래와 같이 주의 표시들이 있을 텐데요.

 

이것은 heap log 디렉토리를 cloudera manager가 default로 /tmp로 잡아서입니다.

이경우, 아래와 같이 해당 서비스의 구성 텝에서 바라보는 디렉토리를 변경할 수 있습니다.

 

 

hdfs의 경우 default block replication 수는 3입니다.
저의 경우 데이터 노드를 2개만 지정하였기 때문에, 계속 경고가 떠있을 텐데요.
이를 위해, 추가로 4번 호스트를 hdfs의 데이터 노드, yarn의 node manager의 역할로 추가하였습니다.

3. 마무리

이번 포스팅에서는 간략히 Hadoop 설치를 진행해봤습니다.

 

다음 포스팅에서는 간단한 Hadoop 사용법을 진행하도록 하겠습니다.

반응형

'BigData > Hadoop' 카테고리의 다른 글

(4) Hive  (0) 2020.03.10
(3) Hadoop 사용법  (0) 2020.03.09
(1) Hadoop에 대해  (0) 2020.03.04
반응형

 

이번 문제는 레몬에이드 판매 문제입니다.

 

레몬에이드는 각 5달러입니다.

인자로 받는 list는 고객이며, 숫자는 각 고객이 보유한 달러입니다. ( 5, 10, 20만 존재한다고 가정합니다. )

 

각 순서대로 레몬에이드를 끝까지 팔 수 있는지에 대한 문제입니다.

 

단, 판매 처음 거스름돈은 0달러인 채로 시작하게 됩니다.

 

아래는 제가 풀은 python code입니다.

 

class Solution:
    def lemonadeChange(self, bills: List[int]) -> bool:
        change = [0, 0]

        for bill in bills:
            if bill == 5:
                change[0] += 1
            elif bill == 10:
                if change[0] > 0:
                    change[0] -= 1
                    change[1] += 1
                else: return False
            else:
                if change[0] > 0 and change[1] > 0:
                    change[0] -= 1
                    change[1] -= 1
                elif change[0] > 2:
                    change[0] -= 3
                else: return False
        return True

 

저의 경우는 거스름돈인 5달러와 10달러를 관리할 list를 초기에 생성합니다.

( list[0] - 5달러 갯수, list[1] - 10달러 갯수 로 가정하였습니다. )

그 후, 각 [5, 10, 20] 달러가 들어왔을때를 가정하여 문제를 풀었습니다.

 

1. 5달러인 경우

  • 거스름돈이 5달러가 추가되어 list 0번째 값을 1 증가시킵니다.

2. 10 달러인 경우

  • 거스름돈 5달러를 주어야하기 때문에 list의 0번째는 1 감소시키며, list의 2번째는 1 증가시킵니다.

  • 거스름돈인 5달러가 없는 경우에는 실패로 간주하여 False를 반환합니다.

3. 20달러인 경우

  • 먼저 10달러짜리와 5달러로 거스름이 가능하다면,  list의 0번째, 1번째 모두 1 감소시킵니다.

( 10달러를 받을 시 5달러로 거스름을 주어야 하기 때문에 10달러, 5달러 조합을 먼저 if 문에 걸리게 해야 합니다. )

  • 5달러짜리로만 거스름이 가능하다면, list의 0번째를 3 감소시킵니다.

  • 거스름이 불가능하다면 실패로 간주하여 False를 반환합니다.

 

 

거스름이 가능한지에 대한 문제로 배열에 20달러를 보유한 케이스는 제외하였습니다.

 

감사합니다.

 

 

반응형
반응형

1. 서론

이번 포스팅에서는 대용량 처리 프레임워크인 Hadoop에 대해 간략히 소개하려고 합니다.

 

소개 목차로는 아래와 같습니다.

 

  • 하둡이란?
  • Hdfs란?
  • mapreduce란?
  • yarn이란?

 

2. 하둡이란?

하둡은 아파치에서 오픈소스로 제공한 분산 처리 프레임워크입니다.

여러개의 컴퓨터를 클러스터화 하여 대용량 데이터를 분산처리하도록 하는것이 목적입니다.

 

그로인해, 하둡은 빅데이터의 열쇠라고도 불리기도 합니다.

 

그렇다면, 하둡은 대략적으로 무엇을 하는지 아래 사진을 통해 설명하도록 하겠습니다.

 

 

1) NameNode

 

하둡에서는 데이터를 block( default = 64M ) 단위로 관리합니다. ( 아래 설명할 HDFS 입니다. )

NameNode는 데이터 block이 어디 DataNode에 있는지를 관리합니다.

 

관리의 의미로는 read시 어느 데이터 노드에 작업을 할당해야하는지와 write시 여유로운 데이터 노드를 찾아 작업 할당을 할지를 의미합니다.

 

만약, NameNode가 죽는다면 관리하고 있던 정보가 사라져 데이터를 얻을 수 없게됩니다.

이를 위해 하둡에서는 별도 FS에 데이터를 동기화하며, NameNode가 죽었을 시

Secondary NameNode는 별도 FS에서 NameNode의 관리 정보를 가져와 새 NameNode에게 할당합니다.

 

마지막으로 NameNode는 메타데이터를 관리하기 위해 EditLog와 FsImage 파일을 사용합니다.

 

  • EditLog = HDFS의 메타데이터에 대한 모든 변화를 기록하는 로그 파일.
  • FsImage = 파일 시스템의 네임스페이스(디렉토리명, 파일명, 상태 정보)와 파일에 대한 블록 매핑 정보를 저장하는 파일. 

2) Secondary NameNode

 

위 EditLog와 FsImage를 주기적으로 병합하는 역할을 합니다.

 

하둡 2.x 버전 부터는 Secondary NameNode를 두지 않고 NameNode를 HA 구성으로 아키텍쳐를 변경하였습니다.
이때, HA 구성한 NameNode는 Active-Standby 구조입니다.

 

3) DataNode

 

데이터노드는 파일 block을 저장하고 제공하는 역할을 합니다.

Client가 데이터 읽기,쓰기 요청을 보낸다면 먼저 NameNode는 요청 데이터에 맞는 데이터 노드를 탐색 후

Client는 탐색 된 DataNode와 통신하여 데이터를 읽고 쓰게됩니다.

 

 

또한, DataNode는 NameNode에게 자신의 정보를 전달합니다.

 

  • 클러스터가 처음 시작될 때, 각 DataNode는 block 정보를 NameNode에게 전달
  • 주기적으로 NameNode에게 Heartbeat와 블록 목록 정보를 전달
  • 변경사항이 발생할 때마다 NameNode에게 변경사항 전달

 

4) JobTracker

 

JobTracker는 일반적으로 NameNode에서 실행시키는 하나의 프로세스입니다.

 

역할로는 TaskTracker의 리소스를 관리하여, MapReduce 작업 요청시 작업을 알맞는 TaskTracker에서 할당합니다. 

또한, TaskTracker가 실패하면 다른 TaskTracker에게 재할당 합니다.

 

5) TaskTracker

 

TaskTracker는 실제로 Task를 처리하는 프로세스입니다.

 

DataNode에는 하나의 TaskTracker만 존재하며, 여러개의 Map과 Reduce를 실행합니다.

 

여러개의 Map과 Reduce를 수행할 수 있기에, 동시에 여러 Task가 처리 가능하고 max Task 갯수는 설정으로 조절가능합니다.

 

 

 

 

 

반응형

 

 

 

 

 

 

 

3. Hdfs란?

Hdfs는 Hadoop Distributed File System의 약자로 하둡 시스템에서 제공하는 파일 시스템입니다.

 

하둡 클러스터의 데이터 노드들에 데이터를 block 단위로 저장하여 대용량 파일 저장이 가능합니다.

 

장점은 아래와 같습니다.

 

  • block 단위로 파일을 나눠 적재. ( default = 64M )
  • 파일에 대해 replication 수행. ( default =3 )
  • Scale-out이 가능으로 인해 필요시 용량 증설 가능.
  • 스트리밍 데이터 엑세스 지원
  • 저사양 하드웨어를 클러스터화하여 고성능 제공

 

4. mapreduce란?

mapreduce는 대용량 데이터를 분산처리하기 위한 모델입니다.

 

하둡에서 제공하는 MapReduce는 아래 그림으로 설명이 됩니다.

 

 

 

하둡의 TaskTracker는 각 Mapper와 Reducer를 생성합니다.

 

Mappper는 input 데이터를 line-by-line으로 읽으며 (key, value)로 만들어 주는 역할을 수행하며,

Reducer는 Mapper에서 넘어온 (key, value)를 merge하는 역할을 수행합니다.

 

이때, Mapper와 Reducer 사이에는 Shuffliing 과정이 존재합니다.

 

Shuffliing은 Mapper의 출력데이터를 Reducer에 전달하기 위한 일련의 과정입니다.

 

이 일련의 과정에서는, 파티셔너와 정렬이 존재합니다.

 

Mapper의 출력데이터는 memory 버퍼에 저장 후 버퍼가 기준치만큼 차게되면 disk에 write하게 됩니다.

파티션을 생성하며, 파티셔너는 동일 key에 대해  List<value>로 묶어주는 역할을 합니다.

 

또한, Mapper 끝나기 직전 disk에 write한 파일들은 정렬된 한개의 파일로 만들어 Reducer에게 전달하게 됩니다.

 

그렇기 때문에, 위 그림의 shuffling 과정에서 key 별로 value list를 가지고 있으며, Bear -> Car -> Deer와 같이 정렬된 것을 볼 수 있습니다.

 

5. yarn이란?

yarn은 Yet Another Resource Negotiator의 약어로 리소스 할당 및 관리를 위해 나온 서비스입니다.

기존 Mapreduce의 jobtracker - tasktracker에는 아래와 같은 단점이 존재했습니다.

 

  • 맵리듀스의 단일 고장점
    • jobtracker는 모든 mapreduce의 요청을 받으며, jobtracker에 문제가 생긴다면 모든 mapreduce는 수행할 수 없는 fail point 입니다.
  • 클러스터의 확장성
    • 단일 클러스터에서 최대 4천대,  동시 실행 태스크 4만개가 한계
  • 맵리듀스의 리소스 관리
    • slot이라는 개념으로 자원을 관리함으로 mapper와 reducer의 자원을 효율적으로 사용하지 못함.
    • mapreduce가 아닌 다른 서비스로 인한 자원 영향은 파악 불가능.

 

위의 단점들로 인해, 아래와 같이 yarn을 Mapreduce대신 hdfs 위에 올리는 아키텍쳐로 변경하게 되었습니다.

yarn은 총 4개의 새로운 컴포넌트들을 제공하고 있습니다.

 

  • resource manager
  • node manager
  • container
  • applicaton master

1) resource manager

 

기존 jobtracker를 대체하는 컴포넌트입니다.

클러스터의 자원 관리, 태스크의 스케쥴링, 태스크가 수행할 수 있는 노드를 찾아주는 역할을 담당합니다.

 

2) node manager

 

기존 tasktracker를 대체하는 컴포넌트입니다.

모든 데이터 노드에서 수행되며 container를 생성하여 container의 라이프 사이클을 모니터링하는 역할을 수행합니다.

 

3) container

 

데이터 노드의 리소스 메트릭이라고 생각하시면 됩니다. ( CPU, Disk, Memory, Network 등 )

node manager는 이 container의 메트릭 상태를 보고 resource manager에게 보고하게 됩니다.

 

4) application master

 

하나의 application을 관리하는 컴포넌트입니다.

client가 2개의 태스크를 요청한다면 2개의 application master가 생성되어 가 application를 관리하게 됩니다.

 

 

이 4개의 서비스로 인해 위의 jobtracker의 단점들을 해결하였습니다.

 

마지막으로, 아래는 yarn의 아키텍쳐입니다.

 

 

6. 마무리

이번 포스팅에서는 간략히 Hadoop에 대해 알아봤습니다.

 

다음 포스팅에서는 Hadoop 설치 포스팅을 진행하도록 하겠습니다.

 

 

 

반응형

'BigData > Hadoop' 카테고리의 다른 글

(4) Hive  (0) 2020.03.10
(3) Hadoop 사용법  (0) 2020.03.09
(2) Hadoop 설치  (0) 2020.03.05
반응형

 

 

이번 문제는 두개의 int 리스트를 인자로 받습니다.

첫번째 인자의 의미는 각 아이들이 만족할 수 있는 쿠키 크기입니다.

두번째는 인자의 의미는 현재 가지고 있는 쿠키입니다.

 

첫번째 예시를 본다면, 3명의 아이들은 각 1, 2, 3의 쿠키를 원합니다.

하지만 현재 쿠키는 1, 1 만 가지고 있어 아이 한명을 충족시킬 수 있습니다.( 그래서 output이 1입니다. )

 

두번째 예시를 본다면, 2명의 아이들은 각 1, 2의 쿠키를 원하며

쿠키는 1, 2, 3을 가지고 있어 두명의 아이를 모두 충족시킬 수 있습니다.( 그래서 output은 2입니다. )

 

 

저의 경우는 아래와 같이 풀었습니다.

 

class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        g.sort()
        s.sort()
        res = 0
        idx = 0

        for greedy in g:
            for j in range(idx, len(s), 1):
                if greedy <= s[j]:
                    res += 1
                    idx = j+1
                    break
        return res

 

아이들의 원하는 쿠키를 가지고 있는지 체크를 하며 있다면, 다음 아이로 대상을 바꾸도록 하였습니다.

단, 많은 아이를 충족하여야 하기 때문에 욕심이 적은 아이에게는 딱 맞는 쿠키를 주어야 합니다.

 

그렇기 때문에, 체크하기 전 두 리스트를 sorting 작업을 추가하였습니다.

 

감사합니다.

반응형
반응형

 

s 문자열이 t 문자열의 subsequence인지 여부를 반환하는 문제입니다.

 

subsequence의 경우에는 문자의 연속성 또한 맞아야 합니다.

예시로 abcde 문자열에서 ace는 subsequence가 맞지만, aec는 맞지 않다고 나와있습니다.
이것은, 연속성이 맞지 않기 때문입니다.

 

그렇기 때문에, 단순히 for문을 통해 문자 비교를 하고 동일한 문자를 찾는다면, 다음 문자부터 재탐색하여 찾으시면 됩니다.

 

만약, 탐색이 되지 않는다면 주어진 문자열은 subsequence가 아닌 것으로 판명되어집니다.

 

아래는 제가 풀은 python code입니다.

 

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        index = 0
        for s_char in s:
            flag = True
            for t_idx in range(index, len(t), 1):
                if t[t_idx] == s_char:
                    index = t_idx +1
                    flag = False
                    break
            if flag:
                return False
        return True

 

감사합니다.

반응형
반응형

 

주어진 int 배열은 하나의 주가이며, 이 주가에서 얻을 수 있는 최대 수익을 출력하는것이 문제입니다.

 

낮은가격에 사 높은 가격에 판다면 이익을 얻습니다.

 

그렇기 때문에, 현재 시점의 주가와 다음 시가의 주가를 비교하여 차익이 있는 것들만 sumation하면 되는 문제입니다.

(차익이 난다면 바로 팔기때문에 greedy 분류의 문제입니다.)

 

아래는 제가 푼 python 코드 입니다.

 

from typing import List

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        res = 0
        prices_len = len(prices)
        for i in range(0, prices_len, 1):
            if i+1 < prices_len and prices[i] < prices[i+1]:
                res += (prices[i+1] - prices[i])
        return res

if __name__ == '__main__':
    s = Solution()
    s.maxProfit([7,1,5,3,6,4])

 

저의 경우, 배열의 인덱스를 넘지 않기 위해 if 문에 다음 인덱스가 있는지의 체크가 추가되었습니다.

 

감사합니다.

반응형

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

leetcode - Maximize Sum Of Array After K Negations  (0) 2020.03.11
leetcode - Walking Robot Simulation  (2) 2020.03.10
leetcode - Lemonade Change  (0) 2020.03.05
leetcode - Assign Cookies  (0) 2020.03.04
leetcode - Is Subsequence  (0) 2020.03.03
반응형

1. 서론

이번 포스팅에서는 Effective-Java 3에 대해 공부한 내용을 공유하고자 합니다.

 

'효율적으로 자바 프로그램 작성하는 방법은 이러한 것들이 있구나' 라는 전제로 포스팅을 보시면 되겠습니다.

 

2. EffectiveJava

 

1. 박싱타입을 사용 X, 기본 타입을 사용

 

박싱타입이 아닌 기본타입을 사용해야 하는 이유는 아래와 같습니다.

 

  • 기본 타입은 유효한 값을 가지는 반면 박싱타입은 null을 가질 수 있어 위험도 증가.
  • 기본 타입은 박싱타입에 비해, byte가 적어 메모리, 시간 높은 성능.
  • 값 == 비교시 박싱타입의 경우에는 정확한 비교가 되지 않음.

 

2. 자원 해제가 필요한 클래스의 경우 AutoCloseable 인터페이스를 구현

 

자원 해제가 필요한 경우 AutoCloseable 인터페이스를 구현해야 합니다.

 

AutoCloseable 은 아래와 같이 close 메소드가 선언되어 있습니다.

 

void close() throws Exception;

 

 

AutoCloseable 을 구현해야 하는 이유는 간단합니다.

java 7에서 제공되는 try-with-resources를 사용하기 위해서는 이 AutoCloseable 인터페이스를 구현해야 하기 때문입니다.

 

3. util 클래스의 경우 private한 생성자를 정의하여 객체 생성의 방어로직을 넣자.

 

util 클래스는 public static 함수들을 가진 클래스를 의미합니다.

static 함수들만을 가지고 있기 때문에 객체를 생성할 이유가 없는 클래스입니다.

 

그렇기 때문에, 개발자의 실수를 방지하기 위해 util 클래스는 private 생성자를 두어 

instance 생성이 되지 않도록 합니다.

 

4. 상속 클래스의 경우 문서화 하라.

 

상속 클래스의 경우에는 조그만 변경에도 영향이 많이 갈 수 있어, 영향도를 문서화해야 합니다.

 

문서화는 class 혹은 각 method 위에 주석으로 설명을 해두는것을 추천합니다.

 

 

5. 추상클래스로 만든것은 인터페이스로 대체하는게 나을지 고려!!

 

추상클래스의 자식클래스는 상속 개념으로 동등이 아닌 하위 계층이 되며, 인터페이스는 동일한 계층으로 분류가 됩니다.

 

java의 경우 다중상속이 지원되지 않습니다. 이것은, 추상클래스는 최대 한개까지만 상속이 가능합니다.

 

대신, 인터페이스의 경우에는 계층구조를 가지게되는 것이 아니기 때문에 다중구현이 되며

java 내에서도 명시적으로 implements로 되어 있는 이유입니다.

 

6. inner 클래스의 경우 바깥 인스턴스에 접근할일이 없다면 무조건 static으로 만들어서 사용.

 

inner 클래스를 static으로 사용하지 않을 시 위험한 점은 아래와 같습니다.

 

  • 바깥 인스턴스로의 숨은 외부 참조를 갖게 됨.
  • 참조의 저장은 시간과 공간이 소비되며 gc가 바깥 인스턴스를 수거하지 못할 수 있음
    • 이는 메모리 누수로 이어지는 길.

 

7. 제네릭의 경우 로타입을 없애고 비한정적 와일드카드 타입을 사용하라.

 

우선, 로 타입의 정의는 아래와 같습니다.

 

매개변수화 타입이 지정이 안된 것 -> ex) List

로 타입은 java 에서 제네릭이 지원되기 이전의 호환성으로인해 서비스 중이지만, 권장 부분이 아닙니다.

 

그 이유는, 로타입의 경우 컴파일에서는 정상적으로 수행되나, 실행 시 런타임 에러를 내뱉기 때문입니다.

 

 

8. 제네릭의 경고를 제거할 수는 없지만 타입안전하다고 확신할수 있다면 @SuppressWarning("unchecked")를 사용하자.

 

이것은 다른 개발자에게 알림을 위해 사용하는것이므로, 가능한한 좁은범위로 사용해야합니다.

또한 경고를 무시해도 안전한 이유를 항상 주석으로 남겨야 합니다.

 

 

 

 

 

반응형

 

 

 

 

 

 

 

9. 배열보다는 리스트를 사용.

 

array는 공변(covariant)이며, List는 불변입니다.

공변은 계층구조를 가지며, super의 변화에 sub도 영향이 가는것을 의미합니다.
불변은 공변과 반대로 super의 변화에 영향이 없다는 것을 의미합니다.

 

공변인 array의 경우에는 type mistmatch경우 컴파일 시점에서 잡아내지 못합니다.

아래는 그 예입니다.

 

Object[] array = new Long[1];
array[0] = "Young's blog";

 

하지만, 불변인 list의 경우에는 컴파일 시점에서 잘못됨을 알 수 있습니다.

아래는 그 예입니다.

 

List<Object> list = new ArrayList<Long>();

 

배열은 이러한 타입 안전성이 떨어져 제네릭과도 어우러지지 않습니다.

 

그로인해, 배열 사용보다는 리스트를 추천합니다.

 

10. Object를 사용하는 코드는 되도록이면 제네릭을 활용하자.

 

Object의 경우 형변환을 하는 비용을 감수해야한다.

하지만 제네릭으로 변환 시 형변환의 비용이 들지 않아 성능면에서 이득을 볼 수 있습니다.

 

11. 가변인수보다는 List 사용

 

가변인수는 인자로 받은 사이즈만큼 배열을 생성하여 값을 세팅하여 사용하게 됩니다.

 

이 경우, size가 0인 가변인수를 받는 경우에는 컴파일 시점이 아닌 런타임시점에 실패하게 됩니다.

또한,  jdk8의 stream 함수를 사용하기 위해서는 list로 타입 변환을 해야하는 비용도 들게 됩니다.

 

이로인해, 가변인수를 사용하기 보다는 애초에 List를 사용하는 것을 추천합니다.

 

12. 정의하려는게 타입이라면 마커 인터페이스를 사용하자.

 

마커 인터페이스는 마커 어노테이션과 다르게 2개의 이점을 가지고 있습니다.

 

  • 구현 클래스의 인스턴스들을 구분하는 타입으로 사용 가능.
  • 어노테이션의 경우 모든 클래스에 적용이 가능한 반면, 인터페이스는 자신을 구현한 클래스만을 구현 클래스임을 보장하는 점입니다.

 

13. 익명클래스 -> 람다 -> 메서드 참조

 

익명클래스가 있다면 람다로 대체하는것을 고려해보자.

사실상 수행에 있어 다른점은 없다, 그 이유는 모두 class 파일로의 변환시에는 같은 byte 코드로 되어 있기 때문이다.

 

하지만, 람다로 대체하는 이유는 좀 더 쉽게 표현이 가능하다는 점입니다.

이것은, 개발자에게 매우 큰 이점을 가져다 줍니다.

 

또한, 타입 추론을 지원하여 더욱 개발의 편의성을 제공합니다.

 

여기서, 람다의 편의성을 능가하는것이 메서드 참조입니다.

 

대표적으로 아래와 같은 예가 있습니다.

 

map.merge(key, 1, (count, incr) -> count + incr); // -> 람다
map.merge(key, 1, Integer::sum); // -> 메서드 참조

 

코드만 보기에도 간결해진것을 볼 수 있습니다.

 

14. null 검사는 자바의 Objects.requireNonNull 사용하기

 

Objects.requireNonNull의 경우 null 체크와 null인 경우 npe의 message도 정의할 수 있어,

매우 간편하며 명시적인 메소드입니다.

 

15. 컬렉션의 반환은 null이 아닌 빈 컬렉션을 반환해라.

 

null은 위에서 말한것처럼 프로그램에서 매우 치명적입니다.

그로인해, 컬렉션은 빈 컬렉션을 반환하게하여 null을 참조하는것을 막아야 합니다.

 

16. int, long, double을 반환하는 optional은 OptionalInt, OptionalLong, OptionalDouble을 사용하자.

 

기본타입의 Optional 반환을 위해 박싱타입으로 변환하지 말고.

Optional에서 제공하는 OptionalInt, OptionalLong, OptionalDouble을 사용하자.

 

조금이나마, 성능저하가 덜하다.

 

17. 정확한 계산이 필요한 경우에는 double과 float는 버리고 int, long, BigDecimal을 사용해야 한다.

 

float, double은 과학과 공학 계산용으로 설계되었다.

이는, 넓은 범위의 수를 빠르게 정밀한 근사치로 계산되어진다.

 

그렇기 때문에, 정확한 계산 시에는 int, long, BigDecimal를 사용해야 합니다.

 

18. 문자열 연결의 경우 StringBuilder를 사용하자.

 

문자열 연결의 경우, 아래와 같이 하는 경우가 있습니다.

 

String sample = "1" + "-" + "2";

이 방법은 계속 다른 String을 생성하여 만들기 때문에 성능면에서 매우 좋지 않습니다.

 

이를 해결하기 위해 java에서는 StringBuilder가 있습니다.

 

사용 예시는 아래와 같습니다.

 

String sample = new StringBuilder().append("1").append("-").append("2").toString();

 

StringBuilder는 '+' 사용보다 일반적으로 5.5배가 성능면에서 유리합니다.

 

19. 객체는 인터페이스를 사용해서 참조하자

 

객체 생성 시 인터페이스가 있다면 인터페이스를 이용한 객체를 생성해야 합니다.

 

예로는 아래와 같습니다.

 

List<String> list = new ArrayList<>(); // - 좋은 예
ArrayList<String> list = new ArrayList<>(); // - 나쁜 예

 

 

 

인터페이스 참조를 한다면, 다른 구현 클래스의 참조가 필요 시에 코드가 유연하게 됩니다.

 

만약, 인터페이스가 존재하지 않는다면 필요한 기능을 만족하는 가장 덜 구체적인 클래스를 참조하도록 합니다.

 

20. 리플렉션 코드는 인터페이스로 가능하면 대체해라

 

리플렉션의 단점은 아래와 같습니다.

 

  • 컴파일 타임 시 타입 검사가 주는 이점을 하나도 누릴 수 없습니다.
  • 코드가 지저분해지며 장황해집니다.
  • 성능에 매우 악영향을 끼칩니다.

이러한 이유로 리플렉션 코드는 최대한 배제하는것을 추천합니다.

 

21. Exception, RuntimeException, Throwable, Error는 직접사용하지 말고 이를 구현한 자식 예외 클래스 혹은 커스텀 예외를 사용하자.

 

Exception, RuntimeException, Throwable, Error들은 여러 Exception들의 상위 클래스로서

정확한 어떠한 예외인지 판단하기에는 모호합니다.

 

그렇기 때문에, 상위 클래스를 구현한 예외 클래스 사용 혹은 custom 예외 클래스 사용을 권장합니다.

 

 

22. 시간 간격을 잴때는 System.currentTimeMillis 보다는 System.nanoTime을 사용하자

 

System.nanoTime은 더 정밀하고, 시스템의 실시간 클락의 변동에도 영향을 받지 않는 장점을 가지고 있습니다.

 

24. 쓰레드 보다는 실행자, 태스크, 스트림을 애용하자.

 

java.util.concurrent 패키지에는 실행자 프레임워크라고 하는 인터페이스 기반의 유연한 태스크 실행 기능을 가지고 있습니다.

 

장점으로는 아래와 같습니다.

 

  • 특정 태스크가 완료되기를 기다릴 수 있습니다.
    • get 메서드
  • 태스크 모음 중 하나 혹은 모든 태스크가 완료되기를 기다릴 수 있습니다.
    • invokeAny, invokeAll 메서드
  • 실행자 서비스가 종료하기를 기다릴 수 있습니다.
    • awaitTermination 메서드
  • 완료된 태스크들의 결과를 차례로 받을 수 있습니다.
    • ExecutorCompletionService 클래스
  • 태스크를 특정 시간에 혹은 주기적으로 실행할 수 있습니다.
    • ScheduledThreadPoolExecutor 클래스

 

25. 동기화 문제일때, Collections.synchronizedMap -> ConcurrentHashMap을 사용

 

Collections.synchronizedMap하나의 쓰레드가 전체 컬렉션의 모든 자원을 lock을 걸게됩니다.

 

하지만, ConcurrentHashMap의 경우 필요한 부분만을 lock을 걸어 안정적이며 성능의 이점을 가져다 줍니다.

 

3. 마무리

이번 포스팅에서는 Effective-Java에 대해 포스팅 하였습니다.

 

감사합니다.

반응형
반응형

1. 서론

이번 포스팅에서는 테스트 code에 대해 진행하려고 합니다.

 

먼저, 테스트 코드 작성 시 알아야 할 점이 5가지가 있습니다.

 

1) 빠르게 Fast

 

테스트 코드는 빨라야합니다.

테스트가 느리다면 개발자는 테스트 코드를 자주 돌릴생각이 들지 않기 때문입니다.

 

2) 독립적으로 Independent

 

테스트 코드는 독립적이고, 어떤 순서로 실행하여도 문제가 있으면 안됩니다.

테스트 코드가 독립적이지 않다면, 한개의 실패는 나머지 테스트 코드에도 영향을 줄 것입니다.

 

결국, 실패의 원인을 찾는데 오랜시간이 소모하게 됩니다.

 

3) 반복가능하게 Repeatable

 

테스트는 어떤 환경에서도 반복 가능해야 합니다.

운영, 개발, QA 환경 등 테스트는 어떤 환경에서도 수행이 반복적으로 가능해야 합니다.

 

4) 자가검증하는 Self-validating

 

테스트는 bool 값으로 결과를 판단해야 합니다. 검증하려는 값이 모두 bool이여야 한다는 의미가 아닙니다.

테스트 수행 후 비교한 값의 판단은 bool 값을 통해 자가 검증해야 한다는 의미입니다.

 

5) 적시에Timely

 

테스트 코드는 적시에 작성해야 합니다.

 

단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현해야 합니다.

그로인해, 테스트하기 용이하도록 실제 코드를 작성할 수 있기 때문입니다.

 

저는 실제코드를 작성 후 테스트 코드를 작성할 때가 있습니다.
그 경우, 실제 코드를 테스트하기 용이하도록 리팩토링 작업이 들어가는 경우가 왕왕 발생하곤 합니다.

 

이제, Clean Code에서의 테스트 코드를 소개하도록 하겠습니다.

 

 

 

 

 

반응형

 

 

 

 

 

 

2. 테스트 코드 또한 실제 코드처럼 

테스트 코드 또한 실제 코드처럼 작성해야합니다.

 

이는, 가독성, 중복 제거, 성능을 고려하여 설계 및 개발을 해야 한다는 의미입니다.

 

그로인해, 아래와 같은 3가지를 지키게 됩니다.

 

  • 빠르게 Fast
  • 독립적으로 Independent
  • 반복가능하게 Repeatable

3.  Asert 클래스의 equals를 사용하여 expected와 existed가 한눈에 보이도록

테스트 코드 작성시에는 Asert 클래스의 equals를 사용하여

무엇을 테스트하는지 expected와 existed를 명시적으로 해야합니다.

 

4. 테스트 함수당 개념 하나만

테스트 함수는 한개의 개념만을 테스트하여야 합니다.

2개 이상의 개념이 한 테스트에 있다면 독립적으로 Independent에 위반됩니다.

 

이는, 무엇을 테스트하는지가 모호해지며 나중에는 결국 테스트 코드로서의 의미를 잃어버리게 될 것입니다.

 

5. 마무리

이번 포스팅에서는 테스트 Code에 대해 포스팅 하였습니다.

 

이렇게, Clean Code 책을 읽으며 제 나름대로 정리한 1~3의 포스팅을 완료했습니다.

 

감사합니다.

반응형
반응형

1. 서론

이번 포스팅에서는 성능 & 안전을 고려한 Code에 대해 진행하려고 합니다.

 

Clean Code에서 말하는 성능 & 안전측면에서의 코드는 아래와 같습니다.

 

  • Synchronized 부분은 가능한 작게.
  • null 반환 X, null 전달 X
  • 멀티 쓰레드 코드 시 유의

2. Synchronized 부분은 가능한 작게.

 

Java 에서의 Synchronized는 멀티 쓰레드 환경에서 데이터의 동시접근을 막아 데이터 정합을 지키기 위해 사용합니다.

 

방법은 Synchronized를 정의한 객체를 lock을 걸어 동시 접근을 막는것입니다.

 

객체에 lock을 걸게되어 성능은 당연히 좋지 않게됩니다.

 

그렇기 때문에, 최대한 Synchronized를 피하는 방식으로 개발을 하는것이 best입니다.

 

하지만, 부득이하게 Synchronized를 사용해야 하는경우에는 가능한 작게 만들어

성능에 큰 이슈가 나지 않도록 해야합니다.

 

3. null 반환 X, 메서드에 전달 X 

 

null을 사용한다는 것은 매우 위험하고 깨끗하지 않은 코드입니다.

 

그 이유는 아래와 같습니다.

 

  • NullPointerException 발생 여지를 만들게 됩니다.
  • null 체크를 위해 코드가 난잡하게 됩니다.

Clean Code에서는 위와 같은 이유로 특수목적의 객체 혹은 빈 객체를 반환하는것을 추천합니다.

 

또한, Java 사용자의 경우에는 8 버전의 Optional을 통하여 간편하게  Null 체크 및 예외를 핸들링 할 수 있습니다.

 

 

 

 

 

 

반응형

 

 

 

 

 

 

 

4. 멀티 쓰레드 코드 시 유의

 

단일 쓰레드가 아닌 멀티 쓰레드의 경우에는 고려할 점이 많습니다.

위에서 언급한 Synchronized, dead lock 등이 대표적입니다.

 

그렇기 때문에 clean code에서는 아래와 같이 유의하라고 나옵니다.

 

  • 문제를 발생시킬 만한 테스트를 작성하고 자주 수행하라.
  • 시스템 오작동을 one-off("한번만 일어나는")로 판단해 무시하지 말라.
  • 여러 환경에서 실행할 수 있게 하라.
  • 스레드 관련 버그는 단일 스레드에서 먼저 잘 동작하는지 확인 후 멀티 스레도 코드로 작성하라.
  • 프로세서 수보다 많은 스레드를 돌려 작업 전환이 잦게하여 critical section이나 dead lock을 찾을 확률을 높여라.

 

위 유의사항들을 한 마디로 요약하면, Error를 무시하지 말고 끝없이 테스트를 진행하라 입니다.

 

멀티쓰레드 환경에서는 수많은 케이스들이 존재하며 에러를 재현하기도 힘듭니다.

 

그렇기 때문에, 저의 경우에는 로컬에서는 단위 테스트 & 잡 테스트를 진행하며

개발망에서는 실제 배포하여 최소 3일정도의 결과를 모니터링 후 리얼에 배포를 진행하고 있습니다.

 

5. 마무리

 

성능 & 안전을 고려한 Code에 대해서 포스팅하였습니다.

다음에는 테스트 Code에 대해 포스팅하겠습니다.

반응형

'Programming > CleanCode' 카테고리의 다른 글

(3) Clean Code - 테스트 Code  (0) 2020.03.01
(1) Clean Code - readability가 좋은 Code  (0) 2020.02.27

+ Recent posts