본 포스팅은 2023년 9월 12일 화요일 19시에 이화여자대학교 신공학관에서 진행된 백엔드 오픈 세미나 '퍼비톡'의 1차 세미나 내용에 관련된 포스팅이다.
서버/클라이언트 간 데이터를 주고받기로 약속한 웹 Application layer(OSI 7 layers Model), Application(TCP/IP Model) 프로토콜(데이터 통신 규약)
- stateless(비연결성) 프로토콜 ➡️ 쿠키, 세션 이용
TLS또는 SSL을 통해 신뢰성 있는 연결 보장해주는 프로토콜
사용하기 위해서는 인증기관(CA)로부터 SSL 인증서를 발급받아야 한다.
암호화가 되어있지 않은 HTTP 프로토콜에 비해,
검색 엔진 최적화➡️ google이 SSL(Secure Sockets Layer, 브라우저와 웹 서버 간의 암호화된 통신을 통해 만든 프로토콜, 비대칭키+대칭키 기반 사용함으로써 빠른 연산속도와 안정성 확보)
프로그램을 명령어 목록이 아니라, 객체라는 독립된 단위로 인식한다.
객체는 메시지를 주고받는 협력을 통해 데이터를 처리함.
➡️ 유연하고 변경에 용이객체 지향의 핵심, "다형성"
쉽게 비유하자면, 운전자는 자동차의 종류에 관계없이 운전할 수 있다.
역할(운전자)과 구현(자동차)을 분리한다고 보면 된다.
운전자는 프로그램에서의 클라이언트[interface]이므로, 구현 대상의 역할만 알면 되고, 내부 구조를 몰라도 된다.
내부 구조가 변경되거나, 구현 대상 자체가 변경되어도 영향을 받지 않는다.
인터페이스(interface)를 안정적으로 잘 설계해야 한다.(처음 설계할 때부터 '안정성'을 고려)
- SRP(Single Responsibility Principle): 단일 책임 원칙
: 한 클래스는 하나의 책임을 가져야 한다.
변경을 할 때 파급이 얼마나 있는가? 를 기준으로 책임을 판단한다.- OCP(Open, Closed Pinrciple)
: 확장에는 열려 있으나, 변경에는 닫혀있어야 한다.
코드의 변경 없이 기능을 확장할 수 있어야 한다. : 인터페이스를 구현한 새로운 클래스 만들기(기존 코드에 영향을 주지 않으면서, 기능을 확장할 수 있다)MemberRepository m = new MemoryMemberRepository(); // 기존 코드 MemberRepository m = new JdbcMemberRepository(); // 변경 코드
✔️ 구현 객체를 변경하기 위해 클라이언트 코드를 변경해야 함(OCP 원칙 위반) ➡️ Spring DI/IoC가 수행해줌!!
- LSP(Liskov Substitution Principle) : 리스코프 치환 원칙
프로그램의 정확성을 깨뜨리지 않고 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
다형성에서 하위 클래스는 그 객체를 신뢰할 수 있도록 인터페이스의 규약을 모두 지켜야 함(정확성을 깨트리지 않기 위함)
ex) 자동차 설계 시 브레이크는 멈추는 기능을 수행해야 한다. 만약 브레이크를 밟았을 때 훅 나가는 엑셀의 역할을 하면 LSP에 위반되게 설계한 것이다.- ISP(Interface Seperation Principle) : 인터페이스 분리 원칙
특정 클라이언트를 위한 인터페이스 여러 개를 사용하는 것이 범용 인터페이스 하나보다 낫다.
: 인터페이스(역할)의 분리, 명확성과 대체 가능성이 높아짐
ex) 운전 인터페이스, 정비 인터페이스를 나누어 설계한다.- DIP(Dependency Inversion Principle) : 의존성 독립 원칙
추상화에 의존해야지, 구체화에 의존하면 안된다.
구체 클래스에 맞추어 개발하게 되면, 상위 인터페이스도 변경, 클라이언트 단에서도 변경해야 하는 번거로운 일이 발생MemberRepository m = new MemoryMemberRepository(); // 기존 코드 // new를 통하여 생성 -> 위반
🎯 SOLID 원칙을 통하여 얻을 수 있는 장점?
(1) 확장 가능한 설계
(2) 클라이언트에 영향을 주지 않는 변경
(3) 안정적인 인터페이스 설계
Spring은 Framework, 오픈소스.
개발자로 하여금 정해진 틀 내에서 개발하기 용이하게 해주는 프레임워크.
Spring은 DI와 IoC 개념을 효과적으로 적용하는 데 중요한 역할을 한다.
➡️ 의존성 관리와 객체 생명 주기를 효율적으로 관리할 수 있다!
public class 안방(){
의자 chair = new 의자();
// 안방의자
// new 생성자의 문제점 : 객체인 chair을 new 연산자를 이용하여
// 생성한다면, 코드를 많이 고쳐야 함. 그러나 interface를 이용하여
// 구현하면, 안방 class를 건드리지 않고도 생성 O
}
public class 거실(){
의자 chair = new 의자();
}
(1) 생성자 주입:
@Autowired
어노테이션
불변성 확보, 순환 참조 방지 가능
최근에는 생성자를 하나 두고,@Autowired
생략
(2) Setter 메소드 주입: 변경 가능이 있는 상태
public으로 선언해야 해서 오류에 취약
순수 자바 코드를 통해 의존 관계가 누락 시 오류 잡기가 번거로워짐
(3) 필드 주입:
클래스 내부 필드에@Autowired
를 붙여
final을 선언할 수 없어 객체의 불변성 위반, 테스트 용이성 감소, 순환 의존성 감지 어려움, 리플렉션 의존
(4) 일반 메서드 주입:
한번에 여러 필드를 주입할 수 있음, but 많이 쓰지 않음.
@Component
기본적인 컴포넌트로, 스프링 빈으로 자동 등록@Autowired
필요한 의존 객체의 타입에 해당하는 Bean을 찾아 주입
생성자, setter, 필드 주입 가능
사용 시 주의할 점?
DI는 스프링이 관리하는 객체에서만 동작
빈이 없는 경우 동작 불가능
반복되는 메서드를 어노테이션을 통해 자동으로 작성해주는 라이브러리
getter()
setter()
메서드
@RequiredArgsConstructor
AllArgsConstructor
@NoArgsConstructor
public void add() {
/* 공통기능 */
// [1]로그
// [2]시간 체크 start
// [3]예외처리
/* 핵심기능 */
// 비즈니스 로직 부분
// [4]시간체크 end
}
Spring에서의 용어
- Before: 조인포인트 실행 이전에 실행
- After Throwing: 조인포인트 완료 후 실행
- After : 메서드 예외를 던지는 경우 실행
- Around: 메서드 호출 전후에 실행, 가장 강력한 Advice
@Component // Component 어노테이션을 통해 빈에 등록
@Aspect // 해당 클래스가 Aspect 임을 명시
public class PerfAspect {
}
- 웹 컨테이너만을 구현해둔 서버
- 개발자는 톰캣을 씀으로써 바로 서버를 사용할 수 있다.
<과정>
클라이언트가 JSP(Java Server Pages, 확장자는 .jsp
파일을 요청함.
웹 브라우저는 JSP를 읽을 수 없음. html, css, js, 이미지등의 정적 데이터만 읽을 수 있음
따라서 Tomcat이 .jsp
형식의 파일을 컴파일 하여 정적인 데이터인 html 파일로 변환
Tomcat이 JSP를 번역하여, 웹 브라우저가 이해할 수 있는 형태로 변환
Spring에 구현되어있는 DispatchServlet이 Tomcat에 구현되어있기 때문에, 로직 처리에만 집중하면 된다.
(핸들러 매핑, 핸들러 어댑터, 뷰 리졸버)
공통 업무에 대한 코드 중복을 줄이기 위한 도구(인증/인가, 로깅, 이미지/데이터 압축, 인코딩)
J2EE 표준 스팩, javax.servlet
패키지 안에 있는 인터페이스
ex) Spring Security에서 인증/인가에 대한 것: 필터
init() 메서드
: 필터 객체 초기화
destroy() 메서드
: 필터 객체를 서비스에서 제거, 사용한 자원을 반환
doFilter() 메서드
: 필터링이 이루어지는 메서드, 오버라이딩 필수, 지정한 url패턴에 맞는 HTTP 요청이 들어올 때마다 호출, Dispatcher Servlet으로 전달되기 전에 웹 컨테이너에 의해 실행
org.springframework.web.servlet
패키지안에 있는 인터페이스(HandlerIntercpetor)
preHandle
: 컨트롤러가 호출되기 전에 실행, 컨트롤러 이전에 처리해야 하는 작업에 사용
postHandle
: 컨트롤러가 호출된 후 실행, 이후 처리 작업에 실행
afterCompletion
: 모든 작업이 완료된 후 실행, 요청처리 중 사용한 리소스를 반환할 때
HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해준다.
과거에는 url 매핑을 위해 모든 서블릿을 web.xml에 등록해야 했다.
그러나, dispatcher servlet이 핸들링해줌.
정적인 페이지 제공(ex. 아파치)
동적 웹 애플리케이션 로직을 처리하는 것
Web Server(정적)+Servlet(동적) = Web application 구축 가능
html을 사용하여 요청에 응답
MVC 패턴에서 Controller로 이용
UDP 보다 처리속도 느림
서블릿을 관리해주는 컨테이너
웹 서버와 소켓으로 request/response 통신한다. (ex 아파치 톰캣)
(1) 웹 서버와의 통신 지원: Servlet에 구현해야만 하는 비즈니스 로직 자체에만 집중할 수 있게 해줌(jwt 토큰 필터를 할 때, servlet request를 이용함으로서 쉽게 인가 코드를 받아올 수 있다)
(2) 서블릿 생명 주기 관리
- 서블릿 클래스를 로딩하여 인스턴스화
- 서블릿 소멸시 가비지 콜렉션 진행
(3) 멀티스레드 지원 및 관리
- 새로운 자바 스레드 생성, 이미 존재하는 스레드 탐색
- HTTP 서비스 메소드 실행 후 스레드는 자동으로 소멸 또는 반환
(4) 선언적인 보안 관리