동시성 제어를 위한 DB 락에 대해 알아보자
·
Java/JPA
이번에 컨텐츠를 사고팔 수 있는 커머스 서비스를 개발하다보니 동시에 일어난 결제를 처리하는 방법으로 락에 대해서 공부하게 되었다. 내용을 복습할 겸 블로그에 정리해보고자 한다. 1. 락이란?웹 서비스는 여러 사용자의 요청을 동시에 처리한다. 조회 API나 데이터 정합성이 덜 중요한 데이터라면 큰 문제가 없을 수 있지만, 잔액 차감, 재고 감소처럼 정합성에 민감한 데이터에서는 동시 요청이 치명적일 수 있다. 예를 들어 사용자 A의 크레딧 잔액이 10,000원이고, 동시에 두 개의 구매 요청이 들어왔다고 가정해보자.첫 번째 요청은 7,000원을 차감하려고 하고, 두 번째 요청도 7,000원을 차감하려고 한다. 둘 다 거의 동시에 잔액을 조회하면 두 요청 모두 “현재 잔액은 10,000원이므로 구매 가능하다”..
Java SpringBoot의 테스트에 대해 알아보자
·
Java
스프링 프로젝트를 진행하던 중 테스트 방법에 대해 고민하게 되었다.처음에는 단위 테스트(Mockito), 통합 테스트 등 모든 테스트를 작성하고자 생각했었다.구현했을 당시에는 문제가 없었지만 개발 초기 단계다 보니 비지니스 로직이 바뀌는 경우가 잦아지면서 테스트 또한 매번 변경해줘야하는 문제가 발생하여 테스트 구조 변경을 고려하게 되었다. 겸사겸사 블로그에 자바 스프링에서의 테스트에 대해 한번 정리하고자한다. 테스트에는 크게 슬라이스 테스트, 단위 테스트, 통합 테스트로 나뉜다.슬라이스 테스트컨트롤러 레이어, 영속성 레이어, 외부 API 호출 등 특정 레이어만 잘라서 해당 레이어에 필요한 빈들만 올려 테스트스프링에서는 컨트롤러 레이어를 테스트하는 @WebMvcTest, 영속성 레이어를 테스트하는 @Da..
모던 자바 인 액션 - chapter 7, 8 병렬 데이터 처리와 성능, 컬렉션 API 개선
·
Java
병렬 데이터 처리와 성능자바 7은 쉽게 병렬화를 수행하면서 에러를 최소화할 수 있도록 fork/join 프레임워크 기능을 제공한다.병렬 스트림컬렉션에 parallelStream을 호출하면 병렬 스트림이 생성된다. 병렬 스트림은 각각의 스레드에서 처리할 수 있도록 스트림 요소를 여러 청크로 분할한 스트림이다. 따라서 병렬 스트림을 이용하면 모든 멀티코어 프로세서가 각각의 청크를 처리하도록 할당할 수 있다.stream에서 parallel을 호출하면 내부적으로 이후 연산이 병렬로 수행한다. 반대로 sequential로 병렬 스트림을 순차 스트림으로 바꿀 수 있다. 이 두 메서드를 이용해서 병렬로 실행할지 순차로 실행할지 제어할 수 있다. 이 중 최종적으로 호출된 메서드가 전체 파이프라인에 영향을 미친다.병렬 ..
모던 자바 인 액션 - chapter 6 스트림 데이터 수집
·
Java
스트림으로 데이터 수집컬렉터Collector 인터페이스는 어떻게 구현하느냐에 따라 스트림에 어떤 리듀싱 연산을 수행할지 결정된다. Collectors 유틸리티 클래스는 자주 사용하는 컬렉터 인스턴스를 손쉽게 생성할 수 있는 정적 팩토리 메서드를 제공한다.Collectors에서 제공하는 메서드의 기능은 크게 세가지로 구분할 수 있다.스트림 요소를 하나의 값으로 리듀스하고 요약요소 그룹화요소 분할리듀싱과 요약counting: 개수를 카운트한다maxBy, minBy: 최대 혹은 최소를 만족하는 요소를 찾는다summingInt: 객체를 int로 매핑하는 인수를 받아 합 계산averagingInt: 객체를 int로 매핑하는 인수를 받아 평균을 계산한다summarizingInt: 요소 수, 합계, 평균, 최대값, ..
모던 자바 인 액션 - chapter 4, 5 스트림과 활용
·
Java
스트림 스트림이란 무엇인가?선언형으로 컬렉션 데이터를 처리할 수 있도록 자바 8 API에 추가된 기능이다. 또한 멀티스레드 코드를 구현하지 않아도 손쉽게 데이터를 병렬 처리할 수 있다.스트림의 장점은 다음과 같다.선언형으로 코드를 구현할 수 있다.여러 블록연산을 연결해서 복잡한 데이터 처리 파이프라인을 만들 수 있다.병렬 스트림을 사용하여 데이터 처리 속도를 높일 수 있다.원본 데이터를 변경하지 않으므로 데이터의 불변성을 유지할 수 있다.지연 연산을 통해 필요할 때만 연산을 수행하여 성능을 최적화할 수 있다.** 지연 연산: filter, map과 같은 중간 연산은 collect와 같은 최종 연산이 호출되었을 때만 실행된다.컬렉션과 스트림컬렉션은 현재 자료구조가 포함하는 모든 값을 메모리에 저장하는 자료..
모던 자바 인 액션 - chapter 2, 3 동작 파라미터화, 람다 표현식
·
Java
동작 파라미터화동작 파라미터화는 메서드 내부적으로 다양한 동작을 수행할 수 있도록 코드를 메서드 인수로 전달한다. 이는 자주 바뀌는 요구사항에 효과적으로 대응할 수 있다. 동작 파라미터화 방법기존엔 클래스를 통한 동작을 메서드의 인수로 전달하는 방법을 통해 구현해야 했다. 익명 클래스로도 어느 정도 코드를 깔끔하게 만들 수 있지만 자바 8에서는 인터페이스를 상속받아 여러 클래스를 구현해야 하는 수고를 없앨 수 있는 람다(익명 함수)를 제공한다.선택 조건을 결정하는 인터페이스 선언(Predicate)public interface ApplePredicate { boolean test(Apple apple);}클래스를 통한 동작 파라미터화public class AppleGreenColorPredicate..
모던 자바 인 액션 - chapter 1 자바 8 무슨 일이 일어나고 있는가
·
Java
프로그래밍 분야는 빅데이터라는 도전에 직면하면서 멀티코어 컴퓨터나 컴퓨팅 클러스터를 이용해서 빅데이터를 효과적으로 처리할 필요성이 증가했다. 또한 병렬 프로세싱을 활용해야 하는데 이전의 자바로는 충분히 대응할 수 없었다. 자바 8부터 추가되는 기능은 현 시장에 요구하는 기능을 효과적으로 제공한다. 이 책은 자바 8에서 제공하는 기능의 모태인 세 가지 프로그래밍 개념을 상세히 설명한다.세 가지 프로그래밍 개념스트림 처리스트림 API는 파이프라인(중간 연산이 연결되어 하나의 연산을 이루는 것)을 만드는데 필요한 많은 메서드를 제공한다. 또한 Thread를 사용하지 않으면서 병렬성을 손쉽게 얻을 수 있다.동작 파라미터화로 메서드에 코드 정달하기메서드를 파라미터화 해서 전달가능하다. 함수형 프로그래밍 기술을 활..
스트림(2) - Stream API의 다양한 연산
·
Java
스트림 API가 지원하는 다양한 연산에 대해서 알아보자. 요약  필터링.filter()filter 메소드는 predicate(boolean을 반환하는 함수)를 인수로 받아서 true를 반환하는 모든 요소를 포함하는 스트림을 반환한다.List vegetarianMenu = menu.stream() .filter(Dish::isVegetarian) .collect(toList());// 채식요리 .distinct()스트림 요소의 중복을 제거하는 distinct 메소드도 지원한다.(중복 여부는 equals와 hashCode로 결정된다)List numbers = Arrays.asList(1,2,3,4,..
equals와 hashCode
·
Java
내가 만든 객체로 List를 만들었는데 List 내에 중복되는 객체가 있다면 제거하고 싶다고 가정해보자.List peopleList = new ArrayList();people.add(new Person("loopy"))people.add(new Person("loopy"))Set peopleSet = new HashSet(people);if(peopleList.size() != peopleSet.size()) { throw new IllegalArgumentException();} 이 코드를 진행했는데 Exception이 발생하지 않고 다음 코드로 넘어간다. 왜일까?정답은 내가 만든 객체에서 equals와 hashCode 메소드를 재정의(override)하지 않았기 때문이다.  equals와 ha..
스트림(1) - Stream API 개요
·
Java
스트림이란?데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소 스트림은 함수형 프로그래밍 언어와 데이터베이스에서 일반적으로 지원하는 연산을 지원한다. 예를 들어 filter, map, find, match, sort 등으로 데이터를 조작할 수 있다. 스트림 연산은 순차적으로 또는 병렬로 실행할 수 있다.  예시를 보자.menu.stream() .filter(dish -> dish.getCalories() > 300) .map(Dish::getName) .limit(3) .collect(toList());  1. 데이터 소스 menu는 연속된 요소를 스트림에 제공한다.2. stream()을 통해 스트림을 얻고3. 데이터 처리 연산(filter, map, limit, collec..