목록전체 글 (130)
csct3434
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/5OkvK/btsFmi8WFOu/JZkUl1g4W4v2bteuWIhpB0/img.png)
서문 웹 인터페이스를 제공하는 어댑터의 구현 방법을 살펴본다. 의존성 역전 웹 어댑터 관련 아키텍처 요소 자세히 보면 의존성 역전 원칙이 적용된 것을 발견할 수 있다. 포트 인터페이스를 거치지 않고 어댑터가 서비스를 직접 호출할 수도 있다. 그럼에도 불구하고 어댑터와 유스케이스 사이에 포트 인터페이스를 넣는 이유는 애플리케이션 코어가 외부 세계와 통신할 수 있는 곳에 대한 명세가 코어이기 때문이다. 포트를 적절한 곳에 위치시키면 외부와 어떤 통신이 일어나는지 정확히 파악할 수 있고, 이는 유지보수에 있어 매우 소중한 정보이다 포트 인터페이스가 필요한 이유는 상호작용이 많이 일어나는 애플리케이션에서 더욱 명확해진다. 애플리케이션에서 웹 소켓을 통해 실시간 데이터를 사용자의 브라우저로 보내는 시나리오에서는 ..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/Gl1jT/btsFwDXpFwV/hAvqQOjkEPe8yeaVnfeKa0/img.png)
구현 순서 도메인 → 유스케이스 → 포트 → 어댑터 도메인 모델 구현하기 Account package buckpal.domain; @AllArgsConstructor(access = AccessLevel.PRIVATE) public class Account { @Getter private final AccountId id; @Getter private final Money baselineBalance; @Getter private final ActivityWindow activityWindow; // 생성자 생략 public Money calculateBalance() { return Money.add( this.baselineBalance, this.activityWindow.calculateBalan..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/CaaXg/btsFpRbxdik/Df3LjxXTl3ZHS77m6lKprk/img.png)
송금하기 유스케이스 계층으로 구성하기 domain : 도메인 계층 / persistence : 영속성 계층 / web : 웹 계층 domain 패키지에 AccountRepository 인터페이스를 추가하고, persistence 패키지에 AccountRepositoryImpl 구현체를 둠으로써 의존성을 역전함 문제점 애플리케이션의 기능 조각이나 특성을 구분 짓는 패키지 경계가 존재하지 않는다. 서로 연관되지 않은 기능들끼리 엉망진창으로 묶여 예상하지 못한 부수효과를 일으킬 가능성이 크다 애플리케이션이 어떤 유스케이스들을 제공하는지 파악할 수 없다. AccountService가 어떤 유스케이스를 구현하는지 패키지 구조만으로는 파악할 수 없다 특정 기능을 찾기 위해서는 어떤 서비스가 이를 구현했는지 추측해야..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/tC0oq/btsFmi17b44/j6vucxoAoOepxIujoNqWxk/img.png)
단일 책임 원칙 일반적인 해석 (오해) : ‘하나의 컴포넌트는 오로지 한 가지 일만 해야 하고, 그것을 올바르게 수행해야 한다’ 실제 정의 : ‘컴포넌트를 변경하는 이유는 오직 하나뿐이어야 한다’ 아키텍처에서 단일 책임 원칙의 의미 컴포넌트를 변경할 이유가 한 가지라면, 어떤 다른 이유로 소프트웨어를 변경하더라도 해당 컴포넌트에 대해서는 신경쓸 필요가 없다는 것 컴포넌트의 의존성 각각은 이 컴포넌트를 변경하는 이유 하나씩에 해당 컴포넌트 A : 모든 컴포넌트에 의존하고 있기 때문에 다른 어떤 컴포넌트가 바뀌든지 같이 변경해야 함 컴포넌트 E : 의존하는 컴포넌트가 없기 때문에 E를 변경할 이유는 새로운 요구사항에 의해 E의 기능을 바꿔야 할 때 뿐 의존성 역전 원칙 의존성 역전 원칙의 정의 : '코드상의..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/Kiq57/btsFoLh8QxZ/FktMPwDsvnwUtMIV1G8rdK/img.png)
웹 계층에서는 클라이언트로부터 요청을 받아 도메인 계층에 있는 서비스로 요청을 보냄 서비스에서는 필요한 비즈니스 로직을 수행하고, 도메인 엔티티의 현재 상태를 조회하거나 변경하기 위해 영속성 계층의 컴포넌트를 호출 사실 계층형 아키텍처는 견고한 아키텍처 패턴이다 계층을 잘 이해하고 구성한다면 웹 계층이나 영속성 계층에 독립적으로 도메인 로직을 작성할 수 있음 도메인 로직에 영향을 주지 않고 웹 계층과 영속성 계층에 사용된 기술을 변경 가능 잘 만들어진 계층형 아키텍처는 선택의 폭을 넓히고, 변화하는 요구 사항과 외부 요인에 빠르게 적응할 수 있음 계층형 아키텍처의 함정 계층형 아키텍처는 데이터베이스 주도 설계를 유도한다 우리가 만드는 대부분의 애플리케이션의 목적은 보통 비즈니스를 관장하는 규칙이나 정책을..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/bP3AHv/btsFoGU8HUA/t7f9KgdTkfuyMoykM9NYp1/img.png)
equals() 두 객체의 동등성을 비교하기 위해 오버라이딩하는 메서드 동등성 : 두 객체가 동등한 정보를 가지고 있는 지(equals) 동일성 : 두 객체가 동일한 객체인지 (==) Object 클래스의 equals()는 기본적으로 동일성을 비교하기 때문에, 객체의 동등성을 비교하려면 equals() 메서드를 재정의해야 함 hashCode() Object 클래스의 hashCode() 메서드는 네이티브 메서드로, 객체의 주소 값을 이용하여 생성한 해시 코드를 반환 주의할 점은, 객체의 주소 값을 이용하는 것이지 주소 값 자체가 해시 코드 값이 아니라는 점이다. equals() 메서드 오버라이딩 시 주의사항 Object 클래스의 hashCode() 메서드 주석을 보면, 빨간 글씨로 equals() 메서드를..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/dGklq0/btsFnXiu8SG/KNpjk3cDSXyDyKZjOSk4gk/img.png)
인트로 Offset 페이징과 No-Offset 페이징의 성능을 비교하기 위해 더미 데이터를 추가하던 중, 호기심이 생겨 다양한 방식으로 적재 속도를 비교해 보았습니다. 실행 환경 PC : Apple M2 Pro (저전력모드) Tool : IntelliJ Datagrip Docker : MySQL 8.0.31 더미 데이터 1,000만 건의 Article 레코드 외래키 제약조건 1개, Check 제약조건 2개가 존재 성능 측정 1. 개별 Insert from datetime import datetime #SQL 파일 생성 sql_file_path = 'individual_insert.sql' with open(sql_file_path, 'w') as sql_file: # 1부터 10000000까지의 데이터 ..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/Ybdpi/btsFsZTHLKi/0qKFXkBvkdHGi7gYCZwuZk/img.png)
인생 처음으로 오픈소스 프로젝트에 기여를 했다! 🎉 주석에 있던 오타를 정정한 게 전부였지만, 오픈소스 기여 경험이 없었고 그 대상도 자바 개발자라면 한번쯤 들어본 AssertJ 라이브러리여서 몹시 두근거렸다 ❤️🔥 검토되는 데 오래 걸릴 줄 알았는데, 잠깐 사이에 AssertJ 레포지토리에 내 아이디가 떠있어서 정말 신기했다 😁 예전에 지나가다 본 블로그에서 대형 프로젝트에 이런 식으로 기여했다는 글을 보고 정말 부러웠는데, 나도 우연히 발견한 오타로 오픈소스 프로젝트에 기여해 볼 수 있어서 참 즐거웠다 :) 정말 사소한 기여였지만, 오픈소스 기여의 첫걸음을 떼었기에 나에게는 의미가 큰 경험이었다 👊
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/ba8ygP/btsFkHAV4Cn/Uvvl9rgGtUkEKD08afNvd1/img.png)
문제 상황테스트 코드를 작성하던 중, 실제 엔티티의 생성 시간과 DB에 저장된 값이 일치하지 않는 오류가 발생했습니다.로그를 확인해 보니, DB에 저장된 값은 22초인데 실제 생성 시간은 21.805265로 약 0.2초의 오차가 있었습니다.문제 원인JPA Auditing에서 LocalDateTime은 기본적으로 MySQL의 datetime과 매칭되는데, 이는 실제로 datetime(0)에 해당합니다.여기서 0은 반올림 자리수를 나타내는 값으로, 소수점 첫번째 자리에서의 반올림을 의미합니다.이로 인해, MySQL에 21.805265 값이 전달되어도 22.0으로 반올림 되어 오차가 발생하게 됩니다.해결 방법1. datetime 반올림 자릿수 변경datetime의 반올림 자리수를 변경하여 JPA Auditin..
문제 링크 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요. programmers.co.kr import java.util.LinkedList; import java.util.Queue; import java.util.Stack; import java.util.stream.Collectors; import java.util.stream.IntStream; class Solution { public int solution(int[] orders) { int answer = 0; Queue mainContainer = IntStream.rangeClosed(1, orders.length).bo..