반응형

소프트웨어 아키텍처 Hard Parts 의 내용을 정리한 내용입니다.

  • BASE 분산 트랜잭션 특유의 속성
    • BA (Basic availavility)
      • 분산 트랜잭션의 모든 서비스 또는 시스템이 분산 트랜잭션에 참여할 수 있으리라고 기대하는것.
    • S (Soft state)
      • 분산 트랜잭션이 진행중이고 원자적 비지니스 요청이 미 완료된 상태.
      • 고객 프로필 정보에서 Profile 테이블에는 데이터카 커밋 됐지만 다른 연관 테이블에는 커밋되지 않은 상태.
    • E (Eventual Consistency)
      • 충분한 시간이 지나면 언젠가는 결국 분산 트랜잭션이 완료되고 모든 데이터가 서로 동기화 된다는 의미.
      • 백그라운드 동기화 패턴 (Background synchronization pattern) - 326p
        • 별도의 외부 서비스나 데이터 소스를 주기적으로 체크해서 데이터 소스를 서로 동기화 한다.
        • 장점
          • 서비스가 디커플링 된다.
          • 응답성이 좋다.
        • 단점
          • 데이터 소스가 결합돤다.
          • 구현부가 복잡해진다.
          • 경계 콘텍스트가 무너진다.
          • 비지니스 로직이 중복될 수 있다.
          • 최종 일관성을 맞추려면 시간이 걸린다.
      • 오케스트레이티드 요청 기반 패턴 (Orchestrated request-based pattern) - 329p
        • 오케스트레이터가 전체 분산 트랜잭션을 관리한다.
        • 장점
          • 서비스가 디커플링 된다.
          • 데이터를 적시에 동기화 할수 있다.
          • 원자적 비지니스 요청이 가능하다.
        • 단점
          • 응답이 느리다.
          • 에러처리가 복잡하다
          • 보상 트랜잭션이 필요하다.
      • 이벤트 기반 패턴 (Event-based pattern) 333p
        • 이벤트나 커맨드 메세지를 이벤트 형태로 비동기 발행 해서 게시하면 구독하는 다른 서비스들이 이벤트를 받아 적절히 응답하는 페턴
        • 장점
          • 서비스가 디커플링 된다.
          • 데이터를 적시에 동기화 할수 있다.
          • 응답이 빠르다
        • 단점
          • 복잡한 에러처리
728x90
반응형
반응형

Python Virtualenv

  • 프로젝트별 종속성 문제를 해결하기 위해서 가상환경을 제공한다.

  • 동시에 여러개의 프로젝트 진행시 각각의 파이썬 버전이 다를경우 사용한다.

  • virtualenv 환경 구성

    pip install virtualenv
    
    D:\STUDY\study_python>virtualenv py3.8-env
    created virtual environment CPython3.8.5.final.0-64 in 6461ms
      creator CPython3Windows(dest=D:\STUDY\study_python\py3.8-env, clear=False, global=False)
      seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=C:\Users\SDS\AppData\Local\pypa\virtualenv)        \Local\pypa\virtualenv)
        added seed packages: pip==22.2.2, setuptools==49.6.0, wheel==0.37.1
      activators BashActivator,BatchActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
    • 1라인 : virtualenv 를 pip 를 이용해서 설치한다.

    • 3라인 : 가상환경을 생성한다.

    • 가상환경을 실행하기 위해서는 activate 명령어를 실행하면 된다. (window 의 경우 Script 폴더에 있고 리눅스인경우 bin 폴더 안에 생긴다.)

      (py3.8-env) D:\STUDY\study_python\py3.8-env\Scripts>

      가상환경을 실행하면 위와 같이 환경 이름이 앞에 붙는다.

    • 가상환경을 종료하기 위해서는 deactivate 명령어를 실행한다.

  • virtual 환경에 구성된 패키지 export

    pip freeze > req.txt
    
    req.txt
    certifi==2022.9.24
    charset-normalizer==2.1.1
    idna==3.4
    requests==2.28.1
    urllib3==1.26.12
  • req.txt 를 인스톨 하려면 다음과 같이 하면 된다.

    pip install -r req.txt
728x90
반응형
반응형

Ubuntu 에서 파이썬 설치 위치 확인

DESKTOP-MBRI3VL:~$ python --version
Python 2.7.17
DESKTOP-MBRI3VL:~$ python3 --version
Python 3.6.9

파이썬을 설치하다 보면 2.X 도 있고 3.X 도 있다. 위와 같이 각각의 버전을 확인해보면 설치된 버전을 확인할 수 있다. Ubuntu를 설치하면 기본적으로 2.7을 path 로 설정한다.

아래와 같이 명령어를 실행 하면 설치된 파이썬 목록들이 나완다. (정말 이것 저것 많다.)

DESKTOP-MBRI3VL:~$ ls /usr/bin | grep python

python-config
python2
python2-config
python2.7
python2.7-config
python3
python3-config
python3-jsondiff
python3-jsonpatch
python3-jsonpointer
python3-jsonschema
python3.6
python3.6-config
python3.6m
python3.6m-config
python3.7
python3.7m
python3m
python3m-config
x86_64-linux-gnu-python-config
x86_64-linux-gnu-python2.7-config
x86_64-linux-gnu-python3-config
x86_64-linux-gnu-python3.6-config
x86_64-linux-gnu-python3.6m-config

그래서 update-alternatives를 사용해서 파이썬에 대한 버전을 변경해보려고 한다. update-alternatives는 심볼릭 링크를 관리해 주는 리눅스 프로그램이다.

DESKTOP-MBRI3VL:~$ ls -al  /usr/bin | grep python
lrwxrwxrwx  1 root   root           26 Mar 27  2018 dh_pypy -> ../share/dh-python/dh_pypy
-rwxr-xr-x  1 root   root         1056 Apr 16  2018 dh_python2
lrwxrwxrwx  1 root   root           29 Mar 27  2018 dh_python3 -> ../share/dh-python/dh_python3
lrwxrwxrwx  1 root   root           23 Jul  2 00:56 pdb2.7 -> ../lib/python2.7/pdb.py
lrwxrwxrwx  1 root   root           23 Jun 29 20:45 pdb3.6 -> ../lib/python3.6/pdb.py
lrwxrwxrwx  1 root   root           23 Dec 10  2021 pdb3.7 -> ../lib/python3.7/pdb.py
lrwxrwxrwx  1 root   root           31 Oct 25  2018 py3versions -> ../share/python3/py3versions.py
lrwxrwxrwx  1 root   root           26 Mar 27  2018 pybuild -> ../share/dh-python/pybuild
lrwxrwxrwx  1 root   root            9 Apr 16  2018 python -> python2.7
lrwxrwxrwx  1 root   root           16 Apr 16  2018 python-config -> python2.7-config
lrwxrwxrwx  1 root   root            9 Apr 16  2018 python2 -> python2.7
lrwxrwxrwx  1 root   root           16 Apr 16  2018 python2-config -> python2.7-config
-rwxr-xr-x  1 root   root      3624880 Jul  2 00:56 python2.7
lrwxrwxrwx  1 root   root           33 Jul  2 00:56 python2.7-config -> x86_64-linux-gnu-python2.7-config
lrwxrwxrwx  1 root   root            9 Oct 25  2018 python3 -> python3.6

위에서 보면 python의 심볼릭 링크는 python2.7 로 되어있고 python3 에 대한 링크는 python3.6 으로 되어있다. 이것을 변경하려고 한다.

DESKTOP-MBRI3VL:~$ sudo update-alternatives --config python
update-alternatives: error: no alternatives for python
DESKTOP-MBRI3VL:~$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
update-alternatives: using /usr/bin/python2.7 to provide /usr/bin/python (python) in auto mode
DESKTOP-MBRI3VL:~$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.6 2
update-alternatives: using /usr/bin/python3.6 to provide /usr/bin/python (python) in auto mode
DESKTOP-MBRI3VL:~$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.7 3
update-alternatives: using /usr/bin/python3.7 to provide /usr/bin/python (python) in auto mode

1번 라인 : python 버전을 변경하는 명령어 인데 현재는 등록되어 있는게 없기 때문에 에러가 난다.

3번 라인 : python 명령어를 2.7로 연결하고 1번으로 할당했다.

5번 라인 : python 명령어를 3.6로 연결하고 2번으로 할당했다.

7번 라인 : python 명령어를 3.7로 연결하고 3번으로 할당했다. (2.7, 3.6, 3.7 이 설치되어있었다.)

DESKTOP-MBRI3VL:~$ update-alternatives --config python
There are 3 choices for the alternative python (providing /usr/bin/python).

  Selection    Path                Priority   Status
------------------------------------------------------------
* 0            /usr/bin/python3.7   3         auto mode
  1            /usr/bin/python2.7   1         manual mode
  2            /usr/bin/python3.6   2         manual mode
  3            /usr/bin/python3.7   3         manual mode

Press <enter> to keep the current choice[*], or type selection number: 3

다 등록을 하고 1번 라인에 썼던 명령어를 다시 실행하면 위와 같이 나와서 사용할 버전을 선택할 수 있다.

DESKTOP-MBRI3VL:~$ python --version
Python 3.7.5

버전을 확인해 보면 위와 같이 나온다.

728x90
반응형

'Development > Python' 카테고리의 다른 글

파이썬 문법 : 튜플  (0) 2023.02.27
Python 가상환경  (0) 2022.10.27
파이썬 입력값 받기  (0) 2021.08.25
파이썬 문법 : 배열 초기화  (0) 2021.08.25
Python 으로 파일 내용 변경 하기  (0) 2020.10.20
반응형
PS C:\Users> wsl -l -v
  NAME                   STATE           VERSION
* docker-desktop-data    Stopped         2
  docker-desktop         Stopped         2
  Ubuntu-18.04           Running         2

위와 같이 배포버전이 여러개 일 경우 default 로 설정되는 배포버전으로 변경하기 위해서는 다음과 같이 설정하면 된다.

 C:\Users> wsl --setdefault Ubuntu-18.04

그럼 다음과 같이 변경이 된다.

 C:\Users> wsl -l -v
  NAME                   STATE           VERSION
* Ubuntu-18.04           Running         2
  docker-desktop         Stopped         2
  docker-desktop-data    Stopped         2

이것을 찾아봤던 이유는 VS Code 에서 remote로 WSL 로 접속하려고 하니 계속해서 docker-desktop-data 로 연결을 시도하면서 실패를 했다. 연결하려는 타겟이 ubuntu 가 되어야 할것 같은데 docker-desktop-data 로 계속 시도를 했다. 그래서 위와같이 디폴트 배포버전을 변경하니 정상적으로 연결됐다.

 

728x90
반응형
반응형

React 에서 Key 가 필요한 이유

  • Map 사용시 고유한 Key 가 필요하다.
  • React 는 상태를 메모리에 저장하고 있다가 변경된 부분만 렌더링 한다.
  • Key 값이 없으면 모든 데이터를 비교해야 하지만 Key 가 있으면 Key만 비교하면 된다.
  • <ul>
      {props.users.map((user) => (
        <li key={user.id}>
          {user.username} ({user.age} years old)
        </li>
      ))}
    </ul>

Map 에서 index 를 Key로 하면 안되는 이유

  • 0번의 index 가 삭제되면 React 가 변경을 감지하여 리렌더링 되고 0번 부터 다시 매핑한다.
  • 1번 인덱스가 0번으로 매핑이 된다.
  • 결론적으로 인덱스가 추가되거나 삭제되면 값이 바뀌기 때문에 index 를 key 로 사용하는것은 안좋다.
728x90
반응형
반응형
  • 값과 함수를 반환한다.
  • 함수는 값을 변화시킨후 컴포넌트를 리렌더링한다
  • 여러개의 state 를 정의할 수도 있고 object로 관리할수도 있다.
    const [enteredTitle, setEnteredTitle] = useState('');
    const [enteredAmount, setEnteredAmount] = useState(0);
    const [enteredDate, setEnteredDate] = useState();
    const [userInput, setUserInput] = useState({
      enteredTitle: '',
      enteredAmount: 0,
      enteredDate: ''
    })
    • 주의 할 점은 update 시 object에 있는 일부 키만 업데이트 한다면 다른 키들이 사라진다.
    • 아래와 같이 enteredTitle 키만 정의할 경우 나머지 키는 사라진다. (merge 하지 않는다)
      const titleChangeHandlerNew = (event) => {
        setUserInput.enteredTitle = event.target.value
      };
    • 수동으로 복사가 필요하다. 기본값을 복사한후 오버라이드 한다.
      const titleChangeHandlerNew = (event) => {
        ...userInput,
        setUserInput.enteredTitle = event.target.value
      };
      • 위 방법에서는 문제가 발생할 수 있다.
      • 리액트가 상태업데이트 바로 실행하지 않는다.
      • 따라서 동시에 많은 상태를 업데이트 할 경우 최신값을 잘못 가져올수 있다.
      • 따라서 다음과 같이 사용하는게 더 낫다. (스냅샷을 이용한다)
        const titleChangeHandlerNew2 = (event) => {
        setUserInput((prevState) => {
          return {
            ...prevState,
            enteredTitle: event.target.value
          }
        });
        };
  • useState 를 사용해서 set을 했는데 화면에서 안바뀔 경우
    • 사실 변경이 안된것이 아니라 화면만 전환이 안된것이다. (input 같은 경우)
    • 이럴때에는 value 에 입력 값을 바인딩 해준다.
728x90
반응형
반응형
  • 301(Permanently Moved)
    • 요청한 URL에 대한 HTTP 요청의 처리 책임이 영구적으로 Location 헤더에 반환된 URL 로 이전되었다는 응답.
    • 영구적으로 이전되었으므로 브라우저는 이 응답을 캐시한다.
    • 추후 같은 URL 로 요청시 브라우저는 캐시된 원래 URL 로 요청을 보낸다.
  • 302 (Found)
    • 요청한 URL 이 "일시적으로" Location 헤더가 지정하는 URL 에 의해 처리되어야 한다는 응답.
    • 클라이언트 요청은 항상 단축 URL 서버에 먼저 보내진 후 원래 URL 로 리다이렉션이 된다.

 

728x90
반응형
반응형
  • 컬랙션 객체임을 JPA 에 알려주는 Annotation.
    @Entity 
    public class Person { 
    	@Id 
        private Long id; 
        private String email; 
        
        @ElementCollection 
        @CollectionTable( name = "address", joinColumns = @JoinColumn(name = "person_id") ) 
        List<AddressInfo> addressInfoList = new ArrayList<>(); 
    }
  • Entity 와 라이프 싸이클을 같이 하며 독립적으로 사용 불가능 하다.
  • 부모 Entity가 삭제될 경우 같이 삭제된다. (실제 클래스에 cascade 를 설정하는 옵션이 없다.)
  • ElementCollection의 Fetch 전략은 기본이 Lazy 이다.
  • 실제 테이블은 FK 를 이용해서 생성된다.
    Hibernate: create table address (person_id bigint not null, address1 varchar(255), address2 varchar(255), zip_code varchar(255))
    Hibernate: create table person (id bigint not null, email varchar(255), primary key (id))
    Hibernate: alter table address add constraint FK81ihijcn1kdfwffke0c0sjqeb foreign key (person_id) references person
  • CollectionTable Annocation 을 사용하지 않을 경우에는 다음과 같이 테이블이 생성된다.
    Hibernate: create table person_address_info_list (person_id bigint not null, address1 varchar(255), address2 varchar(255), zip_code varchar(255))
728x90
반응형
반응형

JPA 가 엔티티 데이터에 접근하는 방식을 지정한다.

1. AccessType.FIELD : 필드에 직접 접근한다.

@Access(AccessType.FIELD)
private String address1;

2. AccessType.PROPERTY : 프로퍼트로 접근한다. 

@Access(AccessType.PROPERTY)
public String getAddress2() {
	return address1 + address2;
}

3. AccessType 이 지정되지 않은 경우는 @Id 위치에 따라 지정된다.

@Entity
public class OrderInfo {
    @Id
    private Long id;
    private String address1;
    @Transient
    private String address2;

    @Access(AccessType.PROPERTY)
    public String getAddress2() {
        return address1 + address2;
    }

    public void setAddress2(String address2) {
        this.address2 = address2;
    }
}

- @Id 위치가 필드에 있기때문에 기본적으로 AccessType.FIELD 가 적용된다. AccessType.PROPERTY를 같이 적용하기 위해서는 메소드 위에 AccessType.PROPERTY 를 넣어주면 된다.

4. 기타 설명들

@Access is used to specify how JPA must access (get and set) mapped properties of the entity. If access type is set to FIELD, the values will directly be read/set on the field, bypassing getters and setters. If set to PROPERTY, the getters and setters are used to access the field value.

FIELD 로 정의하면 다이렉트로 field를 read/set 하고 PROPERTY로 설정하면 getter, setter 메소드를 통해서 접근한다.
https://stackoverflow.com/questions/19264871/what-is-the-use-of-the-access-annoation-in-jpa-means-at-the-entity-level

 

If you use field-based access, your JPA implementation uses reflection to read or write your entity attributes directly. It also expects that you place your mapping annotations on your entity attributes. If you use property-based access, you need to annotate the getter methods of your entity attributes with the required mapping annotations. Your JPA implementation then calls the getter and setter methods to access your entity attributes.

5 reasons why you should use field-based access
Better readability of your code
Omit getter or setter methods that shouldn’t be called by your application
Flexible implementation of getter and setter methods
No need to mark utility methods as *@Transient*
Avoid bugs when working with proxies

https://thorben-janssen.com/access-strategies-in-jpa-and-hibernate/

 

 

728x90
반응형

+ Recent posts