전체 글

https://github.com/oddnine
JAVA/kafka

[Spring] 카프카 스프링에서 토픽 프로듀싱, 컨슈밍 해보자. (feat. nGrinder)

일단 수강 신청 시에 많은 트래픽이 몰려온다고 가정을 하고 아래와 같이 아키텍처를 구성하였다. 구조는 브로커를 복제해서 하나의 브로커가 고장이 나도 예비 브로커를 사용할 수 있도록 하였고, enrollment_create의 경우 순서 보장이 확실하게 이루어져야 하기 때문에 파티션 하나를 사용하였다. 그 외는 순서 보장이 필요 없기 때문에 파티션 3개를 사용하여 분할 적재하였다. 흐름은 아래와 같다. 학생은 수강 신청을 요청하면 수강 신청 정보는 학생 쪽 Producer에서 enrollment_create 토픽에 적재가 된다. 적재된 정보는 수강 신청 서비스에서 Consumer 해준 다음 수강 신청 로직을 돌린 후 enrollment_history_create에 수강 신청 정보를 적재한다. 수강 신청 로그..

JAVA/kafka

[kafka/Docker] 도커로 카프카를 띄워보고, 토픽 생성 후 메시지를 보내보자.

카프카란? 실시간으로 기록 스트림을 게시, 구독, 저장 및 처리할 수 있는 분산형 데이터 스트리밍 플랫폼이다. 즉, API로 데이터를 바로 요청을 하는 것이 아닌 미들웨어인 카프카를 둬서 프로듀서가 메시지를 생산해서 토픽으로 메시지를 보내고, 컨슈머는 토픽의 메시지를 가져와 사용하는 애플리케이션 부분이다. 따라서 연결되어 있는 토픽에 메시지(큐)가 들어오면 컨슈머는 그 메시지를 받을 수 있는 것이다. 장점) 1. 대량의 데이터를 처리 가능하고, 시스템 부하에 따라 확장이 가능하다. 2. 카프카는 실시간 데이터 처리를 위해 설계되었다. 데이터가 전송되는 즉시 프로듀서와 컨슈머가 데이터를 처리할 수 있고, 데이터의 지연 시간이 최소화되기 때문에 실시간 데이터 스트리밍이 가능하다. 3. 카프카는 메시지를 영속..

JAVA/JPA

[JPA/QueryDSL] N+1 문제 해결하는 방법(EntityGraph, fetchJoin)

JPA를 사용하다 보면 N+1 문제를 직면하는 일이 많다. N+1 문제란 예를 들어 친구 목록을 가져오는데 각각 친구들의 상태 메시지는 다른 테이블에서 가져온다고 가정하면 두 테이블을 한 번에 가져오지 않았을 때 쿼리는 두 번 나가게 될 것이고 친구들 전체를 가져오게 된다면 N+1로 쿼리 수가 상당히 많아질 것이다. 즉, 추가적인 쿼리를 계속 보내는 것이다. 따라서 이러한 다수의 쿼리를 보내는 것을 방지하기 위해 한 번에 가져와야 하는데 그때 쓰이는 방법은 JPA에서는 @EntityGraph이고, QueryDSL에서는 .fetchJoin을 해주면 된다. JPA(EntityGraph) @Override @EntityGraph(attributePaths = {"userCar", "account", "addr..

JAVA/Spring

[Spring/Thymeleaf] 타임리프를 이용해서 ENUM 타입 셀렉트 박스 만들기

요즘 마지막 학기 프로젝트로 인해 뜸했다.. 프로젝트를 진행하면서 도메인 안에 위처럼 ENUM 타입이 있는데 정보를 입력할 때 ENUM은 셀렉트 박스로 하고 싶었다. ENUM public enum CarCategory { LIGHT("경차"), SMALL("소형차"), SEMI_MEDIUM("준중형"), MEDIUM("중형"), SEMI_FORMAL("준대형"), LARGE("대형"); @Getter private final String description; CarCategory(String description) { this.description = description; } } 차량 종류에 대한 ENUM이다. 컨트롤러 /** * enum */ @ModelAttribute("carCategories"..

JAVA/Spring

[Spring] Cannot invoke "" because "" is null 오류 해결

서비스 코드에서 레파지토리를 사용하려고 하는데 제목과 같은 오류가 났을 경우 Repository 선언에 아래와 같이 final을 붙이면 된다. 안 붙이게 되면 빈 주입이 되지 않아 null이 된다. private final UserCarRepository userCarRepository; (서비스 부에서 Repository 선언한 코드) 이런 실수를 하다니

Coding Test/DFS & BFS

[BFS] 백준 - 17836번: 공주님을 구해라! Java 풀이

[공부용이기 때문에 코드가 깔끔하지 않을 수 있습니다!] 17836번: 공주님을 구해라! 용사는 마왕이 숨겨놓은 공주님을 구하기 위해 (N, M) 크기의 성 입구 (1,1)으로 들어왔다. 마왕은 용사가 공주를 찾지 못하도록 성의 여러 군데 마법 벽을 세워놓았다. 용사는 현재의 가지고 있는 www.acmicpc.net 위 문제는 n * m의 맵에서 t 시간이 주어지는데 용사는 (0, 0) 지점에서 시작하여 t 시간 이내로 (n, m)까지 가야 한다. 근데 도중에 검을 획득하게 되면 벽을 무제한으로 뚫고 갈 수 있다. 이때 가장 빠르게 가는 시간을 구하고 못 가거나 t 시간 이내로 도착하지 못했을 경우 Fail을 반환하면 된다. 코드 import java.io.*; import java.util.*; pub..

Coding Test/DFS & BFS

[BFS] 백준 - 2665번: 미로만들기 Java 풀이

[공부용이기 때문에 코드가 깔끔하지 않을 수 있습니다!] 2665번: 미로만들기 첫 줄에는 한 줄에 들어가는 방의 수 n(1 ≤ n ≤ 50)이 주어지고, 다음 n개의 줄의 각 줄마다 0과 1이 이루어진 길이가 n인 수열이 주어진다. 0은 검은 방, 1은 흰 방을 나타낸다. www.acmicpc.net 위 문제는 벽을 최소한으로 부수고 끝방까지 가는 문제이다. 먼저 (0, 0)을 제외한 모든 방은 visit에 Integer.MAX_VALUE를 준다. 그리고 다음 방에 방문 시 기존 방의 값보다 크면 일단 방에 들어간다. 그리고 그 방이 흰 방이면 q에 노드를 넣어주고 visited[nowX][nowY] = visited[xx][yy]를 해주고, 만약 검은 방일 경우 q에 노드를 넣어주고 visited[n..

JAVA/Querydsl

[Querydsl] 동적 쿼리 - Where 다중 파라미터 사용

[본 포스팅은 실전! Querydsl 편을 기반으로 작성하였습니다.] 실전! Querydsl - 인프런 | 강의 Querydsl의 기초부터 실무 활용까지, 한번에 해결해보세요!, - 강의 소개 | 인프런... www.inflearn.com 예를 들어 이름이 비어있거나 나이가 비어있을 때 데이터를 조회하기 위해선 동적 쿼리를 짜야한다. @Test public void dynamicQuery_WhereParam() { String usernameParam = "member1"; Integer ageParam = null; List result = searchMember2(usernameParam, ageParam); assertThat(result.size()).isEqualTo(1); } private L..

JAVA/Querydsl

[Querydsl] 프로젝션 결과 반환 (Projections, @QueryProjection -> DTO)

[본 포스팅은 실전! Querydsl 편을 기반으로 작성하였습니다.] 실전! Querydsl - 인프런 | 강의 Querydsl의 기초부터 실무 활용까지, 한번에 해결해보세요!, - 강의 소개 | 인프런... www.inflearn.com 데이터를 DB에서 반환받을 때 필요한 정보만 받아야 할 때가 많이 있다. 그래서 프로젝션으로 결과를 반환받는데 이때 방법을 Projections와 @QueryProjection을 사용해서 받아볼 것이다. 상황) 모든 멤버의 ID를 제외하고 이름과 나이를 반환받기 1. 프로퍼티 접근 - Setter Projections.Bean() List result = queryFactory .select(Projections.bean(MemberDto.class, member.us..

JAVA/Querydsl

Querydsl, Gradle에 추가해서 빌드하기 & 검색 조건

[본 포스팅은 실전! Querydsl 편을 기반으로 작성하였습니다.] 실전! Querydsl - 인프런 | 강의 Querydsl의 기초부터 실무 활용까지, 한번에 해결해보세요!, - 강의 소개 | 인프런... www.inflearn.com 강의를 보고 따라 해보니 다음과 같은 오류가 났다. Unable to load class 'com.mysema.codegen.model.Type'. This is an unexpected error. Please file a bug containing the idea.log file. 그 이유는 gradle의 버전이 올라가면서 맞지 않았던 모양이다. 따라서 아래와 같이 수정해주면 된다. gradle buildscript { ext { queryDslVersion = "..

혁키
혁키의 개발일지