2022. 9. 18. 14:04ㆍSpring
스프링이 필요한 이유
결론부터 말하자면 , 스프링은 좋은 객체지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크이다.
스프링을 공부하기전 스프링의 필요한 이유를 알아야한다.
그러기 위해서 먼저, 객체지향적으로 설계된 자바 코드를 보도록 하겠다.
객체지향이란??
“객체”들의 모임, 각각의 객체는 메세지를 주고받고, 데이터를 처리함. 유연하고 변경이 용이(부품을 갈아끼우듯이) ⇒ 다형성
객체 지향 특징
- 상속
- 다형성
- 추상화
- 캡슐화
클라이언트는 인터페이스만 알면 된다.
인터페이스 → 구현클래스
다형성을 통해 인터페이스를 구현한 객체 인스턴스를 실행시점에 유연하게 변경할 수 있다.
⇒ 클라이언트는 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.
결론 : 인터페이스를 잘 설계해야한다.
좋은 객체 지향 설계의 5가지 원칙 (SOLID)
- SRP : 단일 책임 원칙(single responsibility principle)
- OCP : 개방-폐쇄 원칙(Open/closed principle)
- LSP : 리스코프 치환 원칙(Liskov substition principle)
- ISP : 인터페이스 분리 원칙(Interface segregation principle)
- DIP : 의존관계 역전 원칙(Dependency inversion principle)
SRP 단일 책임 원칙
- 한 클래스는 하나의 책임만 가져야 한다.
- 하나의 책임이라는 것이 모호하다.
- 예를 들어서, 게시판을 구현한다고 할 때, 멤버와 게시판의 역할을 나누는 것
- 따라서, 중요한 기준은 변경하려고 할 때 그 부분만 수정하면 되는 것!
OCP 개방-폐쇄 원칙
- 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야한다.
- 다형성을 이용하는 것
- 인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현 : 인터페이스는 변경하지 않는 것→ 변경 x , 새로운 구현 클래스 → 확장
LCP : 리스코프 치환 원칙
- 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야한다. ⇒ 인터페이스의 본래 설계 목적에 맞게 구현 클래스를 만들어야함
ISP 인터페이스 분리 원칙
- 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
- 인터페이스가 명확해지고, 대체 가능성이 높아진다.
DIP 의존관계 역전 원칙
- 프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다.”
- 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻
일반적인 자바 애플리케이션 구조
다이어그램으로 표현하면 아래와 같다.
코드로 표현하면 아래와 같다.
public class Member {
//학번
private Long memberId;
// 1: 남자, 0: 여자
private int sex;
private String memberPassword;
private String memberName;
private String memberNumber;
private Grade grade;
getter,setter
constructor
}
public interface MemberService {
void join(Member member);
Member findMember(Long memberId);
}
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository = new
MemoryMemberRepository();
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}
public interface MemberRepository {
void save(Member member);
Member findById(Long memberId);
}
public class MemoryMemberRepository implements MemberRepository{
private static final Map<Long, Member> store = new HashMap<>();
@Override
public void save(Member member) {
store.put(member.getMemberId(), member);
}
@Override
public Member findById(Long memberId) {
return store.get(memberId);
}
}
위 코드들은 다형성을 잘 활용하였고, 인터페이스와 구현 객체를 잘 분리하였다.
OCP,DIP와 같은 객체지향 설계원칙을 잘 준수한 것처럼 보인다.
->하지만, 그렇지 않다.
위 클래스들의 의존관계를 분석해보면, 인터페이스뿐만아니라 구현 클래스에도 의존하고 있다.
- 인터페이스 의존 : MemberRepository
- 구현 클래스 의존 : MemoryMemberRepository
=> 현재 코드들은 기능을 확장해서 변경하면, 클라이언트 코드에 영향을 준다.
따라서, OCP 위반이다.
예를들어서, MemberRepository의 구현 클래스를 MysqlRepository로 바꾸고 싶다고 할 때,
private final MemberRepository memberRepository = new
MemoryMemberRepository(); -> private final MemberRepository memberRepository = new MysqlRepository로 바꿔야한다. => 곧 클라이언트 코드를 건드리는 것이다.
결론 : 위의 코드들은 다형성을 잘 활용했지만, 그것만으로는 충분하지 않다.
객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자가 필요하다 → 스프링
위 포스팅은 김영한님의 스프링-핵심-원리-기본편 강의를 수강한 후 작성한 포스팅입니다.
'Spring' 카테고리의 다른 글
Springboot test @Transactional rollback is not working (0) | 2022.09.26 |
---|---|
[김영한님 - 스프링의 핵심원리] Spring - 스프링이 필요한 이유(2) (0) | 2022.09.19 |
파일 업로드 - BindException 에러 해결, multipart (0) | 2022.08.26 |
@ModelAttribute의 특징 (0) | 2022.08.25 |
EmptyResultDataAccessException 해결, jdbcTemplate.queryForObject에 관하여 (0) | 2022.08.21 |