_

Always be tactful

성장 과정/인사이트 9

Common vs Global: 패키지 구조 이해하기

들어가기 전에가장 흔하게 사용되는 Common 패키지에 대해 말하자면, 결국 핵심은 구조화 및 가독성 향상이다.프로젝트를 진행하다 보면 프로젝트 내 여러 모듈이나 레이어에서 공통으로 쓰이는 코드가 생기기 마련이다. 코드 재사용성을 극대화하고 중복 코드를 방지하기 위해, 나아가 유지보수 측면에서 편리하기 위해 우리는 공통 코드들을 따로 빼게 된다. 이러한 코드들의 모음집이 Common 패키지인 셈이다.※ 사실 패키지 구조라는 게 명확한 답이 있는 건 아니다 보니 가벼운 마음으로 읽었으면 한다. Common vs GlobalCommon으로 퉁쳐서 사용하는 경우가 많은데 사실 Common 패키지와 Global 패키지는 서로 의미가 다르다.Common: 공통으로 사용되는 모든 코드를 모아두는 패키지Global:..

.prettierrc

import 정렬하기Code formatter로 Prettier를 쓰고 있었다.그동안 import는 신경 쓰지 않고 살았는데, 프로젝트 규모가 커지면서 상당히 지저분해짐을 느꼈다. 찾아보니 sort-imports 익스텐션을 추천하더라.그러나 막상 적용하고 보니 정렬 기준이 이상했고 커스텀하기도 어려웠다. 다른 방법도 여럿 시도했지만 썩 마음에 들지 않았다. prettier-plugin 사용하기결국 선택한 방법은 Prettier 플러그인을 사용하는 것이다.(그동안 Prettier 플러그인으로 sort-imports가 있는 줄 몰랐다.)# 플러그인 설치npm install --save-dev prettier @ianvs/prettier-plugin-sort-imports플러그인 설치 후, 루트 디렉토리에 아..

Database driver: undefined/unknown

문제 상황Spring Boot 3.4.3에서 JPA를 추가하니 아래와 같은 로그가 출력되었다. Database JDBC URL [Connecting through datasource 'HikariDataSource (HikariPool-1)'] Database driver: undefined/unknown Database version: 9.3 Autocommit mode: undefined/unknown Isolation level: undefined/unknown Minimum pool size: undefined/unknown Maximum pool size: undefined/unknown 해결 방법연결부터 제대로 해야 한다는 생각에 고칠 생각부터 했다. "왜..

Docker Compose에서 MySQL 데이터 영속성 설정하기

🐳 도커 컴포즈최신 버전에서는 Docker Desktop이 기본적으로 Docker Compose v2를 포함하고 있어서 별도로 설치할 필요 없이 사용할 수 있다.과거에는 도커 컴포즈가 별도 바이너리로 취급되어 직접 설치하는 과정이 요구되었으며, dokcer-compose 명령어를 사용했다.# 설치 확인docker compose version# 출력 예시Docker Compose version v2.34.0-desktop.1docker-compose.yml # 기본 공통 구성docker-compose.override.yml # 로컬 전용 설정 (자동 인식)docker-compose.prod.yml # 운영 환경 전용.env # 환경변수데이터..

Spring Boot에서 JPA로 Docker MySQL 연동하기

들어가며자바는 프로그래밍 언어고, 스프링은 자바 기반 웹 애플리케이션 프레임워크다.그런 스프링을 더 쉽게 쓰도록 돕는 툴킷이 스프링 부트다. ▼ 과거 배포 과정 (대략적)더보기WAS 설치 (서버): 톰캣 같은 WAS를 OS에 설치하고 직접 설정IDE 내 개발: 이클립스 같은 IDE에서 복잡한 코딩 후 컴파일WAR 생성 (파일): 애플리케이션을 .war(웹 아카이브) 파일로 패키징WAR 배포: 톰캣 같은 WAS의 'webapps' 폴더에 넣거나 직접 업로드하여 배포웹 앱 실행: WAS가 WAR 안에 들어있는 웹 애플리케이션을 풀어 서버 구동▼ 스프링 부트 도입 후더보기WAS 직접 설치 및 설정→ WAS(톰캣)을 내장 서버로 포함하여 바로 실행 가능WAR 파일 생성 후 WAS에 배포→ 실행 가능한 JAR 파..

RESTful API에서 '응답 설계'가 반이라고?

ResponseEntity응답 설계 핵심 도구우리는 ResponseEntity에 대해 왜 알아야 할까?이유는 간단하다.스프링 프레임워크에서 HTTP 응답을 정교하게 제어하기 위한 핵심 도구이기 때문이다.단순한 "값 반환"이 아니라, HTTP 상태 코드, 헤터, 본문까지 직접 다룰 수 있다. 1. RESTful API에서 '응답 설계'는 감히 절반이라 할 수 있다.REST는 HTTP 자체를 프로토콜로 삼는다.응답에 상태 코드, 헤더, 본문을 정밀하게 제어해야 하며, 이걸 직접 제어하는 대표적인 도구가 ResponseEntity다.return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found");→ 단순한 return "User not fou..

비즈니스 로직이니까 서비스에 있어야지!

비즈니스 로직, 무조건 서비스에 두어야 할까?도메인 주도 설계(DDD)를 공부하다 보면 흔히 맞닥뜨리는 질문이 있다."비즈니스 로직이면 원래 서비스 레이어에 두는 거 아닌가?" 이 질문은 언뜻 맞는 말처럼 들리지만, 사실 절반만 맞는 말이다. 이 글에서는 비즈니스 로직의 위치에 대해 하나씩 짚어보며, 헷갈릴 수 있는 지점들을 정리해본다.서비스에 로직을 두는 게 맞는 경우다음과 같은 경우에는 비즈니스 로직을 서비스 레이어에 두는 것이 자연스럽다.여러 도메인 객체 간의 상호작용이 필요한 경우외부 시스템과의 연동이 포함되는 경우 (예: 메일 전송, 결제 API 호출 등)도메인 객체 내부에 두기엔 과도하거나 부적절한 경우예를 들어, "예약을 저장하고, 알림도 보내고, 결제도 트리거하는 흐름"이라면 이는 하나의 ..

DDD에서는 private을 안 쓴다면서?

DDD에서는 private을 지양한다?객체지향에서는 정보를 감추라고 하는데, 도메인 주도 설계에서는 왜 자꾸 public을 강조할까? 들어가며객체지향에서는 이렇게 배운다."메서드와 필드는 최대한 감춰라.""캡슐화를 통해 객체의 내부 구현을 보호해야 한다."그런데 도메인 주도 설계(DDD)를 공부하다 보면 이렇게 말한다.“비즈니스 규칙은 숨기지 말고, 드러내라.” 그럼 결국, private 쓰지 말라는 건가?헷갈릴 수밖에 없다.도메인 개념은 감추지 말고 드러내야 한다스케줄을 체크하는 것은 꽤 중요한 도메인 개념이다.👉 그래서 다음과 같은 메서드를 외부에 열어주는 게 좋다.public boolean isSchedulable(LocalDateTime start, LocalDateTime end) { r..

무분별한 Getter & Setter 사용은 OOP 원칙을 위배한다.

들어가기에 앞서, 우리는 Getter와 Setter에 대해 학습했다. OOP 원칙 중 캡슐화에 대해 인지하였고, 따라서 Setter 사용을 지양해야 한다는 것 정도는 이미 알고 있는 사실이다. 그렇다면 왜 Getter 사용도 지양해야 하는 걸까?또는, Setter를 지양해야 하는 명확한 이유는 뭘까?Getter와 Setter의 탄생 객체 지향은 정보 은닉에서 시작한다.객체 지향 언어의 장점은 물론 다양하겠지만, 가장 큰 장점 중 하나가 유연성이다. 이러한 설계 방식은 변화하는 요구사항에 쉽게 대응할 수 있도록 한다. 유연성을 가능하게 하는 요소는 무엇일까?바로, 1. 캡슐화 2. 상속 3. 다형성이다. 그중 캡슐화, 이하 정보 은닉은 내부 구현을 숨기고 필요한 부분만 외부에 공개하도록 한다. 외부 코드가..