목록Java (19)
백엔드 엔지니어 이재혁
Spring Framework에는 생성자 주입, 필드 주입, Setter 주입 방식이 있다. 이 중 권장되는 방식은 생성자 주입 방식이고, 런타임에 의존 관계를 수정해야 할때 사용하는 방식이 Setter 주입 방식이다. 순환 참조 문제필드 주입과 Setter 주입에는 순환 참조를 사전에 확인하기 어렵다는 문제가 있다. 우선, 생성자 주입을 사용하는 경우를 확인해보자.생성자 주입은 의존 관계를 따라 가장 먼저 필요한 빈부터 생성해준다. 의존하는 객체가 먼저 생성되기 때문에 순환 의존 문제가 있는 경우 빈 생성 단계에서 즉시 예외가 발생해 사전 예방이 가능하다.A를 생성하려면 B가 필요하고 B를 생성하려면 A가 필요하다면A를 생성할 때는 B가 필요해서 A를 생성하지 못한다.B를 생성할 때는 A가 필요해서 B..
Spring Framework 기반 어플리케이션이 실행되면 어떤 일이 일어나는지 살펴보자. 스프링 컨테이너(ApplicationContext) 생성스프링 컨테이너는 모든 빈(Bean)의 생명 주기를 관리한다.빈(Bean) 생성 및 의존성 주입(DI) 스프링 컨테이너가 설정 파일(application.xml 등)이나 어노테이션(`@Component`, `@Configuration` 등)을 통해 등록된 클래스를 스캔하여 빈으로 등록하며, 객체간 의존성을 주입한다.의존성 주입 후처리의존성 주입이 끝나면, `@PostConstruct` 등으로 정의된 초기화 메서드가 실행된다. 이 시점에 추가적인 설정이나 초기화 작업을 할 수 있다.어플리케이션 실행 및 빈 사용모든 빈이 준비되면, 실제로 어플리케이션 로직이 실행..
핵심은 좋은 객체 지향 어플리케이션 개발을 위해 등장했다. 좋은 객체 지향 프로그래밍이란?객체 지향 프로그래밍의 핵심은 "다형성"이다.(4대 개념은 추상화, 캡슐화, 상속, 다형성이지만 결국 다형성이 핵심이라고 생각함) 프로그램을 유연하고 변경이 용이하게 하는 데에 도움이 된다. 유연하고 변경이 용이하게 해주는 핵심은 "인터페이스" 세상은 역할과 구현으로 구분할 수 있다. 자동차는 역할, 아반떼는 구현.자바에서는 인터페이스(역할)와 클래스(구현)로 구분한다. Spring은 IoC와 DI를 이용해 역할과 구현을 편리하게 다룰 수 있게 지원하여 다형성을 극대화해서 이용할 수 있게 도와준다. 원칙들을 더 살펴보자좋은 객체 지향 설계의 5가지 원칙 (SOLID)SRP: 단일 책임 원칙(Single respons..
java.util.concurrent 패키지에는 BlockingQueue 인터페이스가 있다. 대표적인 구현체ArrayBlockingQueueLinkedBlockingQueueBlockingQueue의 메서드※ Java 7 공식 문서에 있는 요약본OperationThrows ExceptionSpecial ValueBlocksTimes OutInsertadd(e) offer(e) put(e) offer(e, time, unit)Remove remove() poll() take() poll(time, unit)Examine element() peek() not applicable not applicable Throws Exception - 대기시 예외 add(e): e를 큐에 추가. 큐가 가득찬 ..
기존에 사용했던 synchronized와 Object.wait(), Object.nofity()만으로 해결하려고 하면 생산자와 소비자 그룹을 "분리"시켜 대기시킬 수 있는 기능이 없다. 이번에는 자바 1.5부터 도입된 Lock 인터페이스와 ReentrantLock 구현체를 사용해서 개선시켜보자. 우선 클래스에서 ReentrantLock을 사용하기 위해 ReentrantLock 객체를 생성해준다.private final Lock lock = new ReentrantLock(); 그 다음, lock.newCondition()을 통해 스레드의 대기 집합을 만들어줄 수 있다.private final Condition condition = lock.newCondition(); 위와 같이 하나의 대기 집합만 사용한..
생산자 소비자 문제 혹은 한정된 버퍼 문제 (둘 다 같은 의미)는 생산자, 소비자 그리고 버퍼 관계에서 발생할 수 있는 문제를 다룬다. 여러 스레드의 동시 데이터 접근 및 상태 변화 문제라고도 할 수 있다. 생산자: 데이터를 생산하는 쪽 (버거킹 알바)소비자: 데이터를 소비하는 쪽 (버거킹 손님)버퍼: 생산자가 생산한 데이터를 일시적으로 저장하는 공간 (버거킹 버거 대기시켜두는 곳) 소비자는 버퍼에서 데이터를 가져간다. 패스트푸드 음식점 비유위에서 비유한대로 버거킹을 예시로 생산자 소비자 문제를 설명해보겠다. 1. 생산자가 너무 빠를 때 (버퍼 공간 부족 문제)생산자 측에서 버거를 마구마구 만들다가 버거를 대기시켜두는 곳이 가득 차면 만든 버거를 버려야 할까?아니다. 만든 사람(알바)이 ..
synchronized 키워드를 사용하면, 무한 대기 문제와 공정성 문제가 발생할 수 있다. 이를 해결하기 위해 LockSupport를 사용해서 수동으로 동시성 제어를 할 수도 있다. LockSupportpark(), partNanos(long ns), unpark(Thread thread) 메서드 제공 park()는 스레드를 WAITING 상태로 변경하고, 다른 스레드에서 unpark() 메서드를 사용해 RUNNABLE 상태로 바꿔줄 수 있다. 인터럽트를 사용하고 싶다면, 인터럽트로도 가능하다. 차이점이라면 스레드의 인터럽트 상태가 바뀌는지 안바뀌는지 여부가 다르다.참고: BLOCKED 상태는 synchronized 키워드만이 만들 수 있는 상태LockSupport는 BLOCKED 상태를 사용하지 않..
Java에서 synchronized 메서드(혹은 코드 블럭)는 다음과 같이 동작한다.Java 객체에서 기본으로 제공하는 락은 "모니터 락"이라고 부른다.객체당 하나의 모니터 락만 존재한 스레드가 synchronized 메서드를 실행하면, 해당 객체의 락을 획득다른 스레드는 같은 객체의 어떤 synchronized 메서드도 실행할 수 없다.아래와 같이 하나의 클래스 안에 다수의 메스드에 대해서 synchronized 키워드가 붙어있다면, 각 메서드에 락이 걸리는 것이 아니라, 객체 단위로 락이 걸리게 된다.public class BankAccountV2 implements BankAccount{ private int balance; public BankAccountV2(int initialBal..