학원 수업도 끝났고 남는 시간에 한 번 만들어봐야겠다 생각만 하던 조합으로

프로젝트를 만들어 봐야겠다

[실전 SPA 개발 Vue.js with 타입스크립트 + 스프링 부트]

--전자책이라 엄청 신경써서 만드신건지 페이지분량이 어마무시하다..

+ 인프런 김영한 강사님의 스프링 / JPA강의를 참고하며 진행한다. 

 

1. Vue 생성

Vue() 생성자를 사용해 생성된 객체를 Vue 인스턴스라고 한다. DOM 요소에 마운트 해 Vue 기능을 사용한다

<div id="app">
	{{message}}
</div>


new Vue({
	el : '#app',   //요소
    
    data: {
    	message: 'Hello Vue!'
    }, //데이터
    
    computed: {
    	//computed 는 data 속성의 데이터에서 파생된 값을 공개하여 data 속성과 마찬가지로
        //템플릿에서 사용할 수 있게 한다. 함수형태지만 ()를 붙히지 않고 data값처럼 사용한다
    },
    methods : {
    	//methods 는 이벤트 처리 콜백함수 정의나 데이터 가공 함수 정의로 사용한다
        //computed는 캐시기능을 지원하고 methods는 매번 호출시 새로 실행을 보장한다
    },
    watch :{
		//watch는 데이터 변화를 감지하여 자동으로 특정 로직을 수행한다.
        //비동기 처리에 적합하다
    },
    filters: {
    	//필터는  | 왼쪽 하나의 인자를 받아 함수 형태로 정의한다
        //ex totalprice | numberFormat 으로 totalprice를 받아 화폐단위로 변환 등
    }
)}

//el없이
new Vue({
    data: {
    	message: 'Hello Vue!'
    }
)}.$mount('#app');

 

2. Vue의 인스턴스 라이프 사이클(생성부터 소멸까지)

beforeCreate -> data 속성과 methods 속성이 아직 인스턴스에 정의되어 있지 않다

created -> data와 methods 접근 가능

beforeMount -> el 속성에 지전항 화면 요소에 인스턴스 부착 전 호출 단계

mounted -> 인스턴스 부착 후 호출 단계

beforeUpdate -> 관찰하고 있는 데이터가 변경되면 가상 DOM으로 화면을 다시 그리기 전에 호출되는 단계

updated -> 데이터가 변경되고 나서 가상 DOM으로 다시 화면을 그리고나면 실행되는 단계

beforeDestroy -> 인스턴스 접근은 가능하므로 삭제하기 좋은 단계

destroyed -> 모든 속성 제거 후 인스턴스 파괴

 

3. Vue 템플릿 문법

템플릿은 Vue 인스턴스의 데이터와 뷰의 관계를 선언적으로 정의하는 역할

템플릿 문법으로 Mustache ( {{ }} ) / v-bind ( : ) 존재

 

4. 디렉티브 = Vue.js의 독자 정의 속성

v-if 지정한 뷰 데이터 값의 참 거짓 여부에 따라 HTML을 표시한다
v-for 뷰 데이터 개수만큼 HTML 반복 출력
v-show 데이터 진위 여부에 따라 display:none으로 만든다
v-bind HTML 태그의 기본 속성과 뷰 데이터 속성을 연결한다
v-on 화면 요소의 이벤트를 감지하여 처리할 때 사용한다
v-model 폼에 입력한 값을 뷰 인스턴스의 데이터와 즉시 동시화한다
(input, select , textaea 에 사용)
<tr>
	<td>비밀번호</td>
    <td><input type="password" v-bind:value="userPw"/></td>
</tr>
<tr>
	<td>소개</td>
    <td><textarea rows="5" v-bind:value="introduction"></textarea></td>
</tr>
<tr>
	<td>개발자여부</td>
    <td><span v-if="developer">개발자</span></td>
    <td><span v-else>개발자아님</span></td>
</tr>
<tr>
	<td>외국인여부</td>
    <td><span v-show="foreigner==='yes'">외국인</span></td>
</tr>
<tr>
	<td>사용자아이디</td>
    <td>
    	<input type="text" v-on:input="userId=$event.target.value" v-bind:value="userId">
    	//+ ex) v-on:change="~"
    </td>
</tr>
new Vue({
	el : "#app",
    
    data : {
		userId: "alex",
        userPw: "1234",
        introduction: "hello",
        developer : false,
        foreigner : "no",
        hobbyList : ["Sports" , "Music" , "Movie"],
        gender:"male",
        nationality : "01"
    },
    computed : {
    	getNationality: function(){
        	if(this.nationality ==="01"){
            	return "Korea";
            }else if(this.nationality ==="02"){
            	return "Germany";
            }else{
            	return "None";
            }
        }
    },
    methods :{
    	//데이터 값 
        onSubmit(){
        	const{ .....변수명} = this
        }
    }
})

 

자바스크립트 방식 Ajax에 무한스크롤을 구현해본다

 

    let lastpage = false; //마지막 페이지 설정
    let oneTime = false; //한번만 실행을 보장하는 변수
    let first = true; //맨처음 접속시 실행됨을 보장하는 변수


classScroll();

function classScroll(){
    const screenHeight = screen.height;/* 화면크기 */
            
    if(first&& !oneTime){
    oneTime = true; 
    first =false; 
    addClassLine();//컨텐츠 추가 발동
    }//맨처음 실행   
    
    document.addEventListener('scroll',OnScroll,{passive:true}) // 스크롤 이벤트함수정의
    
    function OnScroll () { //스크롤 이벤트 함수
            
            const fullHeight = infinitebox.clientHeight; // infinite 클래스의 높이   , 스크롤 이벤트 안에서 정의해야 추가된 높이가 다시 계산된다
            const scrollPosition = scrollY; // 스크롤 위치
                    if (fullHeight-screenHeight*1/4 <= scrollPosition && !oneTime && !lastpage && !first) {
                        oneTime = true; // oneTime 변수를 true로 변경해주고,
                        addClassLine();//컨텐츠 추가 발동
                    }
    }
}

function addClassLine(){
	//ajax를 통한 데이터 추가
    
}//컨텐츠 추가 발동

'개발자로 업그레이드 되자 > AJAX&JSON' 카테고리의 다른 글

Ajax - 자바스크립트 방식  (0) 2022.02.02
JSON / GSON  (0) 2021.12.08
Ajax개념 및 기초 사용법  (0) 2021.12.08

1. XMLHttpRequest 객체 생성

2. 설정 및 데이터 세팅

3. readyState가 변화했을 때 응답을 받고 데이터 처리

 

//통신에 사용될 XMLHttpRequest 객체 정의
let httpRequest = new XMLHttpRequest();

const 보낼 데이터 = {}


/* Post 방식으로 요청 */
httpRequest.open("POST", 요청할URL입력 , true);

/* Response Type 을 Json으로  */
httpRequest.responseType = "json";

/* 요청 헤더에 컨텐츠 타입 json 명시 */
httpRequest.setRequestHeader("Content-Type", "application/json");

/* 데이더 json으로 변환 후 전송하기 */
httpRequest.send(JSON.stringify(reqJson));


//readyState가 변화했을 때 함수 실행
 httpRequest.onreadystatechange = ()=>{
 	if(httpRequest.readyState === XMLHttpRequest.DONE){
    	//readyState가 Done이고 응답값이 200이면
                    if(httpRequest.status ===200){
                    	//성공
                    }
                    else{
                    	//실패
                    }
        }
 }

'개발자로 업그레이드 되자 > AJAX&JSON' 카테고리의 다른 글

Ajax로 구현하는 무한스크롤  (0) 2022.02.02
JSON / GSON  (0) 2021.12.08
Ajax개념 및 기초 사용법  (0) 2021.12.08

Ex) 로그인 시 아이디 정보를 저장 checkbox 표현 시

 

1. 세션에 저장된 login정보 가져오기

(Spring 에서 세션으로 저장하기 : @SessionAttributes + Model 객체 방식으로도 가능하다)

 

받아올 때 @ModelAttribute 객체로 받아오고 + 클래스에 @SessionAttributes({객체명}) 선언으로

model 객체를 session으로 사용한다.

 

2. 쿠키 생성

Cookie cookie = new Cookie("saveId" , 객체.getId() );

 

3. 쿠키 유효기간 설정 + 사용될 경로 설정

				if(아이디저장 체크박스 value !=null) {
					//아이디 저장 체크 시
					cookie.setMaxAge(60*60*24*30);
				}
				else {
					cookie.setMaxAge(0);
                    //체크 해제 시 유효기간 = 0
                    // 가지고 있던 쿠키가 사라진다
				}
				cookie.setPath(req.getContextPath());
                (HttpServletRequest 객체로 루트를 가져온다
                
                (HttpServletResponse 객체로 전송한다)
				resp.addCookie(cookie);

[ DNS ]

IP는 기억이 어렵고 추후 변경이 가능하다

이를 해결하기 위한 것이 DNS == IP주소를 이름으로 바꾸는 개념

 

[ URI와 웹 브라우저 요청의 흐름 ]

1. URI : Uniform Resource Identifier

- URI는 로케이터 ,이름 또는 둘 다로 추가 분류될 수 있다

(로케이터 : 리소스가 있는 위치를 지정 , 이름 : 리소스의 이름- 위치는 변하지만 이름은 변하지 않는 장점 )

- 결국 URI는 URL(로케이터) + URN(네임) 을 포괄한는 개념

-하지만 URN 이름만으로 실제 리소스를 찾을 수 있는 방법이 보편화 되지 않음

-결국 흔히 사용하는것은 URL의 개념

-URL : scheme://[userinfo@]host[:port][/path][?query][#fragment] 의 작성법을 가짐

 

[ 웹브라우저의 요청흐름 ] 

1. 클라이언트 : DNS를 조회 + HTTPS PORT 생략 + HTTP 요청메시지 생성

2. 생성되면 TCP 등을 추가하고 확인 후 서버로 전송

3. 서버가 받으면 똑같이 응답

 

[ HTTP ]  - Hyper Text Transfer Protocol == 인터넷에서 정보를 주고받는 규칙

1. HTTP 메시지에 모든 것을 전송한다 ( 텍스트, 이미지, JSON, 영상...)

2.  1.1 버전을 기본으로 2, 3 발전 중 ( 1.1 ,2 : TCP  / 3 : UDP 주로 사용 )

--현재는 1.1을 주로 사용하는 상태임

3. 클라이언트 서버 구조

4. 무상태 프로토콜 지향

 

무상태 프로토콜? (stateless)

1. 서버가 이전 상태를 유지하지 않는다 == 요청을 받으면 보관하지 않고 응답만 계속 보냄

2. 서버가 바뀌어도 그대로 진행됨 == 무제한 서버 증설 가능

3. 한계가 존재하는 경우 생김 ( ex 로그인 정보 유지 )

4. 정보를 매번 다 보내야하므로 정보가 커짐

(vs 상태유지 == 요청을 받으면 보관하고 응답 == 서버가 바뀌면 유지 정보를 다시 전달해주지 못할 수 있어 오류)

--일반적으로 브라우저 쿠키와 서버 세션등을 사용해서 상태 유지

--상태 유지는 최소한만 사용하는 것이 좋다

 

[비연결성]

1. 연결을 유지하는 모델 : TCP / IP

2. 연결을 유지하지 않는 모델 : HTTP

-- 처리 요청이 적으면 매우 효율적이나 페이지 넘어가면 매번 TCP 연결 절차로css, js등 매번 다운로드 발생 

-- 지금은 HTTP 지속 연결(Persistent Connections)로 문제 해결

 

 

 

 

 

 

 

'개발자로 업그레이드 되자 > HTTP' 카테고리의 다른 글

HTTP 개념 1  (0) 2022.01.25

인터넷 통신은 클라이언트 -> 서버로 갈때 수많은 노드를 지나가서 도착한다

[ 순서 ] 

1. IP주소 부여 ( = 인터넷 프로토콜 )

2. 패킷 단위로 보내게됨( 내 IP , 도착 IP , 메세지 정보등을 가짐) -> 노드를 거쳐 도착 IP로

3. 서버가 받아서 반대로 응답

 

--> 한계가 발생

1. 비연결성 ( 패킷을 받을 대상이 없거나 불능이여도 보내고 봄 )

2. 비신뢰성 ( 패킷이 사라지거나 나눠보냈는데 순서대로 도착하지 않을 수 있음)

3. 프로그램 구별 문제 ( 같은 IP에서 통신하는 어플이 둘 이상인 경우 구분하기가 어려움 )

 

--> 이를 해결하기 위해 TCP/ UDP 개념이 쓰임

 

[ 인터넷 프로토콜 스택의 4계층 ]

1. 애플리케이션 계층 - HTTP, FTP

2. 전송 계층 - TCP, UDP

3. 인터넷 계층 - IP

4. 네트워크 인터페이스 계층 (LAN 장비)

==> 메세지 생성 -> TCP 정보 추가 -> IP 패킷 추가 -> LAN 카드에서 전송 으로 진행됨

 

TCP? 전송 제어 프로토콜 / 전송 제어, 순서 , 검증 정보를 포함하고 있음 -> 기존 한계점 해결

-특징-

(1) 연결지향 (가상 연결로 연결가능 확인 후 보냄 )

(2) 데이터 전달 보증 (정상 도착을 확인)

(3) 순서 보장

(4) PORT가 포함되어 있어 구별가능


UDP? 사용자 데이터그램 프로토콜 / IP와 유사하지만 PORT + 체크섬 추가

-특징-

(1) 단순하고 빠름

(2) 특별한 기능은 없지만 TCP가 정확함에도 속도 최적화가 어려워 이를 보완하기 위해 쓰임

(3) 애플리케이션에서 추가 작업 가능

 

 

 

 

'개발자로 업그레이드 되자 > HTTP' 카테고리의 다른 글

HTTP 개념 2  (0) 2022.01.25

Java Persistence API - 자바 ORM 기술 표준

 

[ ORM이란] Object-relational-mapping : 객체 관계 매핑

객체와 RDBMS의 중간에서 매핑해주는 기술

 

WHY JPA? 

객체와 RDMBS의 괴리로 객체답게 모델링할수록 의미없는 매핑 작업만 늘어나게된다.

객체를 자바의 형태로 DB에 저장할 수 있도록 도움 필요

--> SQL 중심적인 개발에서 객체 중심의 개발이 가능해진다

==생산성 증가, 유지보수 유리 / 객체-> SQL의 패러다임 불일치 해결

==데이터 접근 추상화

 

JPA의 구동 방식

1. (설정정보 조회)-> Persistence ->

2. EntityManagerFactory 생성 (하나만 생성되어 앱 전체에서 공유됨) ->

3. EntotyManager 생성 (쓰레드간 공유하면 안된다)

--> JPA의 모든 데이터변경은 트랜잭션 안에서 실행된다

 

-매핑-

1. 객체와 테이블 매핑

@Entity : JPA가 관리할 객체 (클래스)

@Id : DB PK와 매핑되는 필드

 

-JPQL-

SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어

JPA를 통한 객체 중심 개발에서 문제가 되는 검색 쿼리의 문제 해결에 이용

검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 하게 해준다

이 과정에서 결국 조건이 포함된 SQL이 불가결대상이 되긴한다

SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원

 

 

 

 

 

 

 

'개발자로 업그레이드 되자 > JPA' 카테고리의 다른 글

엔티티 설계시 주의점  (0) 2022.09.27
영속성  (0) 2022.09.06

AOP란? -> 관점 지향 프로그래밍의 약자

=공통되는 부분을 따로 빼내어 필요한 시점에 해당코드를 추가해주는 기술

ex)컨트롤러 -> 서비스 이동시마다 println 을 실행한다면?

 

1. Advice : 공통되는 부분을 따로 빼내어 작성하는 메소드

2. JoinPoint : Advice가 적용될 수 있는 모든 관점(시점) -> 매우많음

3. Pointcut : JoinPoint 중 실제 Advice를 적용할 부분

4. Weaving : 그 시점에 공통 코드를 끼워넣는 작업

(컴파일 시 , 클래스 로딩 시 , 런타임 시 ) 가능

 

*Aspect = Advice + Pointcut : 실제동작코드 + 실제 적용된 부분 을 작성한클래스

=> 부가기능(로깅, 보안, 트랜잭션 등)을 나타내는 공통 관심사에 대한 추상적인 명칭)

=> 여러 객체에 공통으로 적용되는 부가기능을 작성한 클래스를 나타냄

=> 독립적인 요소로 구분해 내서 부가기능을 런타임 시 필요한 위치에 동적으로 참여하게 할 수 있다

 

Advice 시점에 따라

Before Advice JoinPoint 앞에서 실행
Around Advice JoinPoint  앞과 뒤에서 실행
After Advice JoinPoint  호출이 리턴되기 직전에 실행
After Returning Advice JoinPoint  메소드 호출이 정상적으로 종료된 후에 실행
After Throwing Advice 예외가 발생했을 때 실행

 

*Proxy : 대상 객체에 Advice가 적용된 후 생성되는 객체

*Target Object : Advice를 삽입할 대상 객체

 

스프링은 대상 객체에 대한 프록시를 만들어 감싸서 대상 객체를 호출할 때 먼저 호출되서

Advice 로직을 처리한 후 대상 객체를 다시 호출한다.

 

[ AOP 구현 ] - *애너테이션 방식*

Spring pom.xml에 이미 aspectj 가 포함되어있음

+ 좀 더 쉬운 구현을 위한 Weaver 추가

***MVN Repository => Aspectj Weaver 추가

 

1. 해당 클래스에 @Aspect -> 공통 관심사가 작성된 클래스임을 명시

+(Advice, Pointcut 작성되어 있어야 함)

+@Conmonent 추가해 런타임 중 Advice코드가 동적으로 추가될 수 있도록 bean 등록

 

***servlet-context에서 namespace - aop 체크 + <aop:aspectj-autoproxy/> 작성 필요 ***

 

2. 수행할 메소드 + @Before / @After ...

*@Before("Pointcut")  :  Pointcut으로 지정된 메소드가 수행되기 전에 Advice 수행

**Pointcut 작성법 3가지

1) 직접

@Before("execution( * a.b.c..*Controller.*(..))")

작성식 : execution [접근제한자] +리턴타입 + 패키지경로명 + 클래스(*C : 모든 컨트롤러) + 메서드( *(..) : 모든 메서드)

-접근제한자는 생략가능/ *: 모든 리턴타입 의미 / .. :  하위 모든 패키지 or 0개 이상의 매개변수-

 

2) Pointcut이 작성된 메소드명을 작성

 

 

 

3) 타 클래스에 작성된 Pointcut 메소드를 작성

 

3. 메소드 작성

//@Before(직접작성)
@Before("PointcutCollection.controllerPointcut()")
public void controllerLog(JoinPoint jp) {

	logger.info("테스트");
    
    jp.getArgs() : 수행되는 메소드의 모든 매개변수를 배열로 얻어옴
    jp.getTarget() : 타겟이 된 객체를 얻어온다
    jp.getSignature() : 수행되려는 메소드 선언부를 얻어옴
{

-매개변수로 입력한 JoinPoint : 부가 기능 메소드를 제공하는 인터페이스

 

3-1 Pointcut을 모아둘 클래스

public class PointcutCollection {

	@Pointcut("execution(  식 작성 )
    public void controllerPointcut(){}
    
    @Pointcut("execution(  식 작성2 )
    public void servicePointcut(){}
}

 

 

 

 

++ Around 사용 -- 앞뒤 모두 아우르는 관점 ex) 러닝타임계산

@Aspect // Advice + Pointcut 공통 관심사가 작성된 클래스임을 명시
@Component
public class AroundAspect {
	
	//slf4j import
	private Logger logger = LoggerFactory.getLogger(AroundAspect.class);
	
	
	//Around : 전처리, 후처리를 모두 해결하고자 할 때 
	//ProceedingJoinPoint를 매개변수 필수 사용 
	//(Proceeding: 진행)
	//-> proceed() 메소드 사용 가능: 해당 메소드를 기준으로 Before, After 나뉨
	
	
	@Around("PointcutCollection.serviceImplPointcut()")
	public Object aroundLog(ProceedingJoinPoint pp) throws Throwable {
		
		  // 클래스명
		  String className = pp.getTarget().getClass().getSimpleName(); // 대상 객체의 간단한 클래스명(패키지명 제외)
		  
		  // 메소드명
		  String methodName = pp.getSignature().getName(); // 대상 객체 메소드의 정보 중 메소드명을 반환. 
		  String str = "";
		  
		  str += "[Service]" +  className + "-" + methodName + "()";
		  
		  long startMs = System.currentTimeMillis(); // 서비스 시작 시의 ms 값
		  
		  //구분기준
		  Object obj = pp.proceed();
		  long endMs = System.currentTimeMillis(); // 서비스 종료 시의 ms 값
		  
		  //걸린시간
		  str+= "[Running Time]" +(endMs-startMs) + "ms";
		  
		  //서비스 수행 시 사용된 파라미터
		  str+= "[Param]" + Arrays.toString(pp.getArgs());
		  
		  logger.debug(str);
		  
		  //proceed 반환값을 무조건 리턴
		  return obj;
	}
}

 

 

Bean으로 등록하기 위한 스프링의 애너테이션

1. @Component : 객체(컴포넌트)를 나타내는 일반적인 타입으로 태그와 동일한 역할

2. @Repository : 퍼시스턴스(persistence) 레이어, 영속성을 가지는 속성(파일, 데이터베이스)를 가진 클래스

--EX) DAO

3. @Service : 서비스 레이어, 비즈니스 로직을 가진 클래스

--EX) Service

4. @Controller: 프리젠테이션 레이어, 웹 애플리케이션에서 View에서 전달된 웹 요청과 응답을 처리하는 클래스

(2,3,4 는 1의 구체화 형태인 셈)

 

 DI 주입을 위한 스프링의 애너테이션

1. @Autowired : property, constructor-arg 태그와 동일한 역할을 한다 ,

 의존하는 객체를 주입할 때 주로 Type을 이용하게 된다.

2. @Resource : 애플리케이션에서 필요로 하는 자원을 자동 연결할 때 사용된다.

3. @Value: 단순한 값을 주입할 때 사용되는 어노테이션이다.

 

<context:component-scan> 태그

@Component를 통해 자동으로 Bean을 등록하고, @Autowired로 의존 관계를 주입받는 어노테이션을 클래스에서 선언하여 사용했을 경우에는 해당 클래스가 위치한 특정 패키지를 Scan 하기 위한 설정을 XML에 해주어야한다. 이 때 사용하는 태그이다

스프링 컨테이너: BeanFactory를 기반으로 Bean 클래스들을 제어할 수 있는 기능을 지원한다.

 

스프링의 동작 구조 : 

Request -> Servlet 컨테이너 -> Spring 컨테이너(new XmlWebApplicationContext()-> servlet-context.xml불러옴 )

*servlet-context.xml : spring 컨테이너가 실행해야 하는 내용을 설정하는 파일

(트랜잭션 관리, DI, AOP 등 관리)

 

즉, 

1. 요청

2. 서블릿 컨테이너 - DispatcherServlet이 받음 (Web.xml 포함됨)

3. HandlerMapping ( 해당 요청을 매핑한 컨트롤러가 있는지 검색 -- @RequestMapping() 제공)

4. 처리 요청 +Bean등록

5. 결과를 출력할 View 리턴

6. DispatcherServlet에서 ViewResolver를 통해 view 검색 처리

 

[읽어들이는 순서]

-서버 구동시 web.xml 제일먼저 읽음

-그 안의 context-param 가장 먼저 읽음

-그 안에 root-context(자원관련 , DB ) / spring-security xml을 써놨고 제일 먼저 작동됨

-bean (스프링에서 생성하고 관리하는 객체) 으로 정의해놓음

-클라이언트가 요청시 dispatcher servlet 읽음 == 서블릿 컨테이너가 먼저 받음 ==> 스프링 컨테이너로 넘겨줌

-스프링 컨테이너의 servlet-context.xml의 설정대로 요청 받게됨 -> Handler Mapping -> 
     요청받은 주소를 처리할 클래스나 메서드에 지정하는 역할 (어노테이션 형식 사용) ==> @Controller, @RequestMapping 이 쓰임

-component-scan이 작동됨 -> 처리진행 -> 문자열 반환

-반환받은 문자열에 앞뒤 경로 붙여서 View Resolver 에서 응답 경로 내보냄

 

Bean? 

-스프링이 IoC 방식으로 관리하는 객체 / 스프링이 직접 생성과 제어를 담당

 

<스프링 컨테이너와 스프링 빈> 작동 단계
1. 스프링컨테이너 생성
2. 스프링 빈 등록
3. 스프링 빈 의존관계 설정 준비
4. 스프링 빈 의존간계 설정 완료

 

<스프링 빈 조회 - 상속관계>
-> 부모타입으로 조회하면 자식타입도 모두 조회됨

 

<IoC컨테이너>

Bean 생성 객체 : BeanFactory  <- ApplicationContext  <- AnnotaionConfig ApllicationContext (상속)

BeanFactory  :스프링 컨테이너 최상위 인터페이스 / 스프링의 IoC 담당하는 핵심

ApplicationContext  : 팩토리 상속받아 빈 관리 + 부가기능위해 (실질적 사용)

 

* 스프링 컨테이너는 다양한 형식의 설정 정보를 받아들일수 있게 설계됨

(애너테이션, XML)

HOW? BeanDefinition이라는 추상화 덕분에 여기서 메타정보만 가져오면 스프링 빈을 생성할 수 있다.

 

<싱글톤 패턴>
대부분의 스프링 애플리케이션은 웹 -> 여러 고객이 동시에 요청을 한다
==> 문제점 : 요청시마다 계속 객체 생성해줘야함 ==>메모리 낭비가 극심
--> 1개의 객체를 공유하도록 설계 == 싱글톤 패턴

 

싱글톤 패턴 : 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴
--> 2개 이상 생성을 막는다 == private으로 외부 new 막는다
==>스프링에선 자동으로 싱글톤 지원해줌

 

문제 : 
1. 코드가 길어짐
2. 구체클래스에 의존한다 DIP 위반
3. == OCP 위반
4. 테스트 어려움
5. 유연성 떨어짐, 자식클래스 만들기 어려움

==> 스프링에서는 싱글톤 패턴 문제-> 싱글톤 컨테이너에서 해결함
싱글톤 컨테이너 : 싱글턴 패턴 적용 없이 싱글톤으로 관리
-> 스프링 컨테이너에서 관리.
-> 이미만들어진 객체를 공유해서 재사용

 

<싱글톤 방식의 주의점!!>
-> 상태를 유지하게 설계하면 안된다
== 만약 유저1일 100의 값을 넣은 상태에서 유저 2가 200의 값을 넣고 유저1이 값을 조회한다면?
==> 문제발생

 

<@Configuration> : 스프링의 싱글톤을 위해 존재한다
만약 두개의 bean에서 동일한 객체를 new로 생성한다면?각각 new 해야 맞지만 스프링이 싱글톤을 관리해줌 ==모두 같은 인스턴스가 공유되어 사용됨
HOW? 
bean을 출력해보면 클래스 경로 + CGLIB를 붙혀버림 (상속 클래스를 하나 더 추가해서 조작함) => 이것이 유지해줌
1. 이미 스프링컨테이너에서 있으면? 스프링 컨테이너에서 반환
2. 아니면? 기존 로직을 호출해서 스프링 컨테이너에 등록하고 반환

-> @Configuration이 해주는 일이므로 @bean만 쓰면 싱글톤이 유지되지 않는다!

+ Recent posts