dev 12

원자성 보장 코드에서? DB에서?

🍎 마주한 문제에서 데이터의 원자성을 어느 곳에서 관리하면 좋을지 고민하게 되어 정리합니다.🍏 문제 상황✓ 공공데이터 API에서 여러 건의 원시 데이터를 조회한 후, 이를 내부 비즈니스에 활용할 수 있도록 정제하여 저장해야 했다. 이 과정에서 데이터를 여러 개의 테이블에 나누어 저장해야 하는 상황이 발생 ✓ 처음에는 Bulk Insert를 사용하여 성능을 최적화하는 방안을 고려했지만, 하나의 테이블이 아닌 여러 개의 테이블에 데이터를 삽입해야 하기 때문에 Bulk Insert를 적용할 수 없었다. ✓ 결국 데이터를 한 건씩 개별적으로 저장하는 방식이 필요했는데 중간에 데이터 삽입이 실패할 경우 어떻게 처리할 것인가라는 고민이 생겼다. ✓ 데이터 정제 및 저장 로직이 일부만 실행되고 중단될 경우, 데이..

Dev 2025.03.18

Nginx Basic

🍎 Nginx에 관한 기본과 사용 방법을 정리합니다.❓ Nginx는 어떤 도구인가요?-> 공식 문서 출처에 의하면 NGINX(엔진 X)는 HTTP 웹 서버, 리버스 프락시, 콘텐츠 캐시, 로드 밸런서, TCP/UDP 프락시 서버 및 메일 프락시 서버입니다. ❓ 왜 사용하나요?- 어떤 불편함을 해결하기 위해 Nginx라는 도구가 탄생했는지 찾아본다면 사용 이유를 알 수 있습니다.- Nginx 이전 시중엔 Apache HTTP Server(Web Server)를 사용했고 Apache HTTP Server가 가진 몇 가지 한계를 극복하기 위해 Ningx가 등장했습니다. - 초기 웹 서버들은 클라이언트 요청이 증가할 때마다 성능이 급격히 떨어지는 문제가 있었고 특히 Apache의 프로세스 기반 아키텍처가 대량..

TIL 2025.03.06

원시 데이터가 DB에 존재하는 모습

🍎 원시 데이터(이하 Raw Data)를 내부 DB에 저장할 때 어떤 모습으로 담겨야 하는지 생각한 부분을 정리합니다.- 가공되기 전 데이터인 Raw Data는 비즈니스에 사용되기 전까지 한 번 이상의 가공을 거쳐야 하는 데이터입니다.- Raw Data가 중요한 이유는 가공되지 않기 때문에 중요하다고 생각합니다. 가공된 후 다양한 모습으로 비즈니스 데이터가 될 수 있으며 혹시나 가공 처리 과정에 오류가 있어 오염이 될 경우, 근원 데이터로 오류 추적, 개선을 할 수 있기 때문입니다. ❓ 어떻게 Raw Data를 저장해야 할까?- Raw Data의 모습은 규정할 수 없이 다양한 형태로 존재합니다. 외부 API에서 제공하는 데이터가 Raw Data가 될 수 있고 운영되는 서비스의 사용자 활동 이력도 Raw..

TIL 2025.03.05

[Tip] @Scheduled 와 Cron 어떤 것을 선택해야할까?

🍎 시스템 내부에서 반복적인 작업을 처리해 줄 도구를 고를 때 어떤 부분을 고려하면 좋을 지 정리합니다.🍏 의사 결정이 필요하게 된 이유- 공공데이터를 3분에 한 번 API 호출하여 갱신된 Raw Data를 가져와야 하는 요구 사항 존재- 반복 요청을 OpenAPI Server에 전달해야하는데 어떤 도구를 사용해야할지 고민 🍏 다룰 수 있는 도구 중 Schedule 기능을 제공해주는 도구- Spring Scheduler (@Scheduled)@Serviceclass TestService { @Scheduled(cron = "0 */3 * * * *") // 매 3분마다 실행 (초, 분, 시, 일, 월, 요일) fun executeTask() { println("TestServic..

Dev 2025.03.04

DB CRUD 작업의 비용 분석

🍎 애플리케이션 개발에서 흔히 당연시되는 영속 계층(RDB)의 CRUD 작업에 대해 더 깊이 이해하고 싶어, 그 비용과 효율성에 대해 정리한 글입니다.❗️ CRUD 작업의 효율성을 논하기 전에, ‘Create’와 ‘Read’가 각각 ‘Insert’와 ‘Select’와 어떻게 다른지 정리해 보겠습니다. 단어가 갖고 있는 의미를 명확하게 정의해 혼란을 없애기 위함입니다.‘Create’와 ‘Read’는 데이터 조작의 추상적인 개념을 나타냅니다.‘Insert’와 ‘Select’는 추상적인 개념을 SQL 명령어로 구체화한 것입니다.- 이 후 글의 진행에선 구체화한 명령어인 SQL의 ‘Insert‘와 ‘Select‘를 사용하겠습니다.(참고로 Update와 Delete 역시 마찬가지입니다. 쓰인 단어의 모양이 동일..

Dev 2024.09.15

시간값 발행 주체는 누가 되어야 하는가?

🍎 개발에 있어 시간 값을 정확하게 다루는 것은 아무리 강조해도 지나치지 않습니다.- 한 예로 시간 값을 정확하게 관리하지 않으면 데이터의 일관성을 유지하기 어려워질 수 있고 이는 예상치 못한 상황을 발생시키거나 시스템의 신뢰성을 저하시킬 수 있습니다.🍎 상황- 포춘 쿠키 이벤트 요구 사항을 해결하는 중 "하루 한 번의 포춘 쿠키 메시지만 얻을 수 있다"는 세부 요구사항을 해결하기 위해 Application Layer에서 Instant.now()를 사용해 시간값을 발행해 사용 💭 생각하게 된 이유- 위와 같이 Application Layer에서 시간값을 발행한 이유는 아래 두 이유 존재시간값을 외부에서 주입해 사용함으로 시간값이 포함된 로직 테스트 가능하다고 판단23:59:59에 발생한 API가 D..

Dev 2024.09.03

[설계] 순서 결정의 책임을 결정하는 방법

🍎 클라이언트와 서버 간 데이터를 주고받을 때, 데이터 순서 정렬이 필요한 상황에서 고려할 사항들을 정리합니다.🍏 상황 설명- Json Format으로 조회한 제품 리스트의 순서 정렬에 관한 요구사항을 해결 중 정렬의 관한 책임을 서버에 두기로 생각- 생각의 근거는 순서를 정렬하는 것이 비즈니스 로직에 포함되어야 한다고 판단했고 클라이언트에선 서버에 요청값을{ “order” : “ASCENDING” }- 위와 같이 넘겨 정렬이 완료된 값만 받아오는 것이 합리적이라고 생각📝 놓친 부분- 첫 번째 이유는 서버가 정렬하는 것이 비즈니스 로직이라고 판단했는데 이를 잘못 판단비즈니스 로직이라는 것은 운영하는 서비스 내부에 존재하며 다른 도메인(혹은 서비스)에선 적용되지 않은 로직"정렬" 기능은 내가 속한 조..

Dev 2024.09.03

[설계] 설계 시 우선되어야 할 계층 구조에 대하여

🍎 패키지 계층 구조와 클래스 계층 구조 중 어느 것을 우선으로 생각해야 하는지 정리합니다.- 애플리케이션 요구사항을 받아 코드 작성에 들어가기 전에, 당연하게 생각했던 개발팀 내부의 패키지 계층 구조와 클래스 계층 구조를 다시금 낯설게 바라보게 되었습니다.- 패키지 계층 구조가 아직 정해지지 않은 상황, 즉 백지 상태에서 설계를 시작해야 할 때, 무엇을 우선적으로 고려해야 할지 고민해 보았습니다.🍏 결론- 결론부터 이야기하자면 패키지 계층 구조 설계보다 클래스 계층 구조 설계가 먼저 선행되어야 하는 것이 좋습니다.- 이유는 하나의 패키지 안에 관계를 맺고 있는 클래스들이 존재한다 하더라도 클래스의 계층 구조는 깨지지 않습니다.- 패키지 계층 구조는 단지 클래스들을 보다 보기 쉽게 계층을 나눠 구성하..

Dev 2024.09.03

[Kotlin] reified, inline 그리고 Generic

🍎 Kotlin에서 제공하는 `reified`, `inline` 키워드의 기능을 정리합니다. 키워드들이 무엇인지, 그리고 어떤 상황에서 사용되는지 알아보겠습니다.🍎 `reified`와 `inline`의 사전적 의미- `reified`는 reify의 과거형으로 사전적 의미로 "개념이나 아이디어를 구체적이고 실질적인 형태로 변환하다"라는 의미를 갖습니다.- `inline`은 "줄지어 있는, 일렬로 나란히 있는"을 의미하며 컴퓨터 용어로는 코드를 다른 코드 내에 직접 삽입하는 방식을 의미합니다.🍏 예를 통한 `refied` 이해 - `reified`를 알기 위해선 우선 `inline` 키워드를 알아야 합니다.fun printYourName(operation: () -> Any) { println(..

Dev 2024.09.03

[Kotlin] Any, *, Generic의 공통점과 차이점

🍎 Kotlin 환경에서 Type에 관련해 제공되는 기능 Any, *, Generic을 이해하기 위해 정리한 글🍎 공통점- Any, *, Generic은 Kotlin 환경에서 특정 타입에 구애받지 않고 다양한 타입에 대해 작업할 수 있는 유연성을 제공합니다.🍎 차이점Any, *, Generic은 모두 타입 시스템에서 유연성을 제공하는 역할을 하지만, 각각의 사용 목적과 상황이 다릅니다. 각 요소의 특징을 살펴보면 어떤 상황에서 어떤 타입을 사용하는 것이 적절한지 더 잘 이해할 수 있을 것입니다. 🍏 Any- Any는 모든 타입의 최상위 타입입니다. 모든 Kotlin 타입은 Any 타입을 상속합니다.- Any는 Java의 Object와 유사한 역할을 수행합니다.- 모든 값이 Any Type으로 취급..

Dev 2024.09.01