팀원 정보

<aside> 🔐 스프링 프레임워크는 어떤 특징 혹은 장점을 가지고 있나요? (3가지 이상)

</aside>

🤔 Framework 프레임워크는 프로그램의 기초를 구축할 수 있는 코드의 집합이다. 협업 시 개발자의 능력이나 작업 방식의 차이에서 올 수 있는 어려움을 방지하고, 쉽게 프로그램의 기본 뼈대를 구성할 수 있도록 한다.

1️⃣ POJO(Plain Old Java Object) 기반의 구성

스프링은 내부적으로 별도 API를 사용하지 않고, Plain Java의 방식 그대로 객체를 구성한다. Java의 기본 개념인 객체지향에 집중하고, 특정 클래스나 라이브러리에 종속되지 않는 방식으로 짜여져있다.

2️⃣ Transaction 지원

상황에 따라 @Trancsactional 혹은 XML을 통해 Transaction을 간편하게 구현할 수 있다.

🤔 Transaction ** cf) Commit, Rollback* ****데이터베이스의 상태를 변화시키기 위해 수행하는 작업의 단위. 크게 4가지 특성을 갖는다.

  1. 원자성 : Transaction은 DB에 모두 반영되거나, 전혀 반영되지 않아야한다.
  2. 일관성 : Transaction의 결과는 항상 일관되야 한다.
  3. 독립성 : 여러 Transaction이 실행 중일 때, 서로 연관에 관여할 수 없고, 참조할 수 없다.
  4. 지속성 : Transaction이 완료된 이후, 결과는 영구적으로 반영되어야 한다.

3️⃣ DI(Dependency Injection) / IoC(Inversion of Control)

<aside> 💡 DI는 객체를 직접 생성하는 것이 아닌, 외부에서 생성한 후에 주입하는 방식이다.

</aside>

class Person {
	Schedule schedule;

	public Person() {
		this.schedule = new Schedule();
	}

	// 가능한 여행 출발 날짜를 확인하기 위한 method
	public LocalDateTime vacation() {
		this.schedule.checkSchedule(); // 일정이 있는지 확인
		...
	}
}

위와 같은 코드에서 Person이 가능한 여행 출발 날짜를 확인하기 위해 vacation() 메소드를 호출하기 위해서는, Schedule Class를 필요로 한다. 이러한 경우를 PersonSchedule에 **의존성(Dependency)**를 갖는다고 이야기 한다. 이러한 경우, Person과 Schedule은 강한 결합을 지니게 되는데, 그에 따른 단점은 다음과 같다.

  1. 코드의 재사용성이 떨어진다.
  2. Schedule Class가 수정되면, Person Class도 함께 수정되어야 한다.

예를 들어 고객의 요청으로 인해, Schedule 을 상속한 CourseSchedule 혹은 WorkSchedule을 객체에 따라 사용해야한다면 어떨까? 이런 경우 코드는 다음과 같이 수정되어야 할 것이다.

 class Person {
	Schedule schedule;

	public Person() {
		this.schedule = new WorkSchedule();
	}

	// 가능한 여행 출발 날짜를 확인하기 위한 method
	public LocalDateTime vacation() {
		this.schedule.checkSchedule(); // 일정이 있는지 확인
		...
	}
}

만일 Person이 아닌 다른 객체에서도 Schedule 이 아닌 WorkSchedule 혹은 CourseSchedule을 사용해야 한다면, 해당 객체들을 일일이 찾아다니며 코드를 수정해야할 것이다. 결국, 객체 지향 언어를 사용하는 의미가 퇴색된다.

DI는 이러한 문제를 해결하기 위한 방법이다. DI는 객체(Person)가 의존하는 객체(Schedule)를 내부에서 생성하는 것이 아니라, 주입해줌으로써 이를 해결한다.

class Person {
	Schedule schedule;

	public Person(Schedule schdule) {
		this.schedule = schedule;
	}

	// 가능한 여행 출발 날짜를 확인하기 위한 method
	public LocalDateTime vacation() {
		this.schedule.checkSchedule(); // 일정이 있는지 확인
		...
	}
}

위 코드에서 WorkScheduleCourseScheduleSchedule을 상속받았기 때문에, 상황에 따라 Person을 생성할 때 의존할 객체를 선택하여 사용할 수 있다.

<aside> 💡 IoC는 객체의 호출을 개발자가 결정하지 않고, 외부에서 결정하는 방식이다.

</aside>

일반적인 객체의 생성 및 실행의 단계는 다음과 같다.

  1. Person 생성
  2. Schedule 생성
  3. schedule.checkSchedule() 호출

하지만 Spring에서는 다음과 같은 순서로 객체를 생성한다.

  1. Person 생성
  2. Spring에 의해 Schedule 주입
  3. Spring이 만든 객체에서 schedule.checkSchedule() 호출

Spring은 ApplicationContext를 사용해 객체(Bean)을 생성하고, 그들 간의 의존 관계(Dependency)를 설정한다. @Configuration 이 붙은 Class들을 설정 정보로 등록해두고, @Bean 이 붙은 메소드의 이름으로 @Bean 리스트를 생성한다. 만일 클라이언트가 특정 @Bean 을 요청하면, ApplicationContext@Bean 리스트를 확인해 생성된 @Bean 을 반환하거나, 생성되지 않은 경우 객체를 @Bean 메소드를 통해 생성하고 반환한다.

Untitled

<aside> 🔐 스프링에서 DI (의존성 주입) 를 사용하는 이유가 무엇인가요? 예를 통해 설명 해 보세요.

</aside>

윗 문단 3️⃣ 참고

<aside> 🔐 ORM, JPA, Spring Data JPA 를 구분해서 설명해 보세요.

</aside>

1️⃣ ORM(Object Relational Mapping)

객체와 관계형 데이터베이스의 데이터를 자동으로 Mapping해주는 것을 의미.

객체지향 프로그래밍의 목적은 시스템의 복잡성을 제어할 수 있는 다양한 장치를 구축하고 사용하기 위함이다. 이를 위해 추상화, 상속 등의 개념을 사용한다. 이에 반해 데이터베이스는 집합적인 사고로 구성되어있으며, 객체지향 프로그래밍과 지향하는 목적이 다르다. 이를 패러다임의 불일치라고 하며, 개발자의 역할은 이러한 문제를 해결하는 것에 있다.

문제는 이러한 패러다임의 불일치를 해결하기 위해, 개발자는 수많은 시간과 코드를 소비해야한다는 데 있다. 그나마 일정 부분 객체지향의 개념을 적용할 수 있는 RDBMS를 통해 구현해도, 낭비되는 자원은 적지 않다.

Untitled

public abstract class Item {
    private Long id;
    private String name;
    private int price;
}
public class Album extends Item {
    private String artist;
}
public class Movie extends Item {
    private String director;
    private String actor;
}
public class Book extends Item {
    private String author;
    private String isbn;
}

새로운 ALBUM을 등록하기 위해서는, Album의 Field를 분해하고 두 번에 걸쳐 쿼리를 날려야한다.

INSERT INTO ITEM ...
INSERT INTO ALBUM ...