diff --git "a/_posts/blog/posts/\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270/2024-08-02-\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270 5\354\236\245 \352\265\254\353\266\200\353\237\254\354\247\200\352\261\260\353\202\230 \353\266\200\353\237\254\354\247\200\352\261\260\353\202\230.md" "b/_posts/blog/posts/\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270/2024-08-02-\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270 5\354\236\245 \352\265\254\353\266\200\353\237\254\354\247\200\352\261\260\353\202\230 \353\266\200\353\237\254\354\247\200\352\261\260\353\202\230.md" index 06302c005..586f9fe69 100644 --- "a/_posts/blog/posts/\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270/2024-08-02-\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270 5\354\236\245 \352\265\254\353\266\200\353\237\254\354\247\200\352\261\260\353\202\230 \353\266\200\353\237\254\354\247\200\352\261\260\353\202\230.md" +++ "b/_posts/blog/posts/\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270/2024-08-02-\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270 5\354\236\245 \352\265\254\353\266\200\353\237\254\354\247\200\352\261\260\353\202\230 \353\266\200\353\237\254\354\247\200\352\261\260\353\202\230.md" @@ -67,7 +67,7 @@ public void applyDiscount(customer, order_id, discount) { } ``` -여기서 더 숨길 수도 있지만, 이 앱에서는 `customer`와 `order`가 최상위 개념이다. 이정도는 드러내도 괜찮을 것이다. +여기서 더 숨길 수도 있지만, 여기서는 `customer`와 `order`가 최상위 개념이다. 이정도는 드러내도 괜찮을 것이다. **데메테르 법칙** @@ -102,13 +102,6 @@ LoD(데메테르 법칙) : 어떤 클래스 C에 정의된 메서드는 다음 > 전역적이어야 할 만큼 중요하다면 API로 감싸라. -**필자 여담** - -전역 변수를 메서드로 감싸는 정도가 적절한 것 같음. `하지만 설정데이터를 단 한 벌만 가지고 있는 것에는 변함이 없다.`라는 대목이 있지만 잘 공감이 가지 않는 대목이다. - -### 상속은 결합을 늘린다. - -상속을 잘못 사용하면 결합만 늘어날 수 있다. ### 결국은 모두 ETC @@ -321,4 +314,23 @@ class AccountForAdmin extends Account with AccountValidations, AccountAdminVali 물론 스프링에서 properties 파일과 같은 정적 설정도 장점이 있다. 설정 정보의 성격에 따라 적절히 분리해서 관리하면 될 거 같다. - 정적 설정 : 자주 변경되지 않지만 애플리케이션에 거쳐 많이 사용되거나 외부로 뺄 필요가 있어보이는 값들. 급하게 변경하지 않아도 이슈가 없는 값들 -- 서비스형 설정 : 자주 변경될거라 예상되는 값들. 급하게 변경이 발생할 수 있는 값들. \ No newline at end of file +- 서비스형 설정 : 자주 변경될거라 예상되는 값들. 급하게 변경이 발생할 수 있는 값들. + + +--- + +## 후기 + +이번 장은 전체적으로 결합도를 줄이는 것에 집중한 장이다. + +topic 28 : **책임을 분명히하고, 자신이 직접적으로 아는 것만 다루는 방식**을 통해 결합도를 줄일 수 있다. 전역 변수도 일종의 결합인데, 전역변수 변경 시 필요한 부분을 모두 바꾸었는지 확인하기 어렵기 때문이다. + +이 토픽에서는 데메테르 법칙에 대해서도 얘기하였는데, 쉽게 풀이한 "무언가에 접근할 때 `.`을 두번 이상 사용하지 마라"라는 팁은 이해하기가 쉬웠다. + +topic 29 : 이벤트를 구현하는 방식에 네가지 방식(유한 상태 기계, 감시자 패턴, 게시 - 구독, 반응형 프로그래밍과 스트림)에 대해 설명하였다. 유한상태기계를 작성하면 이벤트를 어떻게 다뤄야하는지 알기 쉽다는 팁이 도움될거 같다. + +topic 30 : 프로그램은 결국 데이터를 변환하는 것이고, 데이터를 중심으로 구조를 생각하면 어떻게 파이프라인을 구성해야할지 한눈에 보인다. + +topic 31 : 상속은 결합을 만들어내기에 사용을 지양해야한다는 파트이다. 상속 대신 인터페이스, 위임, 믹스인 등을 통해 기능을 추가하는 것이 좋다고 한다. 개인적으로 동감하는 파트이고, 상속은 프레임워크에서 제공하는 것 외에는 사용을 자제하는 것이 좋다고 생각한다. + +topic 32 : 설정을 소스 본체 바깥에 저장하는 방식을 설명한다. 개인적으로 서비스형 설정이 변화에 대응이 쉬워 더 선호한다. \ No newline at end of file diff --git "a/_posts/blog/posts/\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270/2024-08-05-\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270 6\354\236\245 \353\217\231\354\213\234\354\204\261.md" "b/_posts/blog/posts/\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270/2024-08-05-\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270 6\354\236\245 \353\217\231\354\213\234\354\204\261.md" new file mode 100644 index 000000000..1d5843970 --- /dev/null +++ "b/_posts/blog/posts/\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270/2024-08-05-\354\213\244\354\232\251\354\243\274\354\235\230\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270 6\354\236\245 \353\217\231\354\213\234\354\204\261.md" @@ -0,0 +1,102 @@ +--- +title: 실용주의프로그래머 6장 동시성 +author: 신성일 +date: 2024-08-04 18:04:36 +0900 +categories: study, 실용주의프로그래머 +tags: + - "#study" +--- +- 동시성 : 둘 이상의 코드 조작이 실행될 때 동시에 실행 중인 것처럼 행동하는 것. 소프트웨어 동작 + - 코드의 다른 부분으로 실행을 전환할 수 있는 환경에서 코드를 구동해야함. ex) 스레드, 프로세스 +- 병렬성 : 실제로 동시에 실행되는 것. 하드웨어 동작 + - 두가지 일을 동시에 할 수 있는 하드웨어가 필요함. ex) CPU내 코어, 네트워크로 연결된 컴퓨터 등 + + +### 모든 일에 동시성이 있다. + +시스템이 커지면 동시성은 필수다. 어떤 일을 할 때, 한번에 하나씩 순차적으로 수행 하면 시스템이 매우 느려질 것이기 때문이다. + +따라서 코드 간의 결합 이외에도, `시간적 결합`을 깨는 것도 중요하다. + + +## Topic 33 : 시간적 결합 깨트리기 + +코드를 짜다보면 순차적 사고를 하기 마련이다. 하지만 유연성과 동시성을 확보하기 위해 시간이나 순서에 의존하는 시간적 결합을 끊어야한다. 그럼 시간 관련 의존성을 줄일 수 있고, 더 빠르고 안정적인 시스템을 만들 수 있다. + + +### 동시성 찾기 + +동시에 일어나도 되는 일과 반드시 순서대로 일어나야하는 일을 구분하기 위해, 활동 다이어그램 등을 사용하여 작업 흐름을 모델화 할 수 있다. + +### 동시 작업의 기회 + +활동 다이어그램을 통해 동시에 작업할 수 있는 부분들이 있다. 이 중에서 데이터베이스 접근, 외부 서비스 요청 등 우리 코드가 아닌 곳에서 시간이 걸리는 일을 할 때, 우리 코드는 다른 작업을 할 수 있을 것이다. + +### 병렬 작업의 기회 + +큰 작업을 독립적인 부분 작업으로 나누어 여러 프로세서에서 동시에 일을 처리할 수 있다. + + +--- + +## Topic 34 : 공유 상태는 틀린 상태 + +> 공유 상태는 틀린 상태다 + +상태가 공유되면 동시성을 구현할 때 프로그램 오류가 발생할 수 있다. 따라서 어떤 상태가 있다면 이를 원자적으로 갱신하여야한다. 여기에는 다음 방법들이 있다. + +- 세마포어 + - 세마포어를 소유하고 있을 때만 조회/갱신을 할 수 있도록 함. + - 단점 : 누군가가 세마포어를 얻는걸 잊어버릴 수 있음. +- 리소스를 트랜잭션으로 관리하라 + - 리소스 제어를 중앙으로 집중하여, 조회와 동시에 업데이트를 할 수 있도록 한다. + + +### 여러 리소스와 트랜잭션 + +어떤 작업을 수행할 때, 여러 리소스가 동시에 필요하면 공유 상태 관리는 더 복잡해진다. 하지만 이때도 여러 리소스를 하나의 리소스로 보고, 이 리소스에 접근하는 코드를 모듈로 옮긴 후, 클라이언트는 그 리소스를 달라고 요청하면 그림이 간단해진다. 클라이언트가 여러 리소스를 직접 호출하는 것보다 훨씬 간단하다. + +### 트랜잭션이 없는 갱신 + +수정 가능한 리소스를 공유하는 애플리케이션 코드 어디에서나 동시성 문제가 발생할 수 있다. 여기에는 한가지 팁이 있다. + +> 불규칙한 실패는 동시성 문제인 경우가 많다. + +--- + +## Topic 35 : 액터와 프로세스 + +**액터** + +자신만의 비공개 지역상태를 가진 독립적인 가상 처리 장치. +우편함을 하나씩 보유하고 있고, 메세지를 받으면 차례대로 처리한다. 메세지를 처리할 때 액터는 다른 액터를 생성하거나, 메세지를 보낼 수 있고, 새로운 상태를 생성할 수 있다. + +### 액터는 언제나 동시성을 띤다 + +- 액터를 관리하는 것은 없다. +- 시스템이 저장하는 상태는 메시지와 각 액터 내의 지역 상태일 뿐이다. +- 모든 메시지는 일방향이고, 메시지 내에서 다른 메시지를 보내는 것만 가능하다. +- 한번에 하나의 메시지만 처리한다. + +위 특징들로 액터들은 아무것도 공유하지 않고 비동기적으로 동시에 실행된다. 따라서 동시성을 다루는 코드도 필요없다. + +> 공유 상태 없는 동시성을 위하여 액터를 사용하라 + + +--- + +## Topic 36 : 칠판 + +`칠판`은 일종의 자유방임주의적 동시성으로, 독립된 프로세스, 에이전트 등이 수집한 사실을 붙이고 누군가는 떼어내기도 한다. (ex : 린다, JavaSpace, T Spaces 등) + +복잡한 규칙과 과정을 준수해야하는 대출 시스템에서 사용할 수도 있는데, 어떤 사실이 칠판에 올라가면 규칙 엔진이 돌아가서 적절한 규칙을 발동시키면 된다. + +### 메시지 시스템과 칠판의 유사성 + +카프카와 같은 메시징 시스템은 단순히 메시지를 보내는 것 이상으로 이벤트 로그를 통한 영속성지원, 패턴 매칭으로 메시지 조회를 지원한다. 따라서 메시징 시스템을 칠판으로 사용할 수도 있다. + +### 하지만 간단하지 않다. + +아키텍처에서 액터, 칠판, 마이크로서비스를 사용하면 애플리케이션에서 생길 수 있는 동시성 문제를 예방할 수 있다. 하지만, 이런 접근 방식은 많은 동작이 간접적으로 일어나서 분석이 어렵다. + +이에 대한 기법으로, 처리를 시작할 때 고유한 '추적 아이디 (Trace Id)'를 붙일 수 있다. \ No newline at end of file