-
자바 코드는 JVM에서 어떻게 실행될까?
자바를 처음 배울 때 가장 자주 듣는 말은 "Write Once, Run Anywhere"이다. 그런데 이 말은 자바 코드가 곧바로 모든 운영체제에서 실행된다는 뜻은 아니다. 자바 소스 코드는 먼저 JVM이 이해할 수 있는 바이트코드 로 컴파일되고,...
/ 11 min readengineering backend -
시스템 규모를 가정하고 추정하기
규모 추정은 시스템 디자인의 일부분이라고 볼 수 있다. 이 시스템 디자인은 소프트웨어 시스템의 구조를 계획하고 설계하는 과정이다. 이 과정은 시스템의 요구사항을 분석하고 최적의 솔루션을 설계하여 시스템이 효울적이고 확장 가능하며 유지관리가 용이하게 만...
/ 5 min readengineering backend -
서킷 브레이커을 사용헌 Redis 장애 전파 막기
운영 도중 레디스에 장애가 발생해 레디스에 의존하는 서비스의 특정 API가 마비되는 현상이 발견되었다. 현재 레디스는 여러 가지 용도로 사용이 되고 있는데 캐싱 용도로 사용되고 있는 레디스에서 네트워크 장애가 발생했고 그로 인해 레디스를 통해 캐시를...
/ 10 min readengineering backend -
JVM은 컴파일러일까, 인터프리터일까?
컴파일러 방식 컴파일러 방식은 고급언어로 작성된 프로그램을 목적 프로그램으로 번환후 링킹작업을 통해 실행파일을 생성한다. 기계어 번역과정에서 많은 메모리를 사용한다. 초기 스캔시간은 오래 걸리지만 한번 실행 파일이 만들어지고 나면 실행속도가 빠르다....
/ 7 min readengineering backend -
모집 마감일에 몰리는 지원서 제출 동시성 문제 해결하기
JECT 서비스는 모집 기간마다 지원자들의 지원서 데이터를 실시간으로 수신받아 관리합니다. 특히 지원서 제출은 모집 마감 직전 짧은 시간에 많은 요청이 몰리는 성향을 가지고 있다. 문제 상황 모집 마감 직전 등 짧은 시간에 동일 사용자가 제출 버튼을...
/ 8 min readengineering backend -
나는 항상 모니터링할 수 없다
일전에 장애 대응을 위해 서버에 유지보수를 위해 모니터링을 도입했다. 운영 중인 서비스 특성상 기능 개발, 버그 대응, 배포 등 여러 작업을 동시에 처리해야 했다. 그 과정에서 지표를 일일이 지속적으로 확인하는 모니터링 방식에는 분명한 한계가 있었다....
/ 6 min readengineering devops -
무질서한 스키마를 통제하기
현재 진행하고 있는 프로젝트 기존에는 생산성과 편의성을 위해 ddl auto=create/update 옵션을 사용해 스키마를 관리하고 있었다. 하지만 이 방식은 프로젝트가 커지고, 환경이 분리되기 시작하면서 문제가 드러났다. 개발/운영 DB 스키마가...
/ 5 min readengineering backend database -
배포했더니 서버가 죽을 뻔 했던 건에 대하여
서버가 응답이 없다 운영 서버(t3.small)에 Docker 기반 무중단 배포를 시도하는 과정에서, 신규 컨테이너와 기존 컨테이너가 공존하는 시점에 메모리와 CPU 사용량이 임계치를 초과하는 현상 발생하고 있었다. 이로인해 배포 진행 중 SSH 접속...
/ 5 min readengineering backend devops -
Spring에서 Event 처리하기
스프링 이벤트가 왜 필요할까? 회원가입하기 메서드를 예시로 들어보자. 과연 이걸로 끝이 날까? 이메일만 있을까? 카카오톡으로도 보낼 수 있을 것이고, 회원가입 시 포인트를 지급하는 정책이 있을 수도 있을 것이다. 이런 일이 비일비재할 것이다. 여기서...
/ 6 min readengineering backend -
좋은 API 설계하기
팀 프로젝트를 하다가 다음과 같은 요청을 받았다. 여러 번 요청을 보내면 네트워크 리소스 비용이 더 많이 소모되니까. 그냥 한 번에 보내주세요. 이 요청을 받으면서 다음과 같은 생각이 들었다. “그래도 되나?” “괜찮아 보이기도 하고..” “뭔가 안...
/ 5 min readengineering backend -
도메인 동상이몽(同床異夢)
이벤트 스토밍(Event Storming)이라는 단어는 익숙치 않을 것이다. 그럼 브레인 스토밍(Brain Storming)은 어떠한가? 상대적으로 더 익숙할 것이다. 브레인 스토밍은 “머릿속 아이디어를 스토밍으로 쏟아낸다.”라고 표현할 수 있다. 그...
/ 5 min readengineering backend communication -
리눅스와 친한 척 해보기
리눅스 리눅스는 리눅스 커널을 기반의 유닉스 계열의 오픈 소스 운영체제이다. 오픈소스이다보니 자신들의 목적에 맞게 자유롭게 커스텀마이징된 다양한 버전들이 있다. Ubuntu, Debian, CentOS, Fedora 등이 이에 속하고 이들을 리눅스 배...
/ 14 min readengineering -
함께 자라기
왜 '함께' 자라야 할까? 많은 개발자가 성장을 고민한다. 더 나은 코드를 짜고 싶고, 더 어려운 문제를 해결하고 싶어 한다. 그런데 흔히 성장을 혼자만의 수련으로 생각하곤 한다. "내가 실력을 쌓아서 팀에 기여해야지." 훌륭한 태도지만, 여기엔 한...
/ 4 min readengineering communication -
이 이름(Naming)이 최선인가?
개발자에게 가장 어려운 일 중 하나는 단연 이름 짓기(Naming)일 것이다. 코드를 작성하다 보면 로직을 짜는 시간보다 변수나 함수 이름을 고민하는 데 더 많은 시간을 쏟곤 한다. "이게 최선일까?" 고민하다 결국 모호한 이름을 짓고, 나중에 다시...
/ 5 min readengineering backend - Engineering
Utility Class에서 생성자를 private으로 선언해야 하는 이유
개발을 하다 보면 Utils , Helper , Constants 등과 같이 객체를 생성하지 않고 정적인 메서드나 상수를 모아두는 유틸리티 클래스(Utility Class) 를 사용하는 경우가 있다. 그런데 이때 흔히 저지르는 실수 중 하나가 바로 이...
/ 4 min readengineering backend - Engineering
GitHub Actions에서 Private 인스턴스로 점프하기
진행하고 있는 프로젝트에서 보안 이슈가 빈번히 발생했고, 이를 해결하기 위한 방안 중 하나로 인스턴스들을 Private Subnet으로 숨길 필요성이 생겼다. 그래서 모든 인스턴스들을 Private Instance로 변경하고, SSH 접근을 위해 Ba...
/ 5 min readengineering devops -
readObject 메서드는 방어적으로 작성하라
방어적 복사를 사용하는 불변 클래스 아이템 50에서는 불변식을 지키고 불변을 유지한 날짜 클래스를 만들기 위해, 생성자와 접근자(getter)에서 Data 객체를 방어적으로 복사하도록 했다. 다음이 그 클래스의 모습니다. 이 클래스를 직렬화를 하고자...
/ 10 min readengineering backend -
과도한 동기화는 피하라
이번 아이템에서는 동기화를 과도하게 했을 때의 피해에 대해 알아본다. 외계인 메서드 동기화된 영역 안에서는 재정의할 수 있는 메서드를 호출하거나 클라이언트가 넘겨준 함수 객체를 호출하는 경우, 클래스 관점에서는 이런 메서드는 모두 바깥 세상에서 온 외...
/ 7 min readengineering backend -
디렉토리 스캔 공격은 어떻게 대응해야 할까?
최근 개발 중인 서버에 무수히 많은 에러 로그와 트래픽이 발생하는 이슈가 발생했다. 이는 찾아보니 디렉토리 스캔 공격이었고, 이 글에서는 이러한 이슈를 어떻게 대응했는지에 대해 기록하고자 한다. 그리고 이를 통해 다른 개발자들이 비슷한 이슈에 대해 대...
/ 6 min readengineering -
복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라
자바는 문제 상황을 알리는 타입(throwable)으로 검사 예외, 런타임 예외, 에러 이렇게 세 가지를 제공하고 있다. 이 글에서는 이러한 검사 예외, 런타임 예외, 에러가 무엇이고 언제 사용해야 하는지 알아본다. 검사 예외 (Checked Exce...
/ 2 min readengineering backend -
다른 타입이 적절하다면 문자열 사용을 피하라
문자열(String)은 텍스트를 표현하도록 설계되었다. 자바에서 문자열은 텍스트를 표현하도록 설계되었지만, 원래 의도하지 않은 용도로도 쓰이는 경향이 있다. 이번 주제에서는 문자열을 쓰지 않아야 할 사례를 다룬다. 문자열은 다른 값 타입을 대신하기에...
/ 4 min readengineering backend -
정확한 답이 필요하다면 float와 double은 피하라
대부분 소수점을 표현하고자 할 때는 int나 long을 사용한다. float와 double 타입은 넓은 범위의 수를 빠르게 정밀한 '근사치'로 계산하도록 세심하게 설계되었다. 따라서 float와 double 타입은 특히 금융 관련 계산과 같은 정확한...
/ 3 min readengineering backend -
라이브러리를 익히고 사용하라
라이브러리에 익숙치 않으면 발생할 수 있는 문제 아래는 무작위 수를 백만 개를 생성한 다음, 그중 중간 값보다 작은 게 몇 개인지를 출력하는 코드다. 괜찮은 듯 보여도 적지않은 문제를 내포하고 있다. n이 그리 크지 않은 2의 제곱수라면 얼마 지나지...
/ 1 min readengineering backend -
적시에 방어적 복사본을 만들라
자바는 안전한 언어다 자바는 네이티브 메서드를 사용하지 않기 때문에 버퍼 오버런, 배열 오버런, 와일드 포인터 같은 메모리 충돌 오류에서 비교적 안전하다. 또한 자바로 작성한 클래스는 시스템의 다른 부분에서 무슨 짓을 하든 기본적으로 불변성을 유지할...
/ 6 min readengineering backend -
스트림은 주의해서 사용하라
스트림이란? 스트림 API는 다야의 데이터 처리 작업(순차적이든 병렬적이든)을 돕고자 Java8부터 추가되었다. 여기서 이 API가 제공하는 핵심 추상 개념은 다음 두 가지다. 데이터 원소의 유한 혹은 무한 시퀀스를 뜻하는 스트림 원소들로 수행하는 연...
/ 7 min readengineering backend -
정의하려는 것이 타입이라면 마커 인터페이스를 사용하라
마커 인터페이스 아무 메서드도 담고 있지 않고, 단지 자신을 구현하는 클래스가 특정 속성을 표시해주는 인터페이스를 마커 인터페이스(marker interface)라고 한다. Serializable 인터페이스가 대표적인 마커 인터페이스이다. 이 인터페이...
/ 2 min readengineering backend -
DBMS는 트랜잭션을 어떻게 관리할까?
트랜잭션 관리는 DBMS가 제공하는 핵심 기능 중 하나로, 데이터베이스 시스템에서 신뢰성을 보장하는 필수 요소이다. DBMS 사용자들에게는 마치 공기처럼 당연한 존재이지만, 내부적으로는 매우 정교한 매커니즘이 작동하고 있다. 이 글에서는 트랜잭션을 커...
/ 23 min readengineering backend -
int 상수 대신 열거 타입을 사용하라
열거 타입 일정 개수의 상수 값을 정의한 다음, 그외의 값은 허용하지 않는 타입 정수 열거 패턴의 단점 기존 정수 열거 패턴(int enum pattern)은 타입 안전을 보장할 방법이 없고 표현력이 좋지 않다 는 단점이 존재한다. 위 코드에서 APP...
/ 10 min readengineering backend -
인덱스만 사용하면 성능이 향상될까?
DBMS에는 저장되어 있는 데이터를 효율적으로 검색할 수 있게 해주는 인덱스가 있다. 우리가 보통 애플리케이션의 백엔드 성능을 높이려고 종종 실행하는 SQL 튜닝은 이 인덱스를 SQL이 DBMS에서 최대한 활용할 수 있도록 SQL을 수정하는 것이라고...
/ 7 min readengineering -
제네릭과 가변인수를 함께 쓸 때는 신중하라
가변인수와 제네릭이 함께 사용될 때의 허점 가변인수(varargs) 메서드에 넘기는 인수의 개수를 클라이언트가 조절할 수 있게 해준다. 가변인수 메서드를 호출하면 가변인수를 담기 위한 배열이 자동으로 하나 만들어지게 된다. 이 배열은 내부로 감춰야 하...
/ 6 min readengineering backend -
인터페이스는 구현하는 쪽을 생각해 설계하라
자바 8 이전에는 기존 인터페이스에 메서드르 추하려면 기존 구현체를 수정해야 했고, 이를 안할 시 컴파일 오률를 일으켰다. 자바 8에서는 디폴트 메서드라는 기능을 도입하면서 인터페이스에 새로운 메서드를 추가할 수 있게 되었지만, 모든 상황에 대비하여...
/ 2 min readengineering backend -
클래스와 멤버의 접근 권한을 최소화하라
잘 설계된 컴포넌트 책에서는 잘 설계된 컴포넌트에 대해 다음과 같이 설명한다. 클래스 내부 데이터와 내부 구현 정보를 외부로 부터 잘 숨겨야 한다. API를 통해서만 다른 컴포넌트와 소통해야 하며, 내부 동작 방식에 개의치 않아야 한다. 이는 캡슐화(...
/ 5 min readengineering backend -
public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라
캡슐화의 이점을 제공하지 못하는 클래스 위와 같은 코드는 데이터 필드에 대한 직접적인 접근을 허용한다. 이러한 코드는 캡슐화의 이점을 제공하지 못한다.(아이템15와 이어지는 맥락) API를 수정하지 않고는 내부 표현을 바꿀 수 없다. public 필드...
/ 6 min readengineering backend -
자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
많은 경우의 클래스들은 하나 이상의 리소스에 의존하는 양상을 띈다. 알림을 보내는 NotificationService 클래스와 이메일을 보내는 EmailSender 클래스가 있다고 가정해보자. NotificationService 는 EmailSende...
/ 9 min readengineering backend - Engineering
자바의 문자열 최적화(String Optimization)
자바 컴파일러는 다음과 같이 문자열을 처리하는 코드를 만나면, 이를 최적화하여 하나의 문자열로 만들어준다. String literal 결합 최적화 위 코드는 str1 과 str2 를 합쳐 str3 에 저장하는 코드이다. 하지만 자바 컴파일러는 이 코드...
/ 3 min readengineering backend - Engineering
기본형(Primitive)과 참조형(Reference)
기본형(Primitive)과 참조형(Reference) 자바의 데이터 타입은 크게 기본형(Primitive)과 참조형(Reference)으로 나눌 수 있다. 기본형은 정수, 실수, 문자, 논리 등의 값을 저장하는 데이터 타입이고, 참조형은 객체의 주소...
/ 3 min readengineering backend - Engineering
동일성(Identity)와 동등성(Equality)
동일성와 동등성 자바에서는 두 객체가 같은지 비교하는 두 가지 방법이 있다. 동일성(Identity) == 연산자를 사용하여 두 객체의 주소값을 비교해서 동일한 객체를 참조하는지 확인 동등성(Equality) equals() 메서드를 사용하여 두 객체...
/ 5 min readengineering backend - Engineering
자바 Object 클래스
Object 클래스를 알아가기 전에 먼저 Object 클래스가 속한 패키지에 대해 알아야 한다. Object 클래스가 속한 패키지는 java.lang 패키지에 포함되어 있다. java.lang 패키지 소개 자바가 기본으로 제공하는 라이브러리(클래스 모...
/ 10 min readengineering backend - Engineering
SynchronizedMap와 ConcurrentHashMap
SynchronizedMap와 ConcurrentHashMap SynchronizedMap 과 ConcurrentHashMap 은 둘 다 멀티 스레드 환경에서 사용할 수 있는 Map 구현체이다. 하지만 두 클래스는 서로 다른 방식으로 동기화를 제공한다...
/ 4 min readengineering backend - Engineering
throw와 throws 그리고 Chained Exception
자바에서 예외처리는 오류를 예측하고 이에 대응하여 프로그램의 안정성을 높일 뿐만 아니라, 상황에 따라서 단순히 발생한 오류를 잡아내는 것을 넘어, 필요에 따라 예외를 발생시키거나 떠넘기고, 예외를 다른 예외로 감싸 처리하는 등 다양한 방법을 유현하게...
/ 8 min readengineering backend - Engineering
자바 문자열(String)
자바에서 문자를 다루는 대표적인 타입은 char 와 String 이렇게 2가지가 있다. 기본형인 char 는 문자 하나를 다루는데 사용되고, char 를 사용해서 여러 문자 즉 문자열을 다루기 위해선 char[] 을 사용해야 한다. 하지만 이렇게 ch...
/ 7 min readengineering backend - Engineering
System.out.println()를 사용한 로깅을 피해야 하는 이유
프로그래밍을 처음 배우면 System.out.println("Hello World"); 와 같이 콘솔에 출력을 시도하게 된다. 콘솔 창에 "프로그램이 정상적으로 동작함을 확인하는 과정은 모든 개발자가 겪는 경험일 것이다. 우리는 원하는 기능을 구현한...
/ 4 min readengineering backend - Engineering
자바 에러(Error)와 예외처리(Exception)
프로그램에서 오류가 발생하면 시스템 레벨에서 문제를 일으켜 원치 않는 버그를 유발하거나, 심각한 경우 프로그램을 강제로 종료시키기도 한다. 이러한 오류의 원인은 다양하며, 내부적으로 프로그램 설계 로직의 허점에서 비롯될 수 있고, 외부적으로는 프로그램...
/ 6 min readengineering backend - Engineering
자바 람다(Lambda)와 스트림(Stream)
람다 표현식(Lambda Expression) 람다 표현식(Lambda Expression)은 함수형 프로그래밍을 위해 자바에서 제공하는 간결한 함수식으로, 자바의 메서드를 간단하게 표현할 수 있는 방법이다. 기존 자바에서는 메서드를 표현하려면 별도의...
/ 10 min readengineering backend