전체 글 361

OOP - 객체지향이란 무엇인가?

객체지향 많은 분들이 객체지향 프로그래밍은 현실 세계의 모방, 추상화를 통해 프로그래밍에 반영하는 것이라고 말한다. 이러한 설명은 실용적인 관점에서 객체지향을 설명하기에 적합하지 않다. 가령 우리는 상속의 예시를 들 때 인간, 도형 등의 예시를 들고 추상화를 배울 때 동물, 타이어, 자동차 등의 예시를 들곤 한다. 이를 실제 소프트웨어에 접목할 수 있는가? 객체지향의 목표는 실세계를 모방하는 것이 아니다. 새로운 세계를 창조하는 것이다. 객체지향에서 가장 널리 퍼져있는 오해는 클래스가 객체지향 프로그래밍의 중심이라는 것이다. 객체지향은 객체를 지향하는 것이지 클래스를 지향하는 것이 아니다. 역할, 책임, 협력 객체지향이라는 말에서 어떤 단어가 먼저 떠오르는가? 많은 사람들은 클래스와 상속을 떠올린다. 하..

Programming/OOP 2022.05.16

Clean Code - 깨끗한 시스템이란 무엇인가?! (+ 관심사 분리)

깨끗한 시스템 시스템을 도시에 비유해보자. 도시의 온갖 세세한 사항을 혼자서 관리할 수 있을까? 그럴 순 없다. 그럼에도 도시는 잘 돌아간다. 수도관리 팀, 전력관리 팀, 교통관리 팀, 치안관리 팀 등 각 분야를 관리하는 팀이 있기 때문이다. 누군가는 각 팀의 역할을 자세히는 몰라도 대략적으로 파악하고 전체 그림을 설계하기도 한다. 누군가는 자신의 팀의 역할과 관련 팀과의 이해 관계 정도 까지만 집중한다. 이러한 부분이 프로그래밍에서는 적절한 추상화와 모듈화이다. 팀이 제작하는 시스템도 객체들을 적절하게 관심사를 분리해서 추상화를 이뤄내게 된다. 시스템 수준에서도 깨끗함을 유지하는 방법에 대해서 알아보자. 시스템 제작과 사용을 분리하라 제작(Construction)과 사용(Use)는 많이 다르다. 소프트..

Clean Code - 깨끗한 클래스란 무엇인가?! (클래스 고찰)

깨끗한 클래스 해당 포스팅은 클래스에 대해 다룬다. 깨끗한 클래스란 무엇인가에 대해 알아보자. 클래스 체계 깨끗한 클래스를 정의할 때 따르는 표준 자바 관례가 있다. 클래스의 내부 요소를 정의할 때 가장 먼저 변수 목록을 정의한다. 변수 중에서는 가장 먼저 static public 상수를 정의하고 다음으로 static private 변수를 정의한다. 그 다음 private 인스턴스 변수를 정의한다. 변수 목록 다음에 public 메소드를 정의하고 그 다음 private 메소드를 정의한다. 클래스가 내부에서 추상화 단계가 순차적으로 내려가는 관례를 지키면서 신문 기사처럼 읽히는 효과를 가진다. 캡슐화 변수와 유틸리티 함수는 가능한 공개하지 않는 것이 좋지만 반드시 숨겨야 한다는 법칙도 없다. 내가 속한 팀..

Real MySQL - 옵티마이저란 무엇인가 ? (+ 기본 데이터 처리)

옵티마이저(Optimizer) MySQL에서 쿼리의 결과는 동일하지만 내부적으로 그 결과를 만들어내는 방법은 매우 다양하다. 그런 방법 중에서 어떤 방법이 최적이고 최소의 비용이 소모될 지 결정해야 한다. 쿼리를 최적으로 실행하기 위해 각 테이블의 데이터가 어떤 분포로 저장돼 있는지를 참조하고, 데이터를 기반으로 최적의 실행 계획을 수립해주는 것이 옵티마이저(Optimizer)이다. 어떤 DBMS든 쿼리의 실행 계획을 수립하는 옵티마이저는 가장 복잡한 부분으로 알려져있다. 하지만 실행 계획을 이해해야 실행 계획의 불합리한 부분을 찾아내고, 더 최적화된 방법으로 실행 계획을 수립하도록 유도할 수 있다. 쿼리 실행 절차 MySQL 서버에서 쿼리가 실행되는 과정은 크게 세 단계로 나눌 수 있다. SQL문을 잘..

Database/SQL 2022.05.13

SQL - Using Temporary, Using Filesort 정리 (+ 임시 테이블, 파일 정렬)

Using Temporary, Using Filesort Explain 문으로 실행 계획을 확인하면, 늘 눈에 거슬리는 것이 Using Temporary, Using Filesort이다. 이것들이 왜 발생하고 어떠한 영향이 있는 지 알아보자. 임시 테이블(Using Temporary) MySQL 엔진이 스토리지 엔진으로부터 받아온 레코드를 정렬하거나 그룹핑 할 때는 내부적인 임시 테이블을 사용한다. MySQL 엔진이 사용하는 임시 테이블은 처음에는 메모리에 생성됐다가 테이블의 크기가 커지면 디스크로 옮겨진다. 원본 테이블의 스토리지 엔진과 관계없이 임시 테이블이 메모리를 사용할 때는 MEMORY 스토리지 엔진을 사용하며, 디스크에 저장될 때는 MyISAM 스토리지 엔진을 이용한다. 다음은 임시 테이블이 ..

Database/SQL 2022.05.11

SQL - SELECT 쿼리 실행 순서 정리!

SELECT 쿼리문은 FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY 총 6단계를 거친다. 아래는 각 단계의 동작을 정리한 것이다. FROM 절 (+ Join) 쿼리의 첫번째 실행 순서는 FROM절이다. FROM 절에서는 조회할 테이블을 지정합니다. 이후 Join을 실행하여 하나의 가상 테이블로 결합합니다. WHERE 절 WHERE 절에서는 테이블에서 조건에 맞는 데이터를 필터링한다. GROUP BY GROUP BY 절에서는 선택한 칼럼을 기준으로 조회한 레코드 목록을 그룹핑한다. HAVING 절 HAVING 절은 그룹핑 후에 각 그룹에 사용되는 조건 절이다. 쉽게 말해 그룹을 필터링한다고 생각하면 된다. HAVING 절의 조건을 WHERE 절에도 사용할 수 있는 경..

Database/SQL 2022.05.11

Clean Code - 깨끗한 테스트 코드 유지하기

개요. 애자일과 TDD 덕택에 단위 테스트를 자동화하는 개발자들이 이미 많아졌고 점점 더 늘어나는 추세다. 하지만 많은 개발자들이 테스트 코드 작성을 급하게 서두르면서 제대로 된 테스트 케이스 작성을 놓치고 있다. 제대로 된 좋은 테스트 케이스를 작성하는 것에 대해 알아보자 TDD 법칙 세 가지 지금은 TDD가 실제 코드를 짜기 전에 단위 테스트부터 작성하라고 요구한다. 아래는 TDD가 추구하는 세 가지 원칙이다. 실패하는 단위 테스트 를 작성할 때까지 실제 코드를 작성하지 않는다. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다. 위 세가지 규칙을 지키면 개발과 테스트가 대략 30초 주기로 묶인다. 추가적으로 테스..

Clean Code - 외부 코드 사용하기 (+ 경계 클래스, 어댑터 패턴)

개요. 시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다. 패키지를 사거나 라이브러리 등 오픈 소스를 사용하기도 한다. 이 때 우리는 외부 코드를 우리코드에 어떻게 해야 더 깔끔하고 안전하게 통합할 수 있는 지 고민해야 한다. 고민은 외부 코드와 우리 코드의 경계를 파악하는 것부터 시작한다. 경계(Boundaries) 전체 소프트웨어 개발에 사용하게 되는 외부 코드를 내 코드에서 호출하는 부분을 경계(boundaries)라고 한다. 경계 없이 단순하게 외부 코드를 사용하려는 곳에서 직접 호출할 수 있지만 그렇게 했을 때 아래와 같은 문제가 생긴다. 인터페이스 제공자가 지원한 인터페이스를 그대로 사용해야 한다. 인터페이스 제공자는 최대한 범용적이게 개발하는 것을 선호한다. 인터페이스 사용자는..

QueryDSL - 벌크(Bulk) 연산 시 주의할 점!

벌크(Bulk) 연산 주의사항 Querydsl에서 Bulk 연산을 할 때 주의사항이 있다. 예를 통해 살펴보자. 아래 메서드는 모든 member의 money를 0으로 초기화한다. public void bulkUpdate() { // init Money queryFactory .update(member) .set(member.money, 0) .execute(); } 문제는 이때 쿼리를 날려서 DB에 반영은 하지만, 영속성 컨텍스트에 반영하지 않는다. 문제 상황 기존에 아래와 같이 Member가 3개가 있다고 가정하자. - id: 1, money: 10000 - id: 2, money: 20000 - id: 3, money: 30000 해당 Member들이 영속성 컨텍스트에 들어 있을 때 Bulk 연산을 ..

Server/Spring JPA 2022.05.08

Java - 제네릭(Generic)타입을 제한하는 방법! (2)

제네릭(Generic) 타입 제한 지난 1장(Java - 제네릭은 무엇인가)에 이어서 제너릭을 사용해서 타입을 제한하거나 와일드카드로 사용하는 방법을 알아본다. 지난 장에서 봤듯 제너릭을 사용하면 타입 체크를 효율적으로 수행할 수 있다. 일반적인 제너릭 형식을 사용한 클래스를 만들었다고 가정하자. 하지만 이 방식으로 클래스를 선언했을 떄 제너릭 타입은 모든 타입을 허용 한다. public class MyClass implements MyInterface{ private E element; void set(E element) { this.element = element; } } 해당 클래스의 인스턴스 객체를 생성할 때 제너릭 타입을 명시한다. MyClass instance = new MyClass(); 여..

Language/Java 2022.05.08