불변 객체 역직렬화 방법 분석

배경 data class Person(var id: Long? = null, var name: String? = null) fun main() { val objectMapper = ObjectMapper() val person: Person = objectMapper.readValue("{\"id\":1, \"name\": \"junroot\"}", Person::class.java) println(person.name) } ObjectMapper를 통해 역직렬화하는 경우, 기본 생성자를 이용해 객체를 생성한 뒤 자바 리플렉션을 이용해 값을 주입하고 있다. 따라서 기본 생성자가 필요한데 이렇게 되면 프로퍼티들이 불변일 수가 없게된다. @JsonCreator와 @JsonProperty를 통해서 생성 가능하다는 사실을 알게되고 이를 사용했었다. data class Person @JsonCreator constructor( @JsonProperty("id") val id: Long, @JsonProperty("name") val name: String ) fun main() { val objectMapper = ObjectMapper() val person: Person = objectMapper....

2024-09-15 · 2 min · 260 words

범위 탐색 시 인덱스 설계

목표 WHERE 절에서 범위 탐색 시에 인덱스 설계하는 방법을 이해한다. 상황 SELECT first_name, last_name, date_of_birth FROM employees WHERE date_of_birth >= '1971-01-01' AND date_of_birth <= '1971-01-09' AND subsidiary_id = 27 위와 같은 상황에 date_of_birth와 subsidiary_id 의 인덱스 컬럼 순서를 어떻게 해야될지 알아보자. date_of_birth, subsidiary_id 순으로 인덱스 설계할 경우 date_of_birth 기준으로 먼저 정렬되어 있다. 중간 노드만으로는 어느 리프 노드가 subsidiary_id가 27인 경우를 가지고 있는지 알 수 없다. 쿼리에 date_of_birth의 범위 조건이 있으므로, 이를 기준으로 먼저 범위 탐색을 하게 된다....

2024-09-15 · 1 min · 167 words

버블링과 캡처링

목표 이벤트 버블링과 캡처링이 무엇인지 이해한다. 이벤트 기본적으로 js에서는 각 요소(element)가 이벤트를 발생시킬 수 있고, 이벤트 리스너를 통해서 이벤트가 발생했을 때의 동작을 명시할 수 있다. const btn = document.querySelector("button"); btn.addEventListener("click", () => { console.log("event!"); }); 이벤트 전파 실제로 이벤트가 발생한 요소가 아니라 다른 요소에서 이를 처리하고 싶을 떄가 있다. 이 때 이벤트 전파를 이용하게 된다. 이벤트 전파는 버블링과 캡처링이 존재한다. 이벤트가 발생하면 3가지 단계로 이벤트가 흐른다. 캡처링 단계: 이벤트가 하위 요소에 전파되는 단계 타깃 단계: 이벤트가 실제 타깃 요소에 전달되는 단계 버블링 단계: 이벤트가 상위 요소로 전파되는 단계 이벤트가 발생하면 최상위 조상에서 시작해서 아래로 전파가 시작되고 캡처링 -> 타깃 -> 버블링 단계를 거치게 된다....

2024-09-15 · 1 min · 202 words

배포마다 DB 테이블이 삭제되지 않도록 구성하기

properties 파일에 아래의 설정을 추가하여 해결했다. spring.jpa.hibernate.ddl-auto=validate 문제점: 새로운 not null 컬럼이 추가되었을 때 기존 row들은 어떻게 처리하는 것이 좋을까? 예를들어, 서비스가 확장되면서 User에 Age컬럼이 추가되었을 때, Age가 not null 이라면 기존의 사용자 데이터는 어떻게 처리하는 것이 좋을까? → 구글링 결과, 방법은 1. not null을 포기하거나 2. default value를 설정하거나 두 가지 방법 밖에없다. 상태로 컬럼을 추가하는 수밖에 없다. (어떻게 보면 당연하다 우리가 사용자의 나이를 추측할 순 없으니까) 1. not null 포기 기존 데이터는 null로 두고 이후에 생성되는 데이터에서는 null이 들어오지 못하도록 DTO에서 null 값체크를 하도록 구현한다....

2024-09-15 · 2 min · 403 words

반환 값이 void인 메소드 아무것도 하지 않게 mocking

doNothing().when(myList).add(any(Integer.class), valueCapture.capture()); https://www.baeldung.com/mockito-void-methods

2024-09-15 · 1 min · 3 words

뮤텍스와 세마포어의 차이

공유 자원을 관리하기 위해서 뮤텍스와 세마포어라는 기법으로 상호배제를 보장할 수 있다. 이 둘은 비슷해보이지만 몇 가지 차이점이 있다. 간단하게만 정리해봤다. 유사점 세마포어는 공유할 수 있는 프로세스의 수를 정수형으로 저장하고 0보다 클 때 까지만, 접근에 허용한다. 만약 이 정수가 1로 시작한다면 뮤텍스와 동작이 비슷해보인다. 차이점 세마포어 정수형 데이터지만, 뮤텍스는 객체다. 세마포어는 신호 메커니즘이고, 뮤텍스는 잠금 메커니즘이다. 세마포어는 wait, signal 신호로 값이 수정된다. 뮤텍스는 뮤텍스를 소유하고 있는 프로세스가 lock 또는 unlock을 할 수 있다....

2024-09-15 · 1 min · 91 words

문자의 ASCII 코드 값 찾기

ord() 함수를 사용하면 된다. character = 'P' unicode_char = ord(character) print(unicode_char) 참고 자료 https://www.programiz.com/python-programming/methods/built-in/ord

2024-09-15 · 1 min · 14 words

무중단으로 DB 스키마 수정하기

배경 운영중인 DB에 여러 애플리케이션이 사용하고 있으면 컬럼 수정/삭제가 제한이 된다. Online Schema Change 정의 이름 그대로 운영중인 상태에서 스키마를 변경하는 기법을 말한다. 동작 과정 대상 테이블을 복제한다. 복제된 테이블에 스키마를 수정한다. binary log stream이나 trigger 등을 사용해서 복제된 테이블에 변경사항을 반영한다. 수정된 코드를 배포한다. 대상 테이블과 복제된 테이블을 swap한다. 주요 툴 Meta: https://github.com/facebookincubator/OnlineSchemaChange gh-ost: https://github.com/github/gh-ost 참고 자료 https://jojoldu.tistory.com/358 https://blog.myungseokang.dev/posts/online-schema-change/

2024-09-15 · 1 min · 60 words

모든 메서드 호출 로깅하기

목표 mocking 한 객체들의 메서드 호출들을 모두 로깅하도록 한다. MockSettings 일반적으로 mockito를 이용해서 목킹할 때 mock(MyClass.class) 형태로 목칭을 하지만, 두번째 인자로 목킹할 때 추가적인 설정을 할 수 있다. MockSettings customSettings = withSettings().defaultAnswer(new CustomAnswer()); MyList listMock = mock(MyList.class, customSettings); MockSettings에는 invocationListeners를 등록할 수 있고, 이는 목킹한 객체에 메서드 호출이 발생할 때 동작하는 리스너다. List mockWithListener = mock(MyList.class, withSettings().invocationListeners(new YourInvocationListener())); Mockito-Kotlin 도 이를 지원하고 있고, 이를 통해서 호출된 메서드가 무엇인지 로깅할 수 있다....

2024-09-15 · 1 min · 86 words

모든 ip에서 사용가능한 계정 만들기

create user [username]@'%' identified by '[password]';

2024-09-15 · 1 min · 6 words

명령어로 특정 클래스만 테스트 하는 법

gradle test --tests SomeClass https://stackoverflow.com/questions/22505533/how-to-run-only-one-unit-test-class-using-gradle

2024-09-15 · 1 min · 5 words

리플리케이션(Replication)

사용자가 많은 Database는 많은 쿼리를 모두 처리하기 힘들어, CUD를 위한 데이터베이스(master)와 read를 위한 database를(slave) 따로 나눈다. 참고 자료 https://kwonnam.pe.kr/wiki/springframework/transaction https://nesoy.github.io/articles/2018-02/Database-Replication

2024-09-15 · 1 min · 20 words

리눅스에서 로그 파일 열기

배경 용량이 큰 로그 파일을 vim이나 cat으로 열게 된다면, 파일 내용을 RAM에 모두 올리면서 OOM 에러가 발생할 수 있다. less less [파일명] 이 명령어를 통해 파일을 열면 내용을 청크로 잘라서 조금씩 볼 수 있기 때문에 OOM이 발생하지 않는다. 참고 자료 https://jmseo.tistory.com/69

2024-09-15 · 1 min · 41 words

로드 밸런싱

L4와 L7 2가지가 있다. L4는 TCP, UDP 정보(특히 포트 넘버)기반으로 로드 밸런싱을 수행한다. L7는 애플리케이션 계층의 프로토콜 정보를 기반으로 수행한다. Nginx에서 수행하는 리버스 프록시가 유사한 기능을 가지고 있다. 한 서버에 장애가 발생했을 때, 다른 서버를 통해 서비스를 제공할 수 있다. 동일한 서비스를 다수의 서버에 부하를 분산시킨다.

2024-09-15 · 1 min · 46 words

로깅 테스트하기

logback 구현체를 통해서 appender를 추가해서 테스트를 진행할 수 있다. ListAppender를 사용하면 로깅 내용을 메모리로 저장할 수 있다. class ReflectionsTest { private static final Logger log = (Logger) LoggerFactory.getLogger(ReflectionsTest.class); private static final ListAppender<ILoggingEvent> listAppender = new ListAppender<>(); static { listAppender.setContext((LoggerContext) LoggerFactory.getILoggerFactory()); log.setLevel(Level.DEBUG); log.addAppender(listAppender); listAppender.start(); } @Test void someTest() { //... assertThat(result).contains("[DEBUG] examples.QnaController", "[DEBUG] examples.MyQnaService", "[DEBUG] examples.JdbcUserRepository", "[DEBUG] examples.JdbcQuestionRepository"); } } 참고 자료 https://www.baeldung.com/junit-asserting-logs

2024-09-15 · 1 min · 62 words

디플로이먼트 파드 전체 재시작

목표 디플로이먼트에 속한 파드 전체를 재시작한다. 방법 kubectl rollout restart <resource> 예시 kubectl rollout restart deployment/nginx 참고 자료 https://kubernetes.io/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_restart/

2024-09-15 · 1 min · 19 words

디렉토리 경로와 파일이름 합치기

import os os.path.join(dirname, filename) 참고 자료 https://wikidocs.net/39

2024-09-15 · 1 min · 7 words

두 리스트가 순서 상관없이 동일한지 비교

assertThat(a).containsExactlyInAnyOrderElementsOf(b); 참고 자료 https://www.baeldung.com/java-assert-lists-equality-ignore-order

2024-09-15 · 1 min · 4 words

동등성 비교

assertThat(fido).isEqualToComparingFieldByFieldRecursively(fidosClone); 참고 자료 https://www.baeldung.com/introduction-to-assertj

2024-09-15 · 1 min · 4 words

도커 스웜을 이용한 스케일 아웃

기존에 내가 진행하던 프로젝트는 WAS가 한 대 뿐이었다. 이번에 성능 향상을 목적으로 스케일 아웃을 진행하기로 결정했다. 스케일 아웃을 진행하면서 처리해야될 작업들에는 다음이 있었다. 서버가 여러 대인 점을 이용한 무중단 배포 WAS가 늘어나면서 NGINX에서 요청을 전달한 WAS 선택 방법 (로드 밸런싱) 이를 해결하기 위해서 나는 도커 스웜을 사용해보기로 결정했다. 그 이유는 다음과 같다. 도커 스웜은 자체적으로 롤링 업데이트를 지원하며, 매우 간단하게 사용할 수 있다. ingress 네트워크를 통해 NGINX에 추가적인 설정을 하지않아도, ingress의 로드 밸런서가 라운드 로빈 방식을 사용해서 WAS의 트래픽을 분산시킬 수 있다....

2024-09-15 · 3 min · 620 words