전체 글

전체 글

    Java 리팩토링 - 조건문 분해하기

    1. 알고자 하는 것 이전 Java 리팩토링 강의 내용 모두 유익하다고 생각했지만, 유독 이 내용은 간단해보이면서도 실무에서 정말 많이 적용 가능한 리팩토링 기법이라고 생각한다. 실제로 코드리뷰 때에도 해당 부분에 대해서 얘기를 많이 했고, 대체로 누군가 짠 코드를 처음 보는 입장이라고 생각해보았을 때, 조건문을 분해(or 추출)했을 때의 가독성이 정말 높아진다고 생각한다. 내가 짠 코드를 처음 보는 사람이 쉽게 이해할 수 있는 코드를 짜는 데에 좋은 첫 걸음이 될만한 부분이라고 생각한다. 항상 좋은 코드, 읽기 쉬운 코드를 짜도록 노력하는 습관을 들이자. 조건문 분해하기 2. 알게된 것 프로그램에는 언제나 조건이 있다. if-else로 분기되는 조건문은 단순한 조건인 경우에는 이해하기 쉽다. 또한,..

    FeignClient에서 read timeout 발생 시 주의사항 (w/ Retry, RetryableException)

    1. 알고자 하는 것 FeignClient에서의 read timeout FeignClient 이슈 분석 FeignClient에서 read timeout 발생 시 주의사항 2. 알게된 것 배경 회사에서 MSA 전환을 준비하기 이전 단계로, 일부 이관되어 멀티모듈로 구성되어있는 프로젝트에 대해 FeignClient로 모듈 간 통신을 하며 발생했던 이슈이다. 특정 조건에 해당하는 n건의 데이터에 대해 일괄적으로 배치 처리를 수행하는 Job이 있다. 해당 Job은 1시간 간격으로 수행되며, 한 번 수행 시 평균 약 5-10건의 데이터를 대상으로 수행된다. Job 내에서 다른 모듈의 API를 FeignClient를 통해 호출하여 추출된 데이터에 대한 비즈니스 로직을 처리한다. 반환값은 따로 없으며, 데이터에 대한..

    Java 리팩토링 - 함수를 명령(Command)으로 바꾸기

    1. 알고자 하는 것 함수를 명령으로 바꾸기 2. 알게된 것 함수를 명령으로 바꾸기 기본적으로 코드가 길어지고 이로 인해 가독성이 떨어진다면, 함수 추출(Extract Method)을 수행해 가독성을 높이고 복잡도를 낮출 수 있다. 함수 추출(Extract Method)을 수행해도 코드의 위치가 해당 위치가 아니라고 생각될 때 함수를 명령으로 바꾸는(Replace Function with Command) 방법을 고려한다. 해당 위치가 아니라고 생각된다 = 클래스의 맥락에서 해당 함수가 별도의 위치로 분리될 필요가 있다. 함수를 독립적인 객체(=Command)로 분리한다. try (FileWriter fileWriter = new FileWriter("participants.md"); PrintWriter..

    [Real MySQL, 4장 - 트랜잭션과 잠금] MySQL에서의 트랜잭션

    1. 알고자 하는 것 트랜잭션(Transaction)이란 트랜잭션이 필요한 이유 트랜잭션 적용 시 주의사항 2. 알게된 것 트랜잭션(Transaction)이란 데이터베이스에서 작업의 완전성을 보장하기 위한 개념 작업을 더 이상 쪼갤 수 없는 하나의 원자적인 단위로 묶음 이러한 논리적인 작업셋이 모두 성공하거나, 하나라도 실패 시 모두 적용하지 않고 되돌리는 것 (All or Nothing) 이는 단지 여러 개의 쿼리를 묶는 것만을 의미하지는 않음 단 하나의 쿼리라도 원자적인 작업으로 묶어, 실패 시 되돌린다. 다음과 같은 테이블이 있을 때, unique로 지정된 uid 컬럼이 중복되었을 때 트랜잭션이 어떻게 동작하는지 확인해본다. create table member ( id bigint auto_incr..

    Java 리팩토링 - 메서드 추출 시 매개변수가 많아질 경우 [3. 객체 통째로 넘기기]

    1. 알고자 하는 것 - 메서드를 추출할 때(Extract method), 해당 메서드에 넘겨야 하는 매개변수가 많아질 경우의 리팩토링 1. 임시 변수를 질의 함수로 바꾸기 (Replace Temp with Query) 2. 매개변수 객체 만들기 (Introduce Parameter Object) 3. 객체 통째로 넘기기 (Preserve Whole Object) 2. 알게된 것 하나의 객체에서 구할 수 있는 여러 값을 메서드의 매개변수로 넘겨주는 경우, 객체를 통째로 넘겨줄 수 있다. 이를 통해 결과적으로 아래와 같이 매개변수의 개수를 줄일 수 있다. //(BEFORE) // 매개변수로 String, Map을 넘겨준다. private String getMarkdownForParticipant(Strin..

    [Real MySQL, 3장 - 아키텍처] MySQL에서의 복제(Replication)

    1. 알고자 하는 것 데이터베이스에서 대용량 데이터를 처리하기 위한 가용성(Availability)과 확장성(Scalability) MySQL에서의 복제(Replication) 복제(Replication) 시 고려해야 할 주의사항 Statement 포맷 방식과 Row 포맷 방식 2. 알게된 것 데이터베이스에서 대용량 데이터를 처리하기 위한 가용성(Availability)과 확장성(Scalability) 서비스 사용자의 수가 늘어나고, 서비스 아키텍처가 커짐에 따라 그에 따른 데이터는 기하급수적으로 많아진다. 이렇게 많아지는 데이터를 기존 하나의 데이터베이스만으로 관리하기 힘들다. 많은 데이터를 하나의 데이터베이스에서 다루게 되면 그에 따른 트래픽을 모두 하나의 데이터베이스가 감당해야 한다. 수많은 요청에..

    QueryDsl에서 결과를 가져오는 메서드, fetchFirst()와 fetchOne()의 차이

    1. 알고자 하는 것 회사에서 mybatis 쿼리를 querydsl로 전환하는 작업 중, update_date 기준으로 정렬된 n개의 결과 중 첫번째 결과만을 가져오는 쿼리가 있었다. 그런데, 쿼리를 실행하니 다음과 같은 Exception이 발생했다. Caused by: javax.persistence.NonUniqueResultException: result returns more than one elements at org.hibernate.jpa.internal.QueryImpl.getSingleResult.... 단건의 결과가 아닌 여러 건의 결과(Non Unique Result)가 반환되어 발생한 오류였다. 원인이 바로 짐작이 가 쿼리를 확인해보니, 역시나 QueryDsl을 통해 쿼리를 짤 때 ..

    QueryDsl에서 in절에 empty list, null이 올 때 어떻게 처리될까?

    1. 알고자 하는 것 회사에서 동기가 MyBatis로 작성한 쿼리 중, in절에 대해 empty list가 넘어올 때 Syntax 오류가 발생하여 empty list에 대한 방어 코드 작성 후 다시 배포했었던 상황이 있었다. QueryDsl로 작성한 쿼리에 대해서는 in절에 대해서 별다른 문제가 없었던 것으로 기억해서, QueryDsl의 in절의 내부 동작과 함께 in절에서의 여러 케이스에 대한 결과를 비교해보고자 한다. QueryDsl에서 in query를 사용할 때 List에 empty list가 올 때의 결과 QueryDsl에서 in query를 사용할 때 List에 null이 올 때의 결과 QueryDsl에서 in query의 내부 동작 2. 알게된 것 QueryDsl에서 in절을 테스트 하기..

    [Real MySQL, 3장 - 아키텍처] MySQL 엔진, 스토리지 엔진

    1. 알고자 하는 것 MySQL 엔진 스토리지 엔진 쿼리의 전체적인 실행 구조 2. 알게된 것 MySQL 엔진 클라이언트, 서버 등에서 요청한 SQL 문장의 파싱 및 최적화를 수행 DBMS의 두뇌로 비유 크게 커넥션 핸들러, SQL Parser, 전처리기, 옵티마이저로 구성 커넥션 핸들러 : 클라이언트와의 접속, 스토리지 엔진에게 데이터 R/W 쿼리 요청 SQL Parser : 클라이언트가 요청한 쿼리를 MySQL이 인식할 수 있는 단위 (토큰)로 분리해 트리형태 구조로 파싱. 쿼리의 문법적 오류를 해당 SQL Parser가 발견하고 오류 전달 전처리기 : 파서 트리 내 토큰과 개체(컬럼명, 내장함수, 객체 접근권한)를 비교해 쿼리 문장의 구조적 오류 확인. 존재하지 않는 토큰, 권한 오류를 해당 전처리..

    JpaRepository의 save() 메서드 내부동작 - Persist vs Merge

    1. 알고자 하는 것 - JpaRepository의 save() 메서드의 동작에 대해 내부 코드를 확인한다. - 내부 코드 중 persist와 merge의 차이를 테스트코드로 확인한다. 2. 알게된 것 JpaRepository의 save 메서드 내부 확인 - 일반적으로 JpaRepository는 다음과 같이 인터페이스 형식으로 상속받아 편리하게 기본 CRUD 메서드를 사용한다. public interface MemberRepository extends JpaRepository { } - 이 때, JpaRepository 인터페이스를 구현한 SimpleJpaRepository를 target으로 가지는 Proxy가 Bean으로 등록된다. - 실제 CRUD 동작은 SimpleJpaRepository가 수행하는..