🥕 이번 당근 클론 프로젝트에서는 기존에 자주 사용하던 MVC 구조가 아닌 헥사고날 아키텍처를 적용해보려 한다. 따라서 먼저 배경 지식을 습득후 간단한 예제 코드를 통해 헥사고날 아키텍처에 대해 익숙해지려 한다. 헥사고날 아키텍처를 적용하려는 이유이전의 협업 프로젝트에서 이런 일이 있었다.여러 회의를 거쳐 프로젝트의 방향성을 정하고, 데이터를 추출한 뒤, 백엔드 팀은 데이터베이스 구조를 모두 설계하고 엔티티에 맞게 비즈니스 로직을 작성하여 4~5 개의 MVP 기능을 구현한 상태였다. 이후 PM과의 회의를 통해 새로운 기능을 추가하기 위해, 데이터베이스 테이블 구조의 변경이 필요하다는 것을 인지했다. 따라서 데이터베이스 테이블 구조를 다소 변경하게 되었다. 여기서 문제가 발생했다. 데이터는 거의 변함..
분류 전체보기
김영한님 강의와 다른 여러 스프링 강의에서 DB와 매핑하기 위한 객체를 생성하는 경우 숫자 타입에 Long을 사용하는 것을 볼 수 있었다. 더 자세하게는 “회원” 엔티티의 AUTO_INCREMENT 인 PK 값을 Long 타입으로 선언했다. 회원 도메인의 레코드 수가 21억개 이상이 될 수 있어서 테이블 컬럼 타입입을 BIGINT로 선언해서 그런것일까? Integer가 아닌 Long 타입을 사용하는 이유가 궁금해서 여러 블로그의 글을 살펴봤는데 내가 확인해 본 블로그 글에서는 모두 같은 내용을 담고 있었다. Wrapper 클래스는 기본 값으로 null을 가진다. Long은 Integer보다 넓은 범위를 표현한다. 뭔가 가려움이 해소되지 않는다.. ☁️ Wrapper 클래스 사용 1번은 나도 겪어본 문제이..
☁️ EJB → Spring → Spring Boot 스프링이란 기존의 EJB(J2EE)에 의존적인 개발 방식의 불편한 점을 개선한 프레임워크이다. EJB에 의존적인 개발은 객체지향적인 설계가 힘들고 서버 구축 비용이 비싼데 성능조차 좋지 않은 단점이 있었다. 이러한 단점을 보완하여 스프링 IoC 컨테이너, DI(의존성 주입), AOP등 객체지향의 장점을 살린 기능을 가지는 프레임워크가 스프링 프레임워크이다. 하지만 스프링으로 만들어진 프로젝트도 불편한 점이 여전히 존재했다. 별도의 WAS 서버를 설치하고 배포해야 하는 작업, XML의 사용, 외부 라이브러리들과의 버전 호환성 등의 불편한 점을 개선하여 스프링 프레임워크를 더 쉽고 편리하게 사용할 수 있게 하는 프로젝트가 스프링 부트이다. 스프링 부트는 ..
테이블 컬럼의 각 데이터 타입을 결정할 때는 아래의 사항을 유의해야 한다. 저장되는 값의 성격에 맞는 최적의 타입을 선정 가변 길이 컬럼은 최적의 길이를 지정 조인 조건으로 사용되는 컬럼은 똑같은 데이터 타입으로 선정 컬럼의 데이터 타입을 결정할 때 실제 저장되는 값의 특성을 고려하기 보다는 저장되는 값의 최대 길이를 기준으로 컬럼의 길이를 선택하는 것이 일반적이다. 하지만 컬럼의 크기가 너무 무분별하게 커진다면 디스크 공간을 많이 차지할 것이고 해당 컬럼이 인덱스라면 검색 효율도 떨어질 것이다. ☁️ ENUM 과 SET ENUM 과 SET을 사용하면 문자열 값을 내부적인 작엽을 통해 숫자 값으로 매핑하여 관리한다. 레코드의 타입이나 상태와 같은 코드 형태의 컬럼(ex. 상품 유형 코드 E(전자), A(..
테이블 컬럼의 각 데이터 타입을 결정할 때는 아래의 사항을 유의해야 한다. 저장되는 값의 성격에 맞는 최적의 타입을 선정 가변 길이 컬럼은 최적의 길이를 지정 조인 조건으로 사용되는 컬럼은 똑같은 데이터 타입으로 선정 컬럼의 데이터 타입을 결정할 때 실제 저장되는 값의 특성을 고려하기 보다는 저장되는 값의 최대 길이를 기준으로 컬럼의 길이를 선택하는 것이 일반적이다. 하지만 컬럼의 크기가 너무 무분별하게 커진다면 디스크 공간을 많이 차지할 것이고 해당 컬럼이 인덱스라면 검색 효율도 떨어질 것이다. ☁️ 문자열 (CHAR, VARCHAR) 두 타입 모두 문자열을 저장한다는 공통점을 가진다. CHAR 타입은 고정길이이며, VARCHAR 타입은 가변길이로 관리된다. CHAR(1), VARCHAR(1) 은 모두..
☁️ 파티션 파티션 기능은 논리적인 하나의 테이블을 물리적으로 여러 개의 테이블로 분리해서 관리하는 기능이다. 주로 대용량의 테이블을 물리적으로 여러 개의 소규모 테이블로 분산하는 목적으로 사용한다. 또한 파티션을 분리하면 필요한 파티션에만 접근할 수 있다는 장점을 취할 수 있다. 대용량 테이블을 분산하여 저장한다면 조회 쿼리의 성능이 좋아지게 된다. 하지만 잘못된 쿼리를 사용하는 경우 오히려 쿼리의 성능이 나빠질 수 있다. 파티션 사용 시 유의해야 할 사항을 알아보자. 파티션을 사용하는 이유 테이블의 데이터가 많다고 해서 무조건 파티션을 적용하는 것은 옳지 않다. 테이블의 크기가 커져 인덱스가 메모리보다 커지는 경우 혹은 데이터 특성상 주기적인 삭제작업이 필요한 경우 등에 파티션을 사용하면 좋다. 인덱..
💡 해당 포스팅은 참고용으로 MySQL 사용 편리성을 위해 쿼리나 명령어, Real MySQL의 쿼리 사용 팁들을 단순 정리한다. ☁️ INSERT 온라인 트랜잭션 서비스에서 INSERT 문장은 대부분 1건 또는 소량의 레코드를 추가하기에 성능에 대해 고려할 부분이 많지 않다. 한 번의 많은 INSERT 문이 실행되는 경우 쿼리 문장 보다는 테이블 구조가 성능에 영향을 미치는 경우가 대다수이다. 하지만 많은 경우 INSERT의 성능과 SELECT의 성능을 동시에 빠르게 만들 수 있는 테이블 구조는 없다. 그래서 INSERT와 SELECT 성능을 어느 정도 타협하면서 테이블 구조를 설계해야 한다 - 중에서 유용한 기능 INSERT IGNORE: INSERT 실행 시 테이블의 유니크 한 컬럼의 값이 중복되는..
인덱스 레인지 스캔은 인덱스를 탐색하는(Index Seek) 단계와 인덱스를 스캔하는(Index Scan) 과정으로 구분할 수 있다. 탐색 단계는 B-Tree를 통해 특정 인덱스 혹은 범위를 탐색하는 작업이고, 스캔 단계는 리프노드를 순차적으로 읽는 작업이다. 일반적으로 인덱스를 통해 가져오는 레코드는 소량이다. 따라서 스캔 작업 보다는 탐색 작업이 상대적으로 부하가 크다. ☁️ 드라이빙 테이블과 드리븐 테이블 두 개 이상의 테이블을 JOIN하는 과정에서 드라이빙 테이블과 드리븐 테이블이 구분된다. 보통 드라이빙 테이블을 읽을 때는 인덱스 탐색 작업을 한 번만 수행한 뒤 스캔작업만 수행하면 되지만 드리븐 테이블은 탐색과 스캔 작업을 드라이빙 테이블에서 읽은 레코드 수만큼 진행한다.따라서 드라이빙 테이블과..
☁️ 인덱스 사용의 기본적인 유의사항 기본적으로 인덱스를 사용하려면 인덱스된 컬럼의 값(인덱스 키값) 자체를 변환하지 않고 사용해야 한다. 해당 조건은 타입이 동일해야 한다는 조건을 포함한다. 자동 타입 변경으로 인해 인덱스를 사용하지 못하는 경우도 유의해야 한다. 예를 들어 아래와 같은 쿼리는 인덱스를 사용하지 못한다. -- employees.salary가 단일 컬럼 인덱스로 선언되었다고 가정 SELECT * FROM employees WHERE salary*10=12000; -- 아래 처럼 변경하면 인덱스를 사용할 수 있다. SELECT * FROM employees WHERE salary=12000/10; 만약 특정 컬럼을 변환한 값에 의한 검색이 빈번하게 발생하는 경우 가상 컬럼을 통해 인덱스를 ..