전체 글
JVM 구조 및 메모리 구조
JVM 이란 JVM(Java Virtual Machine)이란 Java 어플리케이션을 실행하는 프로그램입니다. JRE(Java Run Environment) 의 한 부분으로 JVM은 main 메서드를 java code 에서 실행시키는 주체입니다. 그리고 .java파일에서 컴파일된 결과인 .class 파일들을 load, link, initialize 합니다. Class Loader 클래스로더는 JVM 의 하위시스템으로 class 파일들을 메모리로 로드하는 역할입니다. Java 프로그램을 실행시킬 때 클래스로더를 통해 class 파일을 메모리로 로드합니다. Java 에서는 3가지 클래스로더들이 있습니다. Bootstrap ClassLoader Extension ClassLoader System ClassLo..
Selenide를 기반한 인수 테스트 도입기
대상독자 Template 기반 레거시 프로젝트에서도 테스트를 도입을 하고 싶은 분 시나리오 기반 인수테스트 작성 팁을 얻고 싶은 분 Selenide 설정이 궁금하신 분 도입 배경 이전까진 RESTful API 기반 프로젝트 상에서 통합/단위 테스트를 작성했었습니다. 하지만 레거시 프로젝트를 이번에 맡게 되면서 테스트를 포기할까 생각을 했지만 코드를 안정적으로 리팩토링하려면 결국 통합테스트가 있을 수 밖에 없다는 결론이 났습니다. 그리고 프로젝트를 맡은지 얼마되지 않다보니 여기를 변경하면 다른 곳에 기능이 영향이 가는 경우가 종종 발생하여 QA 시간이 긴 문제도 있었습니다. 팀 내에서 QA 시간 단축 및 빠른 레거시 코드 개선을 효과로 내세워 설득하여 2주정도 작업을 해서 도입할 수 있었습니다. 인수테스트..
데이터베이스 Lock
Lock Lock이란 트랜잭션이 동시에 실행되서 발생하는 동시성 문제를 해결하기 위해 동시성 제어를 위한 DB 의 장치이다. 레코드를 Lock 함으로써 다른 트랜잭션에서 업데이트는 못하고 읽기만 가능하다던가, 읽기도 불가능하게 하게 할 수도 있다. Lock 은 Shared Lock 과 Exclusive Lock 으로 나뉜다. Shared Lock Shared Lock은 해당 레코드를 조회만 타 트랜잭션에 허용하는 것이다. 이 락이 걸린 레코드 대상으로는 Select 만 할 수 있다. Update 하려면 Lock 이 해제될 때까지 기다려야 한다. 타 트랜잭션에서 Shared Lock 을 똑같이 설정할 수 있다. 하지만 Exclusive Lock 은 설정할 수 없다. SQL 문으로 다음과 같이 설정할 수 있..
트랜잭션 격리 수준
MySQL 기준으로 트랜잭션 격리 수준은 4단계가 있다. 격리 수준이 높은 순으로 정리. 1. SERIALIZABLE 가장 높은 격리 수준이다. 한 트랜잭션 내에서 언제든 반복해서 조회하더라도 동일한 결과가 나오는 repeatable read 가 보장된다. 트랜잭션이 실행되면서 실제 레코드에 바로 반영이 되지만서도, 언두로그에 트랜잭션 시작 전 레코드가 기록된다. 다른 트랜잭션에서는 백업된 언두로그를 읽는다. 단점은 단순한 Select 쿼리에서도 Shared Lock을 걸기 때문에 한번에 한 트랜잭션만 처리할 수 있어 한번에 많은 트랜잭션을 처리하지 못해 처리시간이 오래 걸릴 수 있습니다. 2. Repeatable Read 두번째로 높은 격리 수준이다. MySQL에서 기본으로 세팅된 격리 수준이다. 성능..
ACID 원칙
ACID 는 데이터베이스 무결성 보장하기 위해 트랜잭션의 설계 원칙이다. 'A' 는 Atomic 원자성으로 트랜잭션의 원자성이 보장되어야 한다. 트랜잭션 단위는 더이상 쪼개질 수 없는 작업 단위여야 한다. 트랜잭션이 중간에 중단되어도 트랜잭션 실행 전으로 DB 상태가 되어야 한다. 실행됐거나 안됐거나 2가지 결과 상태만 존재할 수 있어야 한다. 예를 들어, 새 유저를 추가하고 Role을 할당하는 트랜잭션이 있다고 가정한다. 실행 중에 새 유저만 추가되고 트랜잭션이 중단되었다면 새 유저 추가된 것은 rollback 되거나 DB에 반영되면 안된다. 반면 정상적으로 트랜잭션 완료되었다면 DB에 잘 반영되어야 한다. 'C'는 Consistency 일관성으로 트랜잭션 실행 전후로 DB 상태는 모순이 없어야 한다...
[실용주의 프로그래머] 5장. 구부러지거나 부러지거나
현대의 미친 듯이 빠른 변화 속도를 따라가려면 모든 수단을 동원하여 가능한 한 느슨하고 유연한 코드를 작성해야 한다. 되돌릴 수 있는 의사 결정. Topic 28. 결합도 줄이기 다리를 설계할 때는 그 형태가 바뀌지 않기를 바랄 것이다. 따라서 구조가 단단해야 한다. 하지만 소프트웨어를 설계할 때는 언젠가 형태를 바꾸려 할 것이다. 바라는 것이 정확히 반대다. 소프트웨어의 구조는 유연해야 한다. 묻지 말고 말하라 Tell, Don't Ask. TDA 객체 메서드를 설계할 때 Getter 를 무분별하게 사용해서 Ask 하지 말고 해당 객체가 역할(일)을 수행하는 메서드를 만들어서 Ask 하도록 하면 좋다. 왜냐하면 Getter 를 통해 사용하면 객체의 상태가 호출자 로직(역할)과 결합이 생긴다. 그러면 한..
[실용주의 프로그래머] Topic 27. 헤드라이트를 앞서가지 말라
언제나 신중하게 작은 단계들을 밟아라. 더 진행하기 전에 피드백을 확인하고 조정하라. 독립적으로 확증하거나 반증하는 것이라면 모두 피드백이다. 단위테스트는 직전에 고친 코드에 대한 피드백을 준다 사용자 데모 및 사용자와의 대화는 기능이나 사용성에 대한 피드백을 준다. 너무 큰 작업은 무엇일까? '예언'을 해야 하는 모든 작업이다. 자동차 헤드라이트로 비출 수 있는 거리에 한계가 있는 것처럼 우리도 한두 단계 앞의 미래만 내다볼 수 있다. 미래에 어떤 기술을 사용할지, 미래 사용자가 어떤 요구사항을 할지 예측해서 개발하는 것은 너무 앞서 나간 예시라고 설명하고 있다. 단위테스트와 실제 사용자 피드백을 통해 오버엔지니어링을 조절할 수 있다고 말하는 것 같다. 예측해서 코드를 짜지 말고 교체 가능한 코드를 작..
[실용주의 프로그래머] Topic 26. 리소스 사용의 균형
Tip40. 자신이 시작한 것은 자신이 끝내라 Tip41. 지역적으로 행동하라 "자신이 시작한 것은 자신이 끝내라" 팁이 가르쳐 주는 것은 이상적으로 말해서 리소스를 할당하는 루틴이 해제 역시 책임져야 한다는 것이다 public long readCustomer(File file){ try(Scanner sc = new Scanner(file)){ return sc.nextLong(); } catch (FileNotFoundException e) { throw new RuntimeException(e); } } try-with-resource 를 사용해서 리소스를 할당한 곳에서 해제하는 것이 좋다. 중첩할당 코드의 여러곳에서 동일한 구성의 리소스들을 할당하는 경우에는 언제나 같은 순서로 할당해야 교착 de..
웹브라우저 JS에서 비동기처리하는 방법
Javascript는 싱글 스레드입니다. 싱글 스레드라서 한 번에 하나의 일 밖에 처리하지 못하는 단점이 있습니다. 하지만 여러 일을 한번에 처리할 수 있는 멀티쓰레드 방식을 사용하면 데드락과 같은 동시성 문제에 대한 처리가 설계에 포함되어야 합니다. 설계가 복잡해지고 언어 구현이 어렵기 때문에 간단한 스크립트 목적에는 부합하지 않아 싱글 스레드를 채택한걸로 추측해봅니다. Why JavaScript is a single-thread language that can be non-blocking?, geeksforgeeks.org JS는 웹 브라우저에서 많이 사용되고 있습니다. JS를 사용하다보면 Ajax 통신, setTimeout 과 같은 Timer 기능과 같은 여러 비동기 기능들을 사용하곤 합니다. 싱글..
[MySQL] InnoDB 아키텍처
MySQL 스토리지 엔진 아키텍처 InnoDB는 MySQL에서 사용할 수 있 는 스토리지 엔진 중 거의 유일하게 레코드 기반의 잠금을 제공. 동시성 처리가 가능하고 안정적이며 성능이 뛰어나다 1. 프라이머리 키에 의한 클러스터링 InnoDB는 기본적으로 프라이머리 키를 기준으로 클러스터링되어 저장된다. 프라이머리 키 순서대로 디스크에 저장된다. 모든 세컨더리 인덱스는 레코드의 주소 대신 프 라이머리 키의 값을 논리적인 주소로 사용. 프라이머리 키가 클러스터링 인덱스이기 때문에 프라 이머리 키를 이용한 레인지 스캔은 상당히 빨리 처리됨. 쿼리의 실행 계획에서 프라이머리 키는 기본적으로 다른 보조 인덱스에 비해 비중이 높게 설정됨. 쿼리의 실행 계획에서 다른 보 조 인덱스보다 프라이머리 키가 선택될 확률이 ..