운영 서버의 데이터베이스가 사라졌다 – Binary Log 만으로 4시간 만에 복구하기
·
Project Logs/DashHub
운영 DB가 사라졌다일 평균 사용자 93명에 달하는 대시허브는 올해 1월 12일 큰 위기를 맞이했다.홈 서버 위에서 돌던 운영 DB 가 어느 날 갑자기 `Empty set` 이 되었기 때문이다. 백업도 없던 상태에서 초보 개발자가 어떻게 사고를 인지하고 복구하였는지, 그날 밤 있었던 일을 기록하고자 한다.19시 38분 – 여느 날과 다름없는 평범한 배포였다`feature/effect` 브랜치를 `main` 에 병합했다. 상점에 신규 아이템들을 띄우는 작은 업데이트였다. 참고로 대시허브는 `GitHub Actions` 를 사용한다. 이미지를 푸시하면 Watchtower 가 30초 간격으로 감지해 컨테이너를 새 이미지로 교체하는 CD 파이프라인이 걸려 있다. 배포 직후 사이드 위젯이 정상으로 뜨는 것을 확인..
Naive한 MyBatis 구조를 리팩토링하자
·
Project Logs/DashHub
들어가며Naive한 MyBatis 구조라는 표현은, 기능 구현에는 성공했지만 아키텍처적인 고민이나 안전장치 없이 가장 단순하고 일차원적인 방식으로 MyBatis를 사용한 형태를 의미한다. 소프트웨어 공학에서 Naive하다는 것은 "순진한", "경험이 부족한"이라는 뜻으로, 보통 돌아가긴 하는데 확장성과 유지보수성을 고려하지 않은 초기 상태를 가리킬 때 쓴다. 오늘은 일반적인 초급 프로젝트에서 볼 수 있는 Naive한 구조의 2가지 특징을 알아보는 시간이 되겠다. JPA로 시작한 나에게 MyBatis란일단 나의 Dash 프로젝트가 어쩌다 Naive하게 되었는지에 대해 언급해야 할 듯하다. 관통 프로젝트를 시작하며 전달받은 일종의 요구사항이 있는데, 그게 바로 "MyBatis와 Spring을 연동하여 표준 ..
제네릭의 탄생 배경과 타입 소거의 이면
·
Engineering Notes/Java & Spring
들어가며지난 28일, 자바 정규 수업을 들었다. 제네릭과 관련한 내용이었는데, 제네릭 사용 시 Type Argument를 정확히 일치시켜야 한다고 하더라. 2주라는 짧은 시간 안에 자바를 가르치다 보니 어쩔 수 없는 부분이었겠지만, 아쉽게도 '왜?'는 빠져있었다. 제네릭의 탄생제네릭이 도입되기 이전 시대에서, List와 Map 같은 자바 컬렉션은 모든 종류의 객체를 담을 수 있는 Object 타입으로 설계되었다. Object 클래스는 최상위 클래스로서, 언뜻 보면 유연하지만 그만큼 치명적인 단점을 안고 있었다. 예를 들어 아래와 같은 원시 타입 리스트가 있다고 하자.List items = new ArrayList();items.add("ssafy");items.add(14);현재 리스트에는 문자열도, 정..
동적 배열의 재할당과 힙 오버플로우
·
Engineering Notes/Java & Spring
동적 배열과 재할당자바에서 ArrayList는 대표적인 동적 배열이다. 내부적으로는 일반 배열을 사용하지만, 요소가 추가되거나 제거될 때 필요에 따라 배열의 크기를 자동으로 조절한다. 이러한 특징으로 개발자가 배열의 크기를 정할 필요 없이 유연하게 사용 가능하다는 장점이 있다.내부적으로는 용량 부족을 감지하고 현재 용량보다 더 큰 (일반적으로 1.5배) 배열을 생성해 모든 요소를 복사한다. 이후 새로운 배열을 참조하도록 변경하는 과정을 거친다. ArrayList의 경우, 배열의 인덱스는 int 타입으로 관리된다. int 타입의 최댓값은 2^31 - 1이니, 이론적으로는 약 21억 개의 요소를 가질 수 있다고 판단하기 마땅하다. 그러니 실제로 21억 개의 요소를 담아보자.import java.util.*;..
당신의 서비스는 "객체 지향"인가?
·
Engineering Notes/Java & Spring
싱글톤 패턴의 출현설계를 하다 보면, 애플리케이션 전반에 걸쳐 유일하게 존재해야 하는 객체가 있다. 싱글톤 패턴은 불필요한 리소스 낭비를 방지할 뿐 아니라, 관리를 용이하게 한다는 점에서 한때 각광받던 디자인 패턴 중 하나다. 어디서든 쉽게 접근해서 쓸 수 있다는 점도 개발자들에게 충분히 매력적으로 느껴졌을 것이다. 마치 전역 변수처럼 편의성을 제공하면서도 최소한의 객체 지향 원칙을 지키는 듯 보였으니 말이다. 하지만 싱글톤 패턴의 가장 고질적인 문제는 강한 결합에 있었다. 싱글톤에 의존하는 클래스들은 싱글톤의 존재를 직접적으로 알게 되고, 이는 곧 테스트를 매우 어렵게 만든다는 말과 같다. 싱글톤의 상태가 전역적으로 공유되기 때문에, 예측 불가능한 사이드 이펙트가 발생하기 쉬웠으며, 병렬 처리 환경에서..
개인 프로젝트인데 도커 왜 써?
·
Engineering Notes/DevOps & Infra
도커를 쓰는 이유일단 MySQL은 가장 보편적인 데이터베이스다. 그리고 운영체제에 맞춰 직접 설치해 사용하면 된다. 그럼에도 불구하고 도커를 사용하는 이유는, 그만큼 시스템 환경에 종속되어 다른 개발자와 동일한 환경을 맞추기 어렵기 때문이다. ..라고 지금까지는 얘기해 왔다. 그런데 한 가지 따져볼 게 있다. 그저 평범한 개인 프로젝트에 불과한데, 타 개발자와 공유할 일이 있을까? 있긴 한가? 없다면 왜 쓰지? 사실 도커를 사용하는 이유는 단순히 다른 개발자가 나와 환경을 맞추기 위해서가 아니다. 도커는 오직 나 혼자 개발하더라도, 내가 편하기 위해서 채택하는 것이다. 그리고 그 이유는 환경 관리에 있다. 만약 A 프로젝트는 MySQL 8.0이 필요한데, B 프로젝트는 MySQL 5.7이 필요하다면?만약..
협업을 위한 8가지
·
Reflections/Feedback
혼자 할 수 있는 건 한계가 있다- 잘하는 사람이 본인밖에 없다고 생각하며 혼자 독주하지 말자. 언제나 팀에게 진행상황을 공유하자.- 내가 잘하는 무언가에 심취하지 말자. 그들은 다른 분야에서 더 뛰어날 수 있다.협업은 목표를 공유하면서도 각자의 전문성을 더 잘 발휘할 수 있도록 서로 돕는 것이다. 개발은 코드로만 하는 게 아니다- 코드를 작성하지 않더라도 팀원과 함께 하는 모든 행위가 개발이고 비즈니스라는 점을 기억하자.내가 만드는 비즈니스의 가치를 높이기 위해 돕고 도움받아 문제를 해결하는 모든 과정 또한 개발이다. 문서화는 결코 기획 인원만의 업무가 아니다- 문서화의 중요성은 처음부터 나타나지 않는다. 처음에는 모두가 기억하기 때문이다.- 기획을 모르는 개발자는 개발자가 아니다. 언제나 구현 가능성..
Variable Hiding은 Overriding과 다르게 동작한다
·
Engineering Notes/Java & Spring
자바 상속과 관련하여과거, 김영한님의 자바 강의를 통해 상속의 개념과 다형성, 메서드 오버라이딩에 대해 학습했다. 비슷한 내용으로 글도 올렸었는데, 이번에 정보처리기사 실기를 벼락치기 하는 과정에서 무언가 착각을해도 단단히 착각했다는 것을 깨달았다. 자바에서는 상속 관계에 있는 클래스들 간에 이름이 같은 멤버가 있을 때, 변수 숨김 또는 메서드 오버라이딩이 동작하게 된다. 내가 착각하고 있던 부분은 변수 또한 메서드 오버라이딩처럼 동작할 거란 막연한 생각이었다. 아래 예시를 보자.public class Main { public static void main(String[] args) { Base a = new Derivate(); Derivate b = new Derivate(); ..