- 방문자수
- Best Article
전체 방문자
오늘 방문자
어제 방문자
Latest Article
-
Github Action 알아보기
기본 flow작동 단계 github pushevent triggerjob 순서대로 작업 수행 이벤트 트리거repository에서 일어나는 push, fort 등의 작업github project, issue에서 일어나는 작업사용자가 직접 트리거 코드 작성 .github.workflows 폴더 하위에 github action으로 실행하고자 하는 일들을 파일별로 정의하면 별도의 설정 과정 없이 project의 actions 탭들을 통해 실행할 수 있습니다. actions 탭에서는 워크플로우 실행 결과를 확인할 수 있습니다. workflowworkflow란 이벤트 발생 시, 어떠한 행위를 할 것인가에 대한 작업 정의합니다. runner : job별 별도의 공간에서 실행하는 작업 공간에 대한 정의로 작업 간 내용..
-
Coroutine 환경에서 Spring AOP 사용하기 (with. tx와 같이 사용시 버그)
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다. Coroutine 환경에서 Spring AOP 사용하기 MVC 환경에서 AOP를 적용할 때는 위와 같이 적용하게 됩니다. 일반적으로 AOP에서 advice를 정의할 때, 타겟 메서드 전후로 특정 서비스의 메서드를 호출하는 경우가 있을 수 있습니다. 여기서 Coroutine을 사용한다면 타겟 메서드 호출 전후로 suspend 함수를 호출해야 하는 경우가 발생합니다. advice에서 suspend 함수를 호출하게 되면 위와 같이 suspend 함수를 호출하기 위해서는 현재 함수가 suspend 함수이거나 coroutine 환경 이어야 된다는 메시지가 표기됩니다. 그렇다면 에러 메시지에서 제시한 해결책 중에 간단해보이는 해결책..
-
Oauth2 Authorization 서버 구축하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다. 개요 Open Authorization 2.0은 인가를 위한 개방형 표준 프로토콜입니다. 이 프로토콜에서는 third-party 애플리케이션이 사용자의 리소스에 접근하기 위한 절차를 정의하고 서비스 제공자의 API를 사용할 수 있는 권한을 부여합니다. 대표적으로 네이버 로그인, 구글 로그인과 같은 소셜 미디어 간편 로그인이 있습니다. OAuth2.0을 사용해 third-party 애플리케이션이 사용자의 소셜미디어 프로필 정보에 접근할 수 있도록 합니다. 즉, OAuth 2.0는 사용자가 애플리케이션(클라이언트)에게 자신을 대신하여 자원 서버(Resource Server)에서 특정 자원에 접근할 수 있는 권한을 부여하는 것을 목..
-
멀티 프로젝트 헥사고날 아키텍처로 구축하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다. Hexagonal 아키텍처헥사고날 아키텍처(Hexagonal Architecture)는 포트와 어댑터 아키텍처(Ports and Adapters Architecture)라고도 불리는 소프트웨어 아키텍처 중 하나로 주요 목표는 응용 프로그램의 비즈니스 로직을 외부 세계로부터 격리시켜 유연하고 테스트하기 쉬운 구조를 만드는 것입니다. 이를 위해 핵심 비즈니스 로직은 중앙의 도메인 영역에 위치하며, 입력과 출력을 처리하는 포트와 어댑터를 통해 외부와 소통합니다. Adapter : 모든 외부 시스템과의 직접적인 상호작용을 담당ex) Controller, Kafka Listener, DB DAOInbound & Outbound port..
-
Spring Data MongoDB
공부한 내용을 정히라는 블로그와 관련 코드를 공유하는 Github이 있습니다. MongoDB란 MongoDB는 오픈소스 비관계형 데이터베이스 관리 시스템(DMBS)으로, 테이블과 행 대신 유연한 문서를 활용해 다양한 데이터 형식을 처리하고 저장합니다. NoSQL 데이터베이스 솔루션인 MongoDB는 관계형 데이터베이스 관리 시스템(RDBMS)을 필요로 하지 않으므로, 사용자가 다변량 데이터 유형을 손쉽게 저장하고 쿼리할 수 있는 탄력적인 데이터 저장 모델을 제공합니다. MongoDB 문서 또는 문서 컬렉션은 데이터의 기본 단위입니다. 해당 문서들은 이진 JSON(JavaScript 객체 표기법) 형식으로 지정되어 다양한 유형의 데이터를 저장할뿐 아니라, 여러 시스템 전반에 분산 처리될 수 있습니다. Mo..
-
Reactive 환경에서 Redisson 분산락 적용하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github가 있습니다. 분산 서버 동시성 제어 ApiGateway로 인해 여러 서버로 분산된 요청들이 DB의 같은 자원에 접근해서 수정하게 되는 경우, 최종적으로 커밋된 데이터의 형태로 자원이 저장되게 됩니다. 예를 들어, A 요청이 먼저 들어와서 1이라는 자원을 수정하고 있는데, B요청이 들어와서 A보다 먼저 자원을 수정하고 커밋하고 이후에 A가 커밋하게 된다면 최종적으로는 A에서 커밋한 데이터가 반영되게 되면서 정합성이 깨지게 됩니다. 분삭락을 사용하게 되는 경우, 가장 먼저 들어온 요청이 락을 획득하여 작업을 처리하기 때문에 이후 들어온 요청은 락을 획득하기까지 기다리고 이전 작업이 락을 해제해야만 다음 요청이 락을 획득하여 작업을 처리할 수..
-
Spring - GraphQL 서버 구축하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.GraphQL 이란? Graph QL(이하 gql)은 Structed Query Language(이하 sql)와 마찬가지로 쿼리 언어입니다. 하지만 gql과 sql의 언어적 구조 차이는 매우 큽니다. 또한 gql과 sql이 실전에서 쓰이는 방식의 차이도 매우 큽니다. gql과 sql의 언어적 구조 차이가 활용 측면에서의 차이를 가져왔습니다. 이 둘은 애초에 탄생 시기도 다르고 배경도 다릅니다. sql은 데이터베이스 시스템에 저장된 데이터를 효율적으로 가져오는 것이 목적이고, gql은 웹 클라이언트가 데이터를 서버로부터 효율적으로 가져오는 것이 목적입니다. sql의 문장(statement)은 주로 백앤드 시스템에서 작성하고 호출하..
-
Spring R2DBC 다양한 쿼리 사용 방법 (feat. kotlin)
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.R2DBC란? R2DBC(Reactive Rela tional Database Connectivity)는 드라이버 공급업체가 관계형 데이터베이스에 액세스 하기 위해서 구현한 리액티브 API를 선언하는 API 명세입니다. R2DBC가 만들어진 이유 중 하나는 적은 스레드로 동시성을 처리하기 위해, 더 적은 하드웨어 리소스로 확장할 수 있는 논-블로킹 애플리케이션 스택이 필요해서 입니다. JDBC는 완전한 블로킹 API 이기 때문에, 표준화된 관계형 데이타베이스 액세스 API(즉, JDBC)를 재이용하더라도 이 요구를 충족할 수가 없습니다. ThreadPool를 사용하여 블로킹 동작을 비슷하게 구현할 수도 있지만 이는 제약 사항이 ..
-
Armeria - zipkin 적용하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.MSA 환경과 OpenTracing이란 모놀리식(monolithic)과 MSA(Micro Service Architecture)에 대해서 간단하게 설명하겠습니다. 모놀리식의 경우 하나의 서버가 서비스의 전반적인 기능을 모두 제공합니다. 그로 인해 복잡도가 증가하고 역할을 나누기 어려운 등 많은 문제가 발생하지만, 클라이언트의 요청을 받으면 하나의 스레드에서 모든 요청을 실행하므로 로그를 확인하기 쉽다는 장점이 있습니다. 그에 반해 MSA의 경우에는 각 서비스의 복잡도가 낮아지고 역할 분담이 용이하지만 클라이언트의 요청을 받았을 때 여러 개의 마이크로 서비스 간에 통신이 발생해 로그를 확인하기 어려운 문제가 있습니다. 이런 문제를..
-
Armeria gRPC 서버에 mTLS 적용하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.mTLS mTLS는 TLS의 확장된 형태로, TLS는 서버의 신원만을 인증하는 반면 mTLS는 서버뿐만 아니라 클라이언트도 자신의 신원을 인증서를 통해 증명해야 하는 상호 인증 방식입니다. 이는 양방향 인증이라고도 하며, 서로의 인증서를 검증함으로써 보다 강화된 보안을 제공합니다. TLS 통신 과정클라이언트가 서버에 연결서버가 TLS 인증서를 제시클라이언트가 서버의 인증서를 확인클라이언트와 서버가 암호화된 TLS 연결을 통해 정보를 교환 mTLS 통신 과정 일반적으로 TLS에서 서버에는 TLS 인증서와 공개/개인 키 쌍이 있지만 클라이언트에는 없습니다. 그러나 mTLS에서는 클라이언트와 서버 모두에 인증서가 있고 양측 모두 공개..
-
Armeria를 활용한 gRPC-kotlin 서버 구축하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.RPC (Remote Procedure Call)와 REST RPC RPC는 네트워크로 연결된 서버 상의 프로시저(함수, 메서드 등)를 원격으로 호출할 수 있는 기능입니다. 코드 상으로는 마치 로컬 함수의 호출과 같지만 실제로는 함수가 원격 서버에서 실행됩니다. 네트워크 통신을 위한 작업 하나하나 챙기기 귀찮으니 통신이나 call 방식에 신경 쓰지 않고 원격지의 자원을 내 것처럼 사용할 수 있다는 의미입니다. IDL(Interface Definication Language) 기반으로 다양한 언어를 가진 환경에서도 쉽게 확장이 가능하며, 인터페이스 협업에도 용이하다는 장점이 있습니다. 지원 언어 : C++, Java, Python..
-
Spring - CircuitBreaker
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다. CircuitBreaker란?CircuitBreaker는 문제가 발생한 지점을 감지하고 실패하는 요청을 계속하지 않도록 방지하며, 이를 통해 시스템의 장애 확산을 막고 장애 복구를 도와주는 기능을 제공합니다. 위 그림과 같이 A가 B를 호출할 때, B가 반복적으로 실패한다면 CircuitBreaker를 Open 하여 B에 대한 흐름을 차단하는 기능을 제공합니다. CircuitBreaker를 지원하는 라이브러리Netflix Hystrix (deprecated)Netflix 에서 개발한 라이브러리로 MSA 환경에서 서비스 간 통신이 원활하지 않을 경우 각 서비스가 장애 내성과 지연 내성을 갖게 하는 라이브러리Resilience4j..
-
Elasticsearch - 샤드, 인덱스 운영 전략
샤드 운영 전략 샤드는 다음과 같은 옵션으로 개수를 설정할 수 있습니다. number_of_shard : 프라이머리 샤드 개수 number_of_replicas : 레플리카 개수 만약 인덱스에 위 옵션을 3, 2로 지정했다면 해당 인덱스는 프라이머리 샤드 3개에 대한 복제본이 2개씩 생기므로 프라이머리 3개, 레플리카 6개로 총 9개의 샤드가 생성됩니다. number_of_shard는 인덱스가 데이터를 몇 개의 샤드로 쪼갤 것인지를 지정하는 값이므로 신중하게 설계해야 합니다. 한 번 지정하면 reindex 같은 동작을 통해 인덱스를 통째로 재색인하는 등 특별한 작업을 수행하지 않는 한 바꿀 수 없기 때문입니다. 샤드 개수를 어떻게 지정하느냐는 엘라스틱서치 성능에도 영향을 미칩니다. 클러스터에 샤드 숫자가..
-
Elasticsearch - 집계 API
집계 엘라스틱서치의 집계는 검색의 연장선입니다. 집계의 대상을 추려낼 검색 조건을 검색 API에 담은 뒤 집계 조건을 추가해서 호출합니다. GET kibana_sample_data_ecommerce/_search { "size": 0, "query": { "term": { "currency": { "value": "EUR" } } }, "aggs": { "my-agg": { "sum": { "field": "taxless_total_price" } } } } 검색 요청 본문에 aggs를 추가하고 size는 0으로 지정했습니다. size를 0으로 지정하면 검색에 상위 매칭된 문서가 무엇인지 받아볼 수 없지만 검색 조건에 매치되는 모든 문서는 집계 작업 대상에 사용됩니다. 집계 작업은 검색 대상을 받아보는 ..
-
Elasticsearch - 검색 API
단건 문서 API 색인 PUT [인덱스 이름]/_doc/[_id값] // 가장 기본 POST [인덱스 이름]/_doc PUT [인덱스 이름]/_create/[_id값] POST [인덱스 이름]/_create/[_id값] PUT의 경우 요청 본문에 담아 보낸 JSOPN 문서를 지정된 인덱스와 _id값으로 색인을 시도합니다. 만약 같은 _id값을 가진 문서가 있다면 덮어씌웁니다. 반면에 POST 메서드는 _id값을 지정하지 않고 색인을 요청할 경우에 사용합니다. 이 경우에는 랜덤한 _id값이 지정됩니다. _create이 경로에 들어가는 API는 항상 새로운 문서 생성만을 허용하고 덮어씌우면서 색인하는 것은 금지합니다. 조회 GET [인덱스 이름]/_doc/[_id값] 조회 API는 문서 단건을 조회합니다. ..
-
Elasticsearch - 기본 콘셉트와 구조도
ElasticSearch 기본 콘셉트 루씬은 데이터를 색인하고 검색하는 기능을 제공하는 검색 엔진의 코어 라이브러리입니다. 엘라스틱서치는 루씬을 코어로 이용하여 JSON 문서의 저장, 색인, 검색 등의 작업을 분산 처리하는 검색 엔진입니다. 검색 엔진 단순한 텍스트 매칭 검색이 아닌 전문 검색이 가능하며 다양한 종류의 검색 쿼리를 지원합니다. 검색 엔진이기 때문에 역색인을 사용하여 검색 속도도 매우 빠르며, 다양한 애널라이저를 조합하여 요구사항에 맞는 색인을 구성할 수 있고 형태소 분석도 가능합니다. 분산 처리 데이터를 여러 노드에 분산 저장하여 검색이나 집계 작업 등을 수행할 때도 분산 처리를 지원합니다. 고가용성 제공 클러스터를 구성하고 있는 일부 노드에 장애가 발생해도 복제본 데이터를 이용해 중단 ..
Spring
-
Coroutine 환경에서 Spring AOP 사용하기 (with. tx와 같이 사용시 버그)
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다. Coroutine 환경에서 Spring AOP 사용하기 MVC 환경에서 AOP를 적용할 때는 위와 같이 적용하게 됩니다. 일반적으로 AOP에서 advice를 정의할 때, 타겟 메서드 전후로 특정 서비스의 메서드를 호출하는 경우가 있을 수 있습니다. 여기서 Coroutine을 사용한다면 타겟 메서드 호출 전후로 suspend 함수를 호출해야 하는 경우가 발생합니다. advice에서 suspend 함수를 호출하게 되면 위와 같이 suspend 함수를 호출하기 위해서는 현재 함수가 suspend 함수이거나 coroutine 환경 이어야 된다는 메시지가 표기됩니다. 그렇다면 에러 메시지에서 제시한 해결책 중에 간단해보이는 해결책..
-
Oauth2 Authorization 서버 구축하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다. 개요 Open Authorization 2.0은 인가를 위한 개방형 표준 프로토콜입니다. 이 프로토콜에서는 third-party 애플리케이션이 사용자의 리소스에 접근하기 위한 절차를 정의하고 서비스 제공자의 API를 사용할 수 있는 권한을 부여합니다. 대표적으로 네이버 로그인, 구글 로그인과 같은 소셜 미디어 간편 로그인이 있습니다. OAuth2.0을 사용해 third-party 애플리케이션이 사용자의 소셜미디어 프로필 정보에 접근할 수 있도록 합니다. 즉, OAuth 2.0는 사용자가 애플리케이션(클라이언트)에게 자신을 대신하여 자원 서버(Resource Server)에서 특정 자원에 접근할 수 있는 권한을 부여하는 것을 목..
-
Spring - GraphQL 서버 구축하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.GraphQL 이란? Graph QL(이하 gql)은 Structed Query Language(이하 sql)와 마찬가지로 쿼리 언어입니다. 하지만 gql과 sql의 언어적 구조 차이는 매우 큽니다. 또한 gql과 sql이 실전에서 쓰이는 방식의 차이도 매우 큽니다. gql과 sql의 언어적 구조 차이가 활용 측면에서의 차이를 가져왔습니다. 이 둘은 애초에 탄생 시기도 다르고 배경도 다릅니다. sql은 데이터베이스 시스템에 저장된 데이터를 효율적으로 가져오는 것이 목적이고, gql은 웹 클라이언트가 데이터를 서버로부터 효율적으로 가져오는 것이 목적입니다. sql의 문장(statement)은 주로 백앤드 시스템에서 작성하고 호출하..
-
Spring - CircuitBreaker
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다. CircuitBreaker란?CircuitBreaker는 문제가 발생한 지점을 감지하고 실패하는 요청을 계속하지 않도록 방지하며, 이를 통해 시스템의 장애 확산을 막고 장애 복구를 도와주는 기능을 제공합니다. 위 그림과 같이 A가 B를 호출할 때, B가 반복적으로 실패한다면 CircuitBreaker를 Open 하여 B에 대한 흐름을 차단하는 기능을 제공합니다. CircuitBreaker를 지원하는 라이브러리Netflix Hystrix (deprecated)Netflix 에서 개발한 라이브러리로 MSA 환경에서 서비스 간 통신이 원활하지 않을 경우 각 서비스가 장애 내성과 지연 내성을 갖게 하는 라이브러리Resilience4j..
-
Spring - OpenFeign
본 포스팅은 spring boot 3.2.2 버전을 기준으로 작성되었습니다.공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다. open feign이란? feign은 Netflix에서 개발된 Http client binder로 REST Call을 위해 호출하는 클라이언트를 보다 쉽게 작성할 수 있도록 도와주는 라이브러리입니다. spring의 경우 spring-cloud-starter-openfeign 라이브러리 추가로 사용할 수 있습니다. spring cloud는 spring mvc annotation에 대한 지원과 sprinb web에서 사용되는 것과 동일한 HttpMessageConverters를 지원합니다. 의존성 및 client build.gradle.ktsdependen..
-
Spring Batch - 병럴 처리
단일 스레드 vs 멀티 스레드 프로세스 내 특정 작업을 처리하는 스레드가 하나일 경우 단일 스레드, 여러 개일 경우 멀티 스레드라고 합니다. 작업 처리에 있어서 단일 스레드와 멀티 스레드의 선택 기준은 어떤 방식이 자원을 효율적으로 사용하고 성능 처리에 유리한가 하는 점입니다. 일반적으로 복잡한 처리나 대용량 데이터를 다루는 작업일 경우 전체 소요 시간 및 성능상의 이점을 가져오기 위해 멀티 스레드 방식을 사용합니다. 하지만 멀티 스레드 처리 방식은 데이터 동기화 이슈가 존재하기 때문에 주의해야 합니다. 스프링 배치 스레드 모델 스프링 배치에서 멀티스레드 환경을 구성하기 위해서 가장 먼저 해야 할 일은 사용하고자 하는 Reader와 Writer가 멀티스레드를 지원하는지 확인하는 것입니다. 스프링 배치 모..
-
Spring Batch - Scope
@JobScope와 @StepScope Scope는 스프링 컨테이너에서 빈이 관리되는 범위를 의미합니다. JobScope와 StepScope는 Job과 Step의 빈 생성과 실행에 관여하는 스코프입니다. 프록시 모드를 기본값으로 하기 때문에 애플리케이션 구동 시점에는 프록시 빈이 생성되고 실행 시점에 실제 빈 생성이 이뤄집니다. 이를 통해 빈의 실행 시점에 값을 참조할 수 있는 일종의 Lazy Binding이 가능해집니다. 스코프를 사용하게 되면 @Value를 사용하여 아래와 같이 인자로 주입받을 수 있게 됩니다. @Value("#{jobParameters[파라미터명]}") @Value("#{jobExecutionContext[파라미터명]}") @Value("#{stepExecutionContext[파라..
-
Spring Batch - 리스너
Listener 배치 흐름 중에 Job, Step, Chunk 단계의 실행 전후에 발생하는 이벤트를 받아 용도에 맞게 활용할 수 있도록 제공하는 인터셉터 개념의 클래스입니다. 각 단계별로 로그기록을 남기거나 소요된 시간을 계산하거나 실행상태 정보들을 참조 및 조회할 수 있습니다. Job JobExecutionListener : Job 실행 전후 Step StepExecutionListener : Step 실행 전후 ChunkListener : Chunk 실행 전후(Tasklet 실행 전후), 오류 시점 ItemReaderListener : ItemReader 실행 전후, 오류 시점, 단, item이 null일 경우에는 호출 X ItemProcessorListener : ItemProcessor 실행 전후..
-
Spring Batch - 반복 및 오류 제어
Repeat 스프링 배치는 특정 조건이 충족될 때까지 Job 또는 Step을 반복하도록 배치 애플리케이션을 구성할 수 있습니다. 스프링 배치에서는 Step과 Chunk의 반복을 RepeatOperation을 사용해 처리하고 있습니다. 기본 구현체로 RepeatTemplate을 제공합니다. 구조 Step은 RepeatTemplate을 사용해 Tasklet을 반복적으로 실행합니다. ChunkOrientedTasklet은 내부적으로 ChunkProvider를 통해 ItemReader로 데이터를 읽어올 것을 지시합니다. ChunkProvider는 내부적으로 RepeatTemplate을 갖고 있고 이를 이용해 반복적으로 ItemReader에게 반복적으로 데이터를 읽어오도록 처리합니다. FaultTolerant 스..
-
Spring Batch - ItemProcessor
ItemProcessor 데이터를 출력하기 전에 데이터를 가공 및 필터링 역할을 하는 인터페이스입니다. ItemReader 및 ItemWriter와 분리되어 비즈니스 로직을 구현할 수 있습니다. ItemReader로부터 받은 아이템을 특정 타입으로 변환해서 ItemWriter에 넘겨줄 수 있습니다. Itemreader로부터 받은 아이템들 중 필터과정을 거쳐서 원하는 아이템들만 ItemWriter로 넘겨줄 수 있습니다. ChunkOrientedTasklet 실행 시 선택적 요소기 때문에 필수 요소는 아닙니다. O process() I 제네릭은 ItemReader에서 받을 데이터 타입 O 제네릭은 ItemWriter에게 보낼 데이터 타입 아이템을 하나씩 가공 처리하며 null을 리턴할 경우 해당 아이템은 C..
-
Spring Batch - ItemWriter
ItemWriter Chunk 단위로 데이터를 받아 일괄 출력 작업을 위한 인터페이스입니다. 플랫 파일 - csv, txt XML, Jsono Database Message Queuing 서비스 Mail Service Custom reader 다수의 구현체들이 itemReader와 같은 맥락으로 itemWriter와 ItemStream을 동시에 구현하고 있습니다. 하나의 아이템이 아닌 아이템 리스트를 전달받아 수행합니다. ChunkOrientedTasklet 실행 시 필수적 요소로 설정해야 합니다. void write() 출력 데이터를 아이템 리스트로 받아서 처리합니다. 출력이 완료되고 트랜잭션이 종료되면 새로운 Chunk 단위 프로세스로 이동합니다. 위와 같이 다양한 구현체들을 제공하고 있습니다. Jd..
-
Spring Batch - ItemReader
ItemReader itemReader는 다양한 입력으로부터 데이터를 읽어서 제공하는 인터페이스입니다. 플랫 파일 - csv, txt XML, Json Database Message Queuing 서비스 Custom reader 다수의 구현체들이 ItemReader와 ItemStream 인터페이스를 동시에 구현하고 있습니다. ItemStream은 파일 스트림 연결 종료, DB 커넥션 연결 종료 등의 장치 초기화 등의 작업에 사용됩니다. ExecutionContext에 read와 관련된 여러 가지 상태 정보를 저장해 두고 재시작 시 참조됩니다. ChunkOrientedTasklet 실행 시 필수적 요소로 설정해야 합니다. T read() 입력 데이터를 읽고 다음 데이터로 이동합니다. 아이템 하나를 리턴하며..
-
Spring Batch - 청크 기반 프로세스
Chunk 여러 개의 아이템을 묶은 하나의 덩어리를 의미합니다. 한 번에 하나씩 아이템을 입력받아 Chunk 단위의 덩어리로 만든 후 Chunk 단위로 트랜잭션을 처리합니다. Chunk 단위로 Commit과 Rollback Chunk Chunk, Chunk Chunk ItemReader로 읽은 하나의 아이템을 Chunk 크기만큼 반복해서 저장하는 타입 Chunk ItemReader로부터 전달받은 Chunk 를 참조해서 ItemProcessor에서 적절하게 가공한 뒤 ItemWriter로 전달되는 타입 여기서 O는 Processor가 없다면 ItemReader로부터 전달받는 타입, Processor가 있다면 Processor로부터 전달받는 타입입니다. 아키텍처 ItemReader가 Source를 한 건씩 ..
-
Spring Batch - DB 스키마와 도메인
배치 애플리케이션이란? 배치(Batch)는 일괄처리란 뜻을 갖고 있습니다. 쇼핑몰에서 매일 전날의 매출 데이터를 집계해야 한다고 가정해 보겠습니다. 매출 데이터가 대용량이라면 하루 매출 데이터를 읽고, 가공하고, 저장한다면 해당 서버는 순식간에 CPU, I/O 등의 자원을 다 써버려서 다른 작업을 할 수 없게 됩니다. 집계 기능은 하루에 1번만 수행된다면 이를 위해 API를 구성하는 것은 낭비가 될 수 있고, 데이터 처리 중에 실패했다면 처음부터가 아니라 실패시점부터 다시 처리하고 싶을 수 있습니다. 이런 단발성으로 대용량의 데이터를 처리하는 애플리케이션을 배치 애플리케이션 이라고 합니다. 배치 애플리케이션은 다음 조건을 만족해야 합니다. 대용량 데이터 - 배치 애플리케이션은 대량의 데이터를 가져오거나,..
-
Spring - hikariCP 옵션 정리 및 권장 설정
datasource spring boot 2.x.x 기준에서 사용 가능한 connection pool은 3가지가 있습니다. hikariCP tomcat pooling datasource common dbcp2 spring boot 1.x.x에서는 tomcat이 default였으나 2.0.0부터 hikaricp가 default가 되었습니다. 그래서 spring-boot-starter-jdbc, spring-boot-starter-data-jpa를 사용하면, HikariCP(가장 높음) -> Tomcat pooling -> Commons DBCP2의 순위로 지정됩니다. 위의 우선순위를 무시하고 spring.datasource.type에 값을 통해 설정할 수도 있습니다. spring.datasource.typ..
-
Spring - restTemplate 대용량 파일 업로드, 다운로드 설정
본 포스팅은 kotlin과 java 코드가 혼재되어 있으며 spring boot 3.x 버전에서 사용된 코드입니다. RestTemplate이란? Spring MVC에서는 외부 요청을 위해 RestTemplate을 사용합니다. spring boot 3.x 설정 RestTemplate은 커넥션 풀을 지원하지 않아 구성 요소인 HttpClient를 통해서 커넥션과 관련된 추가 세팅을 진행합니다. 아래 RestTemplateGenerator 클래스는 restTemplate을 만들어내서 반환해 주는 object 클래스로 spring boot 3.x 버전부터 사용하는 RestTemplate 설정입니다. object RestTemplateGenerator { // https://www.baeldung.com/http..
Database
-
Spring Data MongoDB
공부한 내용을 정히라는 블로그와 관련 코드를 공유하는 Github이 있습니다. MongoDB란 MongoDB는 오픈소스 비관계형 데이터베이스 관리 시스템(DMBS)으로, 테이블과 행 대신 유연한 문서를 활용해 다양한 데이터 형식을 처리하고 저장합니다. NoSQL 데이터베이스 솔루션인 MongoDB는 관계형 데이터베이스 관리 시스템(RDBMS)을 필요로 하지 않으므로, 사용자가 다변량 데이터 유형을 손쉽게 저장하고 쿼리할 수 있는 탄력적인 데이터 저장 모델을 제공합니다. MongoDB 문서 또는 문서 컬렉션은 데이터의 기본 단위입니다. 해당 문서들은 이진 JSON(JavaScript 객체 표기법) 형식으로 지정되어 다양한 유형의 데이터를 저장할뿐 아니라, 여러 시스템 전반에 분산 처리될 수 있습니다. Mo..
-
Reactive 환경에서 Redisson 분산락 적용하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github가 있습니다. 분산 서버 동시성 제어 ApiGateway로 인해 여러 서버로 분산된 요청들이 DB의 같은 자원에 접근해서 수정하게 되는 경우, 최종적으로 커밋된 데이터의 형태로 자원이 저장되게 됩니다. 예를 들어, A 요청이 먼저 들어와서 1이라는 자원을 수정하고 있는데, B요청이 들어와서 A보다 먼저 자원을 수정하고 커밋하고 이후에 A가 커밋하게 된다면 최종적으로는 A에서 커밋한 데이터가 반영되게 되면서 정합성이 깨지게 됩니다. 분삭락을 사용하게 되는 경우, 가장 먼저 들어온 요청이 락을 획득하여 작업을 처리하기 때문에 이후 들어온 요청은 락을 획득하기까지 기다리고 이전 작업이 락을 해제해야만 다음 요청이 락을 획득하여 작업을 처리할 수..
-
Spring R2DBC 다양한 쿼리 사용 방법 (feat. kotlin)
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.R2DBC란? R2DBC(Reactive Rela tional Database Connectivity)는 드라이버 공급업체가 관계형 데이터베이스에 액세스 하기 위해서 구현한 리액티브 API를 선언하는 API 명세입니다. R2DBC가 만들어진 이유 중 하나는 적은 스레드로 동시성을 처리하기 위해, 더 적은 하드웨어 리소스로 확장할 수 있는 논-블로킹 애플리케이션 스택이 필요해서 입니다. JDBC는 완전한 블로킹 API 이기 때문에, 표준화된 관계형 데이타베이스 액세스 API(즉, JDBC)를 재이용하더라도 이 요구를 충족할 수가 없습니다. ThreadPool를 사용하여 블로킹 동작을 비슷하게 구현할 수도 있지만 이는 제약 사항이 ..
-
Elasticsearch - 샤드, 인덱스 운영 전략
샤드 운영 전략 샤드는 다음과 같은 옵션으로 개수를 설정할 수 있습니다. number_of_shard : 프라이머리 샤드 개수 number_of_replicas : 레플리카 개수 만약 인덱스에 위 옵션을 3, 2로 지정했다면 해당 인덱스는 프라이머리 샤드 3개에 대한 복제본이 2개씩 생기므로 프라이머리 3개, 레플리카 6개로 총 9개의 샤드가 생성됩니다. number_of_shard는 인덱스가 데이터를 몇 개의 샤드로 쪼갤 것인지를 지정하는 값이므로 신중하게 설계해야 합니다. 한 번 지정하면 reindex 같은 동작을 통해 인덱스를 통째로 재색인하는 등 특별한 작업을 수행하지 않는 한 바꿀 수 없기 때문입니다. 샤드 개수를 어떻게 지정하느냐는 엘라스틱서치 성능에도 영향을 미칩니다. 클러스터에 샤드 숫자가..
-
Elasticsearch - 집계 API
집계 엘라스틱서치의 집계는 검색의 연장선입니다. 집계의 대상을 추려낼 검색 조건을 검색 API에 담은 뒤 집계 조건을 추가해서 호출합니다. GET kibana_sample_data_ecommerce/_search { "size": 0, "query": { "term": { "currency": { "value": "EUR" } } }, "aggs": { "my-agg": { "sum": { "field": "taxless_total_price" } } } } 검색 요청 본문에 aggs를 추가하고 size는 0으로 지정했습니다. size를 0으로 지정하면 검색에 상위 매칭된 문서가 무엇인지 받아볼 수 없지만 검색 조건에 매치되는 모든 문서는 집계 작업 대상에 사용됩니다. 집계 작업은 검색 대상을 받아보는 ..
-
Elasticsearch - 검색 API
단건 문서 API 색인 PUT [인덱스 이름]/_doc/[_id값] // 가장 기본 POST [인덱스 이름]/_doc PUT [인덱스 이름]/_create/[_id값] POST [인덱스 이름]/_create/[_id값] PUT의 경우 요청 본문에 담아 보낸 JSOPN 문서를 지정된 인덱스와 _id값으로 색인을 시도합니다. 만약 같은 _id값을 가진 문서가 있다면 덮어씌웁니다. 반면에 POST 메서드는 _id값을 지정하지 않고 색인을 요청할 경우에 사용합니다. 이 경우에는 랜덤한 _id값이 지정됩니다. _create이 경로에 들어가는 API는 항상 새로운 문서 생성만을 허용하고 덮어씌우면서 색인하는 것은 금지합니다. 조회 GET [인덱스 이름]/_doc/[_id값] 조회 API는 문서 단건을 조회합니다. ..
-
Elasticsearch - 기본 콘셉트와 구조도
ElasticSearch 기본 콘셉트 루씬은 데이터를 색인하고 검색하는 기능을 제공하는 검색 엔진의 코어 라이브러리입니다. 엘라스틱서치는 루씬을 코어로 이용하여 JSON 문서의 저장, 색인, 검색 등의 작업을 분산 처리하는 검색 엔진입니다. 검색 엔진 단순한 텍스트 매칭 검색이 아닌 전문 검색이 가능하며 다양한 종류의 검색 쿼리를 지원합니다. 검색 엔진이기 때문에 역색인을 사용하여 검색 속도도 매우 빠르며, 다양한 애널라이저를 조합하여 요구사항에 맞는 색인을 구성할 수 있고 형태소 분석도 가능합니다. 분산 처리 데이터를 여러 노드에 분산 저장하여 검색이나 집계 작업 등을 수행할 때도 분산 처리를 지원합니다. 고가용성 제공 클러스터를 구성하고 있는 일부 노드에 장애가 발생해도 복제본 데이터를 이용해 중단 ..
-
MySQL 8.0 쿼리와 인덱스 처리 방식
order by 처리(using filesort) 정렬을 처리하는 방법은 인덱스를 이용하는 방법과 쿼리가 실행될 때 Filesort라는 별도의 처리를 이용하는 방법으로 나눌 수 있다. 인덱스 이용 장점 insert, update, delete 쿼리가 실행될 때 이미 인덱스가 정렬돼 있어서 순서대로 읽기만 하면 되므로 매우 빠름 단점 insert, update, delete 작업 시 부가적인 인덱스 추가/삭제 작업이 필요하므로 느리다. 인덱스 때문에 추가 디스크 공간이 필요하고 늘어날수록 innoDB의 버퍼 풀을 위한 메모리가 많이 필요하다. filesort 이용 장점 인덱스를 생성하지 않아도 되므로 인덱스를 이용할 때의 단점이 장점으로 바뀐다. 정렬해야 할 레코드가 많지 않으면 메모리에서 filesort..
-
MySQL 실행계획 보는 방법
쿼리튜닝을 위한 인덱스 특징(innoDB, B-Tree) 인덱스는 정렬되어 있다. 왼쪽 컬럼인 column_1 순으로 먼저 정렬되고, column_1이 같다면 column_2 순으로 정렬된다. 따라서 인덱스를 기준으로 조회한 데이터는 인덱스 컬럼 순으로 정렬되어 있다. 인덱스는 스캔하는 방식으로 처리된다. 중간중간 데이터를 읽는 것이 아니라, 시작지점을 잡고 종료지점까지 쭉 스캔한다. 인덱스는 메모리 위에 존재한다. column_1 = 'A'인 레코드 중에 column_3 이 필요하다면? 실제 column_1 = 'A'인 레코드를 모두 가져온 다음 물리 주소를 파악해서 물리 주소를 기반으로 디스크에서 값을 가져온다. 모든 컬럼 값을 인덱스에 올려놓을 수는 없기 때문에 성능적으로 타협하면서 세팅해야 한다...
-
JPA - AttributeConverter
AttributeConverter AttributeConverter는 주로 다음과 같은 상황에서 사용됩니다. JPA가 지원하지 않는 타입을 매핑 두 개 이상의 속성을 갖는 밸류 타입을 한 개 칼럼에 매핑 JPA가 지원하지 않는 타입을 매핑 public interface AttributeConverter { public Y convertToDatabaseColumn (X attribute); public X convertToEntityAttribute (Y dbData); } X : 엔티티의 속성에 대응하는 타입 Y : DB에 대응하는 타입 convertToDatabaseColumn 엔티티의 X 타입 속성을 Y 타입의 DB 데이터로 변환합니다. 엔티티 속성을 DB에 반영할 때 사용됩니다. convertTo..
-
MySQL 인덱스
Index란? 인덱스란 (검색을 위해) 지정한 컬럼들을 기준으로 메모리 영역에 일종의 목차를 생성하는 것 입니다. 인덱스를 사용하게 되면 데이터 추가, 수정, 삭제의 성능을 희생하고 대신 조회의 성능을 향상 시킵니다. 여기서 주의할 것은 update, delete 행위가 느린것이지 update, delete를 하기 위해 해당 데이터를 조회하는 것은 인덱스가 있으면 빠르게 조회 됩니다. Clustered Index vs Non-Clustered Index 인덱스 종류에는 clustered와 Non-Clustered 두 가지가 있습니다. MySQL의 InnoDB엔진에서는 인덱스가 B-Tree(균형 트리) 자료구조로 구성되어 있습니다. Cluster Index(클러스터형 인덱스) 한 테이블당 1개 (Prima..
-
MySQL 아키텍처
MySQL 아키턱처 MySQL 접속 클라이언트 대부분의 프로그래밍 언어에 대한 접속 API 제공 쉘 스크립트를 통해 접속 가능 MySQL 엔진 클라이언트 접속과 SQL 요청 처리 담당 쿼리 파서, 전처리기, 옵티마이저(요청된 SQL문을 최적화해서 실행하기 위한 실행계획을 짜는 역할), 실행 엔진 등으로 구성 MySQL 스토리지 엔진 데이터를 실제로 디스크에 저장하거나 읽어오는 역할 옵티마이저가 작성한 실행 계획에 따라서 적절히 실행 MySQL 엔진이 스토리 엔진을 호출할 때 사용하는 API를 핸들러 API라고 함 운영체제, 하드웨어 실제 테이블 데이터와 로그 데이터를 파일로 저장하는 부분 쿼리 실행 과정 사용자가 SQL 요청을 MySQL로 보냅니다. 가장 먼저 쿼리 캐시를 만나는데 쿼리 캐시는 쿼리 요청..
-
Spring Data JPA - QueryDSL 사용하기
설정하기 build.gradle.kts import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.springframework.boot") version "3.0.4" id("io.spring.dependency-management") version "1.1.0" kotlin("jvm") version "1.7.22" kotlin("plugin.spring") version "1.7.22" kotlin("plugin.jpa") version "1.7.22" kotlin("kapt") version "1.7.22" } group = "com.example" version = "0.0.1-SNAPSHOT" java.sourceCompat..
-
Spring Data JPA - 성능 최적화
@Transactional(readOnly = true) service layer에서 @Transactional을 대부분 사용합니다. 데이터 변경이 있는 경우 @Transactional을 붙이고 데이터 조회만 하는 경우라면 @Transactional(readOnly = true)를 명시합니다. readOnly가 true로 붙은 조회용의 경우 스냅샷이 생기지 않습니다. 즉, 영속성 컨텍스트에서 관리는 하고 있지만 dirty checking을 안하기 때문에 수정해도 DB에 결과가 반영되지 않습니다. N+1 N+1 은 엔티티를 조회할 때, 해당 엔티티에 연관관계를 갖는 다른 엔티티를 프록시로 가져오면서(LazyLoading) 실제 데이터에 접근하는 시점에 해당 엔티티를 가져오기 위해 또 다른 조회 쿼리를 보내..
-
JPA Batch Insert와 JDBC Batch Insert
Bulk Insert MySQL을 사용하면서 Batch Insert를 수행하기 위해서는 2가지 방법이 있습니다. JPA Batch Insert + Table 전략 JDBC Batch Insert IDENTITY 전략으로 Batch INSERT가 불가능한 이유 JPA + Batch Insert를 MySQL에서 사용하기 위해서는 ID 전략을 Table 전략으로 수정해야 합니다. 하지만 MySQL은 Sequence 전략이 없습니다. 일반적으로 MySQL에서 사용하는 IDENTITY 전략은 auto_increment으로 PK 값을 자동으로 증분합니다. 즉, Insert를 실행하기 전까지는 ID에 할당된 값을 알 수 없기 때문에 Transactional Write Behind를 할 수 없고 결과적으로 Batch ..
-
JPA - LOCK
애그리거트와 트랜잭션 한 주문 애그리거트에 대해 운영자는 배송 상태로 변경할 때 사용자는 배송지 주소를 변경하면 어떻게 될까요? 위 그림은 운영자와 고객이 동시에 한 주문 애그리거트를 수정하는 과정을 보여줍니다. 트랜잭션마다 리포지토리는 새로운 애그리거트 객체를 생성하므로 운영자 스레드가 고객 스레드는 같은 주문 애그리거트를 나타내는 다른 객체를 구하게 됩니다. 운영자 스레드가 고객 스레드는 개념적으로 동일한 애그리거트지만 물리적으로 서로 다른 애그리거트 객체를 사용합니다. 때문에 운영자 스레드가 주문 애그리거트 객체를 배송 상태로 변경하더라도 고객 스레드가 사용하는 주문 애그리거트 객체에는 영향을 주지 않습니다. 고객 스레드 입장에서 주문 애그리거트 객체는 아직 배송 상태 전이므로 배송지 정보를 변경할..
Armeria
-
Armeria - zipkin 적용하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.MSA 환경과 OpenTracing이란 모놀리식(monolithic)과 MSA(Micro Service Architecture)에 대해서 간단하게 설명하겠습니다. 모놀리식의 경우 하나의 서버가 서비스의 전반적인 기능을 모두 제공합니다. 그로 인해 복잡도가 증가하고 역할을 나누기 어려운 등 많은 문제가 발생하지만, 클라이언트의 요청을 받으면 하나의 스레드에서 모든 요청을 실행하므로 로그를 확인하기 쉽다는 장점이 있습니다. 그에 반해 MSA의 경우에는 각 서비스의 복잡도가 낮아지고 역할 분담이 용이하지만 클라이언트의 요청을 받았을 때 여러 개의 마이크로 서비스 간에 통신이 발생해 로그를 확인하기 어려운 문제가 있습니다. 이런 문제를..
-
Armeria gRPC 서버에 mTLS 적용하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.mTLS mTLS는 TLS의 확장된 형태로, TLS는 서버의 신원만을 인증하는 반면 mTLS는 서버뿐만 아니라 클라이언트도 자신의 신원을 인증서를 통해 증명해야 하는 상호 인증 방식입니다. 이는 양방향 인증이라고도 하며, 서로의 인증서를 검증함으로써 보다 강화된 보안을 제공합니다. TLS 통신 과정클라이언트가 서버에 연결서버가 TLS 인증서를 제시클라이언트가 서버의 인증서를 확인클라이언트와 서버가 암호화된 TLS 연결을 통해 정보를 교환 mTLS 통신 과정 일반적으로 TLS에서 서버에는 TLS 인증서와 공개/개인 키 쌍이 있지만 클라이언트에는 없습니다. 그러나 mTLS에서는 클라이언트와 서버 모두에 인증서가 있고 양측 모두 공개..
-
Armeria를 활용한 gRPC-kotlin 서버 구축하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.RPC (Remote Procedure Call)와 REST RPC RPC는 네트워크로 연결된 서버 상의 프로시저(함수, 메서드 등)를 원격으로 호출할 수 있는 기능입니다. 코드 상으로는 마치 로컬 함수의 호출과 같지만 실제로는 함수가 원격 서버에서 실행됩니다. 네트워크 통신을 위한 작업 하나하나 챙기기 귀찮으니 통신이나 call 방식에 신경 쓰지 않고 원격지의 자원을 내 것처럼 사용할 수 있다는 의미입니다. IDL(Interface Definication Language) 기반으로 다양한 언어를 가진 환경에서도 쉽게 확장이 가능하며, 인터페이스 협업에도 용이하다는 장점이 있습니다. 지원 언어 : C++, Java, Python..
Kafka
-
Spring Kafka
본 포스팅은 spring boot 3.2.2 버전을 기준으로 작성되었습니다.공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다.스프링 카프카 스프링 카프카는 카프카를 스프링 프레임워크에서 효과적으로 사용할 수 있도록 만들어진 라이브러리로 기존 카프카 클라이언트 라이브러리를 래핑해서 만들어졌습니다. 스프링 카프카 프로듀서의존성implementation 'org.springframework.boot:spring-boot-starter'implementation 'org.springframework.kafka:spring-kafka' application.ymlspring: kafka: bootstrap-servers: kafka.sample.url.com:9092 KafkaT..
-
Kafka - consumer
컨슈머 구조 카프카에는 1개 이상의 컨슈머로 이뤄진 컨슈머 그룹이 존재합니다. 컨슈머 그룹을 운영함으로 인해 각 컨슈머 그룹으로부터 격리된 환경에서 안전하게 운영할 수 있습니다. 컨슈머 그룹으로 묶인 컨슈머들은 토픽에 있는 1개 이상 파티션들에 할당되어 데이터를 가져갈 수 있습니다. 반면에 파티션은 최대 1개의 컨슈머에만 할당 가능합니다. 이러한 특징으로 컨슈머 그룹의 컨슈머 개수는 가져가고자 하는 토픽의 파티션 개수와 같거나 작아야 합니다. 만약 그보다 많아지게 되면 특정 컨슈머는 파티션이 할당되지 않아 스레드만 차지하게 되기 때문입니다. 컨슈머 그룹은 다른 컨슈머 그룹과 격리되는 특징을 가지고 있어 컨슈머 그룹끼리 영향을 받지 않게 처리할 수 있으므로 컨슈머 그룹으로 따로 나눌 수 있는 경우는 최대한..
-
Kafka - Producer
프로듀서 객체 직렬화 전송 프로듀서는 보내는 객체를 직렬화화여 바이트 배열 형태로 브로커로 전송합니다. 브로커는 파티션에 바이트 배열 형태로 저장하고 컨슈머는 바이트 배열을 받아서 역직렬화로 객체를 복원합니다. 메시지 키값 여부에 따른 전송메시지 키의 사용 여부는 데이터 처리 순서와 관련이 있습니다. 카프카 프로듀서에서 브로커로 메시지를 보낼 때, 메시지 키를 지정할 수 있습니다. 메시지 키를 지정하지 않으면 스티키 파티셔닝(2.4버전 이후)방식으로 특정 파티션으로 전송되는 하나의 배치에 메시지를 빠르게 먼저 채워서 보냅니다. 이 경우에는 전송하는 대상 토픽이 파티션을 여러 개 가지고 있는 경우, 메시지의 전송 순서가 보장되지 않은 채로 컨슈머가 읽는 경우가 발생합니다. 반면에 메시지 키를 사용하면 메시..
-
Kafka - 구성요소
카프카 브로커 카프카 브로커는 카프카 클라이언트와 데이터를 주고받기 위해 사용하는 주체이자, 데이터를 분산 저장하여 장애가 발생하더라도 안전하게 사용할 수 있도록 도와주는 애플리케이션입니다. 하나의 서버에는 한 개의 카프카 브로커 프로세스가 실행되며, 보통은 데이터를 안전하게 보관하고 처리하기 위해 3대 이상의 브로커 서버를 1개의 클러스터로 묶어서 운영합니다. 카프카 클러스터로 묶인 브로커들은 카프카 프로듀서가 보낸 데이터를 안전하게 분산 저장하고 복제하는 역할을 수행합니다. 프로듀서로부터 데이터를 전달받으면 카프카 브로커는 프로듀서가 요청한 토픽의 파티션에 데이터를 저장하고 컨슈머가 데이터를 요청하면 파티션에 저장된 데이터를 전달합니다. 프로듀서로부터 전달된 데이터는 메모리, 데이터베이스, 캐시 메모..
NGINX
-
NGINX - CORS 처리하기
출처(Origin)이란? 출처(Origin)은 Scheme(protocol), Host, Port로 구성되어 있습니다. http, https의 경우에는 프로토콜이 포트 번호를 포함하고 있기 때문에 생략 가능하지만, 만약 포트를 명시함다면 포트번호까지 일치해야 출처가 같다고 볼 수 있습니다. 즉, scheme, host, port가 모두 일치하는 경우를 동일한 출처로 봅니다. # 기준이 되는 origin https://www.backtony.github.io # 같은 origin https://www.backtony.github.io/about https://www.backtony.github.io/about?q=hello https://user:password@www.backtony.github.io #..
-
NGINX - HTTP 모듈 구성
Nginx 기본 구성 worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; access_log logs/host.access.log combined; location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; loca..
-
Nginx - 등장 배경과 사용 용도
NginX란? NginX는 웹 서버이며, 리버스 프록시, 로드 밸런서, HTTP 캐시로 등으로 쓰일 수 있는 소프트웨어입니다. 요청에 응답하기 위해 이벤트 기반 구조를 채택하여 자원을 효율적으로 사용합니다. 등장 배경 최초의 웹서버 NCSA에 수많은 버그로 인해 이를 보완한 아파치 서버가 등장합니다. 아파치 서버는 요청이 들어오면 커넥션을 형성하기 위해 프로세스를 생성하는 방식으로 새로운 클라이언트 요청이 들어올 때마다 새로운 프로세스를 생성합니다. 프로세스를 만드는 작업은 오래 걸리므로 미리 프로세스를 만들어 놓는 prefork 방식을 사용합니다. 만약 미리 만들어 놓은 프로세스가 모두 할당되었다면 추가로 프로세스를 만들게 됩니다. 이런 구조로 인해 개발자는 다양한 모듈을 만들어 빠르게 기능을 추가할 ..
ETC
-
Github Action 알아보기
기본 flow작동 단계 github pushevent triggerjob 순서대로 작업 수행 이벤트 트리거repository에서 일어나는 push, fort 등의 작업github project, issue에서 일어나는 작업사용자가 직접 트리거 코드 작성 .github.workflows 폴더 하위에 github action으로 실행하고자 하는 일들을 파일별로 정의하면 별도의 설정 과정 없이 project의 actions 탭들을 통해 실행할 수 있습니다. actions 탭에서는 워크플로우 실행 결과를 확인할 수 있습니다. workflowworkflow란 이벤트 발생 시, 어떠한 행위를 할 것인가에 대한 작업 정의합니다. runner : job별 별도의 공간에서 실행하는 작업 공간에 대한 정의로 작업 간 내용..
-
멀티 프로젝트 헥사고날 아키텍처로 구축하기
공부한 내용을 정리하는 블로그와 관련 코드를 공유하는 Github이 있습니다. Hexagonal 아키텍처헥사고날 아키텍처(Hexagonal Architecture)는 포트와 어댑터 아키텍처(Ports and Adapters Architecture)라고도 불리는 소프트웨어 아키텍처 중 하나로 주요 목표는 응용 프로그램의 비즈니스 로직을 외부 세계로부터 격리시켜 유연하고 테스트하기 쉬운 구조를 만드는 것입니다. 이를 위해 핵심 비즈니스 로직은 중앙의 도메인 영역에 위치하며, 입력과 출력을 처리하는 포트와 어댑터를 통해 외부와 소통합니다. Adapter : 모든 외부 시스템과의 직접적인 상호작용을 담당ex) Controller, Kafka Listener, DB DAOInbound & Outbound port..
-
Tomcat의 file upload (feat. octet-stream, multipart)
application/octet-stream은 무엇일까? 구글링 결과는 다음과 같습니다. application/octet-stream은 이 타입은 이진 파일을 위한 기본값입니다. 이 타입은 실제로 잘 알려지지 않은 이진 파일을 의미하므로, 브라우저는 보통 자동으로 실행하지 않거나 실행해야 할지 묻기도 합니다. Content-Disposition 헤더가 값 attachment 와 함게 설정되었고 'Save As' 파일을 제안하는지 여부에 따라 브라우저가 그것을 다루게 됩니다. application/octet-stream은 알려지지 않은 이진 파일을 알리는 content-type이라고 볼 수 있습니다. multipart/form-data 클라이언트는 HTTP Request의 Body에 전송하고자 하는 데이터..
-
가비지 컬렉터
메모리 구조 모든 프로그램은 메모리에 올라와야 실행할 수 있습니다. 따라서 프로그램에 사용되는 변수들을 저장할 메모리가 필요한데 운영체제는 프로그램의 실행을 위해 다양한 메모리 공간을 제공합니다. 대표적으로 위와 같은 4가지 영역이 있습니다. Code 영역 실행한 프로그램의 코드가 저장되는 영역으로 텍스트 영역이라고도 합니다. CPU는 코드 영역에서 저장된 명령어를 하나씩 가져가서 처리합니다. Data 영역 전역 변수, 정적 변수가 저장되는 영역입니다. 프로그램의 시작과 함께 할당되어 프로그램이 종료되면 소멸합니다. Heap 영역 프로그램을 실행하면서 생성한 모든 객체가 저장되는 영역입니다.(흔히 new를 통해 성상한 모든 Object 타입의 인스턴스가 저장되는 영역) 힙 영역에 보관되는 메모리는 메소드..
-
HTTP/HTTPS
HTTP와 HTTPS HTTP Hypertext Transfer Protocol의 줄임말 서로 다른 시스템들 사이에서 통신을 주고받게 하는 가장 기본적인 프로토콜입니다. 서버에서 브라우저로 데이터를 전송하는 용도로 가장 많이 사용합니다. HTTPS Hypertext Transfer Protocol Secure의 줄임말 SSL(보안 소켓 계층)을 사용 SSL은 서버와 브라우저 사이에 안전하게 암호화된 연결을 만들 수 있게 도와주고, 서버와 브라우저가 민감한 정보를 주고받을 때 해당 정보가 도난당하는 것을 막아줍니다. Header는 암호화하지 않고 HTTP Message Body만 암호화합니다. SSL/TLS SSL/TLS는 HTTPS에서 암호화 시 사용하는 방식입니다. SSL의 업그레이드 버전이 TLS로,..
-
Blocking과 Non-Blocking, Sync와 Async
Blocking vs Non-Blocking 두 가지의 차이점은 다른 주체가 작업할 때 자신이 코드를 실행할 제어권이 있는지 없는지로 판단할 수 있습니다. Blocking Blocking 자신의 작업을 진행하다가 다른 주체의 작업이 시작되면 제어권을 다른 주체로 넘깁니다. 따라서 자신은 제어권이 없기 때문에 실행할 수 없고, 다른 주체가 실행을 완료하고 제어권을 돌려줄 때까지 아무 작업도 할 수 없습니다. Non-Blocking Non-Blocking은 다른 주체의 작업에 관련 없이 자신이 제어권을 갖고 있습니다. 따라서, 자신은 계속 작업을 수행할 수 있습니다. Sync vs Async 두 가지의 차이점은 결과를 돌려주었을 때 순서와 결과에 관심이 있는지 없는지 에 차이가 있습니다. 아래 설명부터 A는..
-
리눅스 메모리 관리
메모리가 관리되는 방법 메모리는 주소 덩어리로, 주소로 인덱싱하는 커다란 배열입니다. 컴퓨터가 부팅되면 텅텅 비어있던 메모리에 운영체제나 사용자 프로그램이 배열의 원소처럼 채워지면서 CPU를 점유할 기회를 노립니다. CPU가 메모리에 채워진 프로그램 속 코드를 곧장 읽으면 좋겠지만 CPU를 코드를 읽지 못합니다. 숫자로 바꿔줘야 합니다. 소스 코드를 숫자로 바꿔주는 것이 컴파일러고, 컴파일러가 동작하는 과정에서 코드들의 논리 주소를 결정합니다. 각각 프로그램마다 다른 논리 주소를 갖는 것이 아니라, 중복되는 논리 주소를 갖고 있습니다. 그래서 논리 주소를 가상 주소라고도 부릅니다. 모두 같은 주소를 사용한다면 메모리에서 어떻게 이를 구분할까요? 논리 주소 앞에 하나의 주소값이 더 추가되면서 프로그램마다 ..
-
Process & Thread
프로그램과 프로세스 피자와 피자 레시피를 비유로 들면 이와 같습니다. 피자 레시피 = 코드가 구현되있는 파일 = 프로그램 피자 레시피가 피자가 되는 것처럼 코드 파일(프로그램)도 실행되어 사용할 수 있는 무언가!!가 되어야 합니다. 그 무언가가 프로세스 입니다. 프로그램 -> 프로세스 프로그램이 프로세스가 되면서 총 2가지 일이 발생합니다. 프로세스가 필요로 하는 재료들이 메모리에 올라가야 합니다. 메모리는 Code, Data, Heap, Stack 으로 총 4가지 영역으로 구성되어 있습니다. 또한, 해당 프로세스에 대한 정보를 담고 있는 Process Control Block(PCB)가 프로세스 생성 시 함께 만들어 집니다. Process & Thread 우리는 대부분 위 그림과 같이 여러 가지의 프로..