소개대용량 서버를 구축하기 위해서는 어떤 것들을 알아야 할까?Spring, MySQL, MongoDB, Redis, Kafka, MSA….서버 개발자의 핵심은 데이터다.대용량 시스템이 어려운 이유는 결국 많은 양의 데이터에서 시작된다. 어떻게 많은 양의 데이터를 안정적으로 삽입, 갱신, 조회할까?MySQL - 정규화, 인덱스, 트랜잭션, 동시성 제어MySQL에서는 이 4가지 키워드가 핵심이 된다. 대용량 시스템에 대한 이해웹의 기본 아키텍처웹 서버는 HTML, CSS, JavaScript와 같은 정적인 데이터들을 주로 서빙한다.웹 애플리케이션 서버는 데이터베이스에 저장된 데이터처럼 동적인 데이터들을 서빙한다. 웹 서버, 웹 애플리케이션 서버는 왜 나누어져 있을까?태초에는 웹 서버만 있는 형태에서 웹의 복..
코드를 보는 것만으로도 어떤 아키텍처인지 파악할 수 있다면 좋지 않을까? 새 프로젝트에서 가장 먼저 제대로 만들려고 하는 것은 패키지 구조다. 프로젝트에서 계속 사용할 괜찮아 보이는 구조를 잡는다. 그러고 나서 프로젝트가 진행될수록 점점 바빠지고 패키지 구조는 짜임새 없는 엉망진창 코드를 그럴싸하게 보이게 만드는 껍데기일 뿐이라는 점을 깨닫게 된다. 한 패키지에 있는 클래스들이 불러오지(import) 말아야 할 다른 패키지에 있는 클래스들을 불러오게 된다. 계층으로 구성하기 코드를 구조화하는 첫 번째 접근법은 계층을 이용하는 것으로서, 다음과 같이 구성할 수 있다. 여기서는 전에 봤듯이 domain 패키지에 AccountRepository 인터페이스를 추가하고, persistence 패키지에 Accoun..
코딩테스트 연습 - 카펫 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요. programmers.co.kr 문제 설명 Leo는 카펫을 사러 갔다가 아래 그림과 같이 중앙에는 노란색으로 칠해져 있고 테두리 1줄은 갈색으로 칠해져 있는 격자 모양 카펫을 봤습니다. Leo는 집으로 돌아와서 아까 본 카펫의 노란색과 갈색으로 색칠된 격자의 개수는 기억했지만, 전체 카펫의 크기는 기억하지 못했습니다. Leo가 본 카펫에서 갈색 격자의 수 brown, 노란색 격자의 수 yellow가 매개변수로 주어질 때 카펫의 가로, 세로 크기를 순서대로 배열에 담아 return 하도록 solution 함수를 작성해..
요구사항 대용량 데이터 엑셀 다운로드 파라미터에 따라 동적으로 조건이 바뀌게 해야 함 DB: MongoDB 방법 구상: 스트림 방식으로 데이터를 뽑아오고 ➜ 엑셀을 스트림으로 채우고 ➜ 엑셀 내보내기 구현 알아보니 스프링부트에서는 엑셀기능을 구현할 때 poi라는 기능을 사용할 수 있다고 한다. // build.gradle implementation('org.apache.poi:poi-ooxml:5.2.2') Repository interface CustomRepository { fun streamSearch(requestDto: RequestDto): Stream } @Repository class CustomRepositoryImpl(@Autowired private val mongoTemplate: ..
코딩테스트 연습 - 피보나치 수 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요. programmers.co.kr 문제 설명 피보나치 수는 F(0) = 0, F(1) = 1일 때, 1 이상의 n에 대하여 F(n) = F(n-1) + F(n-2)가 적용되는 수입니다. 예를 들어 F(2) = F(0) + F(1) = 0 + 1 = 1 F(3) = F(1) + F(2) = 1 + 1 = 2 F(4) = F(2) + F(3) = 1 + 2 = 3 F(5) = F(3) + F(4) = 2 + 3 = 5 와 같이 이어집니다. 2 이상의 n이 입력되었을 때, n번째 피보나치 수를 1234567로 나눈 ..
코틀린에는 객체의 컨텍스트에서 코드를 실행하기 위한 몇 가지 범위 지정 함수가 있다. let `let` 함수는 주로 null이 아닌 객체에 대한 코드를 실행하거나, null 가능성이 있는 변수와 작업을 할 때 사용한다. 람다는 'it' 키워드를 통해 호출된 객체에 접근하며, 람다 내부의 마지막 표현식을 반환한다. fun main() { val listWithNulls: List = listOf("A", null) for (item in listWithNulls) { item?.let { println(it) } // prints A and ignores null } } // 실행 결과 A run `run` 함수는 람다 내에서 수신 객체('this')에 대한 작업을 수행한 후, 람다 내부의 마지막 표현식을..
계층형 아키텍처에 대해 불만만 늘어놓았으니 이번 장에서는 대안에 대해 이야기해 보자. 먼저 SOLID의 'S'와 'D'를 담당하는 단일 책임 원칙(SRP)과 의존성 역전 원칙(DIP)으로 시작한다. 단일 책임 원칙 '오로지 한 가지 일만 하는 것'은 단일 책임이라는 말을 가장 직관적으로 해석한 것이므로, 단일 책임 원칙을 자주 위와 같이 해석한다. 하지만 오해의 여지가 있다는 점에 주의해야 한다. '책임'은 사실 '한 가지 일만 한다'는 것보다는 '변경할 이유'로 해석해야 한다. 컴포넌트를 변경할 이유가 오로지 한 가지밖에 없다면 컴포넌트는 딱 한 가지 일만 하게 된다. 그리고 여기서의 초점은 변경할 이유가 오직 한 가지라는 것이다. 아키텍처에서는 컴포넌트를 변경할 이유가 한 가지라면 우리가 어떤 다른 ..
다들 한 번쯤은 계층으로 구성된 애플리케이션을 개발해 본 적이 있을 것이다. (사실, 지금까지 맡았던 프로젝트가 그랬다..) 맨 위의 웹계층에서는 요청을 받아 도메인 혹은 비즈니스 계층에 있는 서비스로 요청을 보낸다. 서비스에서는 필요한 비즈니스 로직을 수행하고, 도메인 엔티티의 현재 상태를 조회하거나 변경하기 위해 영속성 계층의 컴포넌트를 호출한다. 사실 계층형 아키텍처는 견고한 아키텍처 패턴이다. 계층을 잘 이해하고 구성한다면 웹계층이나 영속성 계층에 독립적으로 도메인 로직을 작성할 수 있다. 원한다면 도메인 로직에 영향을 주지 않고 웹 계층과 영속성 계층에 사용된 기술을 변경할 수 있다. 기존 기능에 영향을 주지 않고 새로운 기능을 추가할 수도 있다. 잘 만들어진 계층형 아키텍처는 선택의 폭을 넓히..