CS공부(개념)/독후감

클린코드 5주차: 동시성, 그리고 JUnit

cantor 2023. 9. 5. 13:19

230904 클린코드 5주차 

클린코드 북스터디를 하며 작성한 독후감 겸 요약글입니다.

로버트 C 마틴 저 clean code

 

 

 

5주 차 동안 13장인 "동시성"과 15장 "JUnit 들여다보기"에 대해 읽었습니다.

13장 동시성

동시성 개념과, 동시성 코드를 깨끗하게 작성하는 방법을 이야기합니다.

 

저는 이 책이 일종의 디자인패턴/소프트웨어 공학적 지식을 다루는 것으로만 알았는데
OS개념이라고 할 수 있는 동시성에 대한 설명이 나와 반갑기도 하고 신기하기도 했습니다.

 

책을 읽고 보니 사실 동시성이야말로 클린코드에서 다루어야 할 부분이더군요.
일반 싱글 스레드 프로그램보다 코드가 복잡하고, 기상천외한 오류가 많이 발생하기 때문입니다.

 

이 장의 직접적인 코드예제는 많이 적어서 아쉬웠지만
그래도 동시성 개념에 대한 공부 방향과 테스트 코드 작성 방법에 대해 정리할 수 있었습니다.

동시성이 필요한 이유

 

우선, 깨끗한 동시성 코드를 고려하기 전에, 왜 동시성이 필요한지에 대해 먼저 알아야 합니다.

 

개발자로서, 문제를 명확히 정의하고 도구를 선택하는 것이 중요합니다.
동시성도 추상적인 하나의 도구이기에 도입 목적을 신중히 고려해야겠죠?

 

동시성이 해결하는 주요 문제는 "처리 성능 개선"입니다.

 

동시성을 도입하지 않은 싱글 스레드 프로그램은 코드가 데이터에 접근하는 시점이 명확합니다.

"어떤" 코드가 "어떤" 데이터에 "언제" 접근하는지를 한눈에 파악할 수 있죠.

 

반면, 동시성은 어떤:(작업자, 작업대상)과 언제(: 작업 시간)의 결합을 분리합니다.

 

설명을 위한 비유를 들어보겠습니다.

 

회사에서 한 명이 처리하기 힘든 커다란 업무가 발생했습니다.

 

사장님은 해당 업무를 빠르게 처리하기 위해 직원을 새로 고용하고,

기존의 직원들을 모아 여유시간에 해당 작업을 수행하는 팀을 구성하였습니다.

 

직원은 각자 기존의 업무를 수행하며,

여유 시간마다 공통작업의 남은 부분을 진행하게 하였습니다.

 

일전에 한명이 업무를 처리할 때에는, 담당자와 작업 시각이 명확했습니다.

하지만 이제 수행시각과 업무를 할당중인 직원이 결합되어있지 않습니다.

 

회사는 이를 통해 원하는 업무처리 속도를 얻을 수 있었을까요?

 

담당자가 한명이었던것을 여러 명이서 하게 되었습니다.

여기서 여러 가지 어려움이 함께 발생합니다.

 

일단 직원이 증가하니 회사가 지출하는 비용이 증가합니다.

 

진행상황에 대한 감독이 어려워집니다.

팀을 케어하는 것은 직원 한 명을 관리하는 것보다 훨씬 더 어려운 일이기 때문입니다.

 

사람이 증가한다고 그만큼 속도가 빨라지는 것도 아닙니다.

 

만약 업무를 위한 도구나 권한이 한정적이라면,

여유시간이 있어도 손 놓고 있는 직원이 생길 수 있지요.

 

서로 업무를 파악하고 진행기록을 남기는 프로세스에 문제가 생긴다면 어떻게 될까요?

 

다른 사람이 이미 처리한 부분을 중복으로 처리하는 직원이 생길 것입니다.

시간낭비는 물론이고 중복처리에 의한 문제가 발생할 수도 있습니다.

또 대체 어떤 일을 해야 하는지 아무도 모르게 될 수도 있지요.

 

최악의 경우 한 명의 숙달된 직원이 작업을 처리할 때보다 더 오랜 시간이 걸릴 수도 있습니다.

 

 

컴퓨터의 동시성구현에서도 비슷한 어려움이 있습니다.

 

작업속도 향상을 목적으로 동시성을 구현하지만

무조건적인 처리속도의 증가가 보장되어있지 않고,  프로그램 관리에 있어 여러 어려움이 생깁니다.

 

구체적으로 아래와 같은 애로사항이 있습니다.

  1. 기존 프로그램의 설계를 변경해야 합니다.
  2. 동시성의 자체적인 개념과 코드가 복잡합니다.
  3. 프로그램이 다소 부하를 유발합니다.
  4. 발생한 버그를 재현하기 어렵습니다.
    • 프로그램이 실행되는 데이터 흐름 경로의 경우의 수가 엄청나게 증가합니다.
    • 각 경로는 같은 결과를 보장하지 않습니다.
      • 책에서 저자가 보여주는 코드는 만개의 경우가 백만 개로 증가한다고 합니다.

 

위에 나열한 여러 가지 난관에도 불구하고 

제대로 구현한 동시성이 가져다주는 성능 향상은 무척 매력적입니다.

 

개발자들은 동시성을 회피하지 말고,

이에 관한 문제들을 제대로 공부하고, 에러 방어 원칙을 지켜가며 프로그래밍해야 합니다.

13장의 세부내용 요약
동시성 방어원칙
  1. 단일책임원칙
기존의 클래스 설계 원칙과 동일합니다.
동시성 작업을 수행하는 코드는 다른 코드와 분리하여야 합니다.
  1. 자료범위제한
여러 스레드가 서로를 간섭하는 과정에서 버그가 발생합니다.
공유 객체 통해 코드 내 임계영역으로 버그를 막아야 합니다.

그러나 임계영역이 많을수록 개발자가 확인해야 할 세부사항이 커집니다.
자료를 캡슐화하여 임계영역을 최대한 줄여야 합니다.

 

  1. 자료 사본사용
공유자료 접근에 의한 문제를 방지하기 위해 처음부터 자료 공유를 막는 기법입니다.
공통 자료를 복제하여, 개별 스레드가 각각 독립적으로 한 개씩 접근하게 하면 됩니다.
  1. 스레드는 가능한 독립적으로 구현
다른 스레드와 자료를 공유하지 않고, 각자의 로컬 변수를 사용하는
독립적인 스레드를 구현하는 것이 좋습니다.
라이브러리를 이해할 것

동시성 설계를 지원하는 라이브러리, 즉 안전성을 보장하는 라이브러리를 찾아 사용하여야 합니다.

 

실행모델을 이해할 것

운영체제 과목에서 소개하는 동시성을 위한 전통적 개념들을 익히고, 병렬 처리 관련 알고리즘을 공부해야 합니다.

병렬처리를 기술하기 위한 개념

- 한정된 자원
- 상호배제
- 기아
- 데드락
- 라이브락 등등
주로 발생하는 문제를 해결하기 위한 알고리즘

- 생산자-소비자
- 읽기-쓰기
- 식사하는 철학자들
적절한 동시성 프로그래밍을 위한 전략

1. 동기화하는 메서드 사이의 의존성을 인지, 공유객체는 되도록 메서드 하나만 사용하게 할 것
2. 동기화하는 부분을 작게 만들 것
3 종료코드 구현의 어려움을 인지하고, 처음부터 전략적으로 설계하기
4. 프로그램 및 시스템 설정, 그리고 부하를 바꿔가며 많은 테스트를 수행하기 
5. 말도 안 되는 실패는 스레드 문제로 취급하기
6. 다중 스레드 코드에 집중할 수 있게 순차코드 로직을 먼저 깔끔하게 작성하기
7. 다중 스레드 코드를 다양한 환경을 위해 다양한 설정으로 사용할 수 있게 작성하기
8. 프로그램이 실행되는 도중에 처리율과 효율에 따라 스레드 개수를 조율하는 코드를 만들어 보기
9. 프로세서 수보다 많은 스레드를 돌려보기
10. 프로그램을 다양한 플랫폼에서 돌려보기
11. 보조 코드를 추가하여 강제로 실패를 일으켜보기

15장 JUnit 들여다보기

JUnit은 자바의 테스트코드 작성을 위한 라이브러리입니다.

  • JS의 Jest나 Mocha 라이브러리 같은 것이지요.

이 책은 전반적으로 TDD (Test-Driven Development)와 테스트 코드에 관한 내용을 주로 다루고 있어서,
JUnit을 효과적으로 활용하는 클린 한 코드를 작성하는 방법이 나올 것이라 예상했습니다.

 

그러나, 실제로는 JUnit 코드에 대한 리팩터링을 다루고 있었습니다.

15장의 세부내용: 리팩터링

실제 저자가 실무에서 수행하는 리팩터링 과정을 보여줍니다.

 

변수명에 접두사가 필요한 것인지 판단합니다.

만약 불필요하다면 제거합니다.

 

조건식에서의 긴 논리식을 함수로 캡슐화합니다.

 

```

```

 

falsy일 때 통과하는 조건식이 있다면 조건을 반전시켜 준후

truthy로 바꾸어줍니다.

 

구조를 바꿔주기보단 이름을 바꾸거나, 읽기 편한 명명을 통해

다양한 방법으로 가독성을 높여주는 작업을 합니다.

 

인상 깊었던 부분은 변수명에 들어가는 단어 index와 length에 관한 언급이었습니다.

 

저자는 값이 불연속적이며 0이 될 수 있는 경우에는

length를 사용해서는 안 된다고 합니다.

 

어떻게 보면 너무 당연한 이야기입니다.

하지만 저는 저 두 단어를 맥락상 같은 의미로 많이 자주 사용하고 있었습니다.

 

이렇게 작은 부분하나 신경 쓰는 내용을 보고 책에서 주창하는 "소프트웨어 장인정신"이

더 이상 단순한 과장처럼 보이지 않았습니다.


나눠볼 만한 이야기

  1. 우리가 자바스크립트를 하다가 동시성과 만날 일이 있을까요?

  2. 동시성 프로그램의 테스트코드에서 자료의 범위를 제한하는 것은 어떤 방식으로 구현하는 것이 좋을까요?
데이터중심 애플리케이션 개발이라는 서적에서 아래와 같은 내용을 읽은 적이 있습니다.

빅데이터 분석을 위한 쿼리들은 엄청나게 많은 양의 데이터를 DB에서 한 번에 뽑아냅니다.
이런 쿼리들에 의한 부하 혹은 쿼리 간 충돌을 방지하기 위해 
비즈니스 로직이 처리되는 DB와 별개로 빅데이터 처리를 위한 readonly  DB를 만듭니다.

이렇게 좀 거시적인 관점에서의 자료범위 제한은 쉽게 와닿습니다.

또 운영체제 과목에서 말하는 미시적인 자료범위 제한도 크게 어렵지 않습니다.

하지만 프로그램 내부에서 임계영역을 만들고 처리한다니까 잘 와닿지 않습니다.

 

  1. 버그로부터 안전한 라이브러리를 찾는 적합한 방법이 있을까요?

저자는 외부 라이브러리를 깊게 이해하고,동시성에 관한 문제들에 대해
방어가 잘되는 라이브러리를 사용하라는 말을 합니다.

그런 라이브러리에 대한 탐색은 어떻게 해야 할까요?

저는 프로젝트 기술스택을 선택할 때, 그냥 npm 다운로드 횟수와 이용하는 회사들을 통해 신뢰성을 평가합니다.

디테일한 정보를 찾아보지 않습니다. 방법을 모르기 때문입니다.

패키지가 특정 장애에 대한 안전성을 제공하는지 파악하는 방법을 알게 된다면, 

개발자의 능력에 있어 커다란 도약이 될 거 같습니다.

 

  1. 스레드 단위 코딩이 무엇일까요?

    저자는 말도안되는 에러는 스레드 자체의 장애로 취급하라고 합니다.
    여기서 말하는 스레드는 무엇인지 궁금합니다.

    컴퓨터 구조 수준의 low-level 개발이 아닌 자바프로그래밍 이야기인것은 확실한데
    예제 코드가 없어서 무슨이야기를 전하는지 잘 모르겠습니다.


    이번주 내용은 어려웠지만 즐거웠습니다.
    모임시간이 기대가 됩니다.