인프런 spring framework 강의 정리 2

하파타카·2023년 12월 14일
0

spring

목록 보기
2/2
post-thumbnail

자바 스프링 프레임워크(renew ver.) - 신입 프로그래머를 위한 강좌

스프링 컨테이너, 빈(Bean) 객체 생명주기


04. 설정 및 구현

생명 주기

스프링 컨테이너 초기화 : 빈(Bean) 객체 생성 및 주입
스프링 컨테이너 종료 : 빈(Bean) 객체 소멸
→ 빈 객체의 생명주기는 스프링 컨테이너의 생명주기와 같이 한다.

//스프링 컨테이너 생성(초기화)
GenericXmlApplicationContext ctx = 
		new GenericXmlApplicationContext("classpath:appCtx.xml");

// 더미 도서 목록 등록
BookRegisterService bookRegisterService = 
		ctx.getBean("bookRegisterService", BookRegisterService.class);
// 더미 도서 목록 출력
BookSearchService bookSearchService = 
		ctx.getBean("bookSearchService", BookSearchService.class);
// 더미 회원 목록 등록
MemberRegisterService memberRegisterService = 
		ctx.getBean("memberRegisterService", MemberRegisterService.class);
// 더미 회원 목록 출력
MemberSearchService memberSearchService = 
		ctx.getBean("memberSearchService", MemberSearchService.class);
        
ctx.close();	// 스프링 컨테이너 종료

스프링에서 제공하는 인터페이스(InitializingBean/DisposableBean)를 구현하여 빈 객체 생성/소멸 시 실행할 작업을 작성할 수 있다.

빈 객체 생성/소멸 시 실행할 작업 지정 방법
1) 스프링에서 제공하는 인터페이스(InitializingBean/DisposableBean)를 구현
2) init-method, destroy-method 속성 사용

1) InitializingBean/DisposableBean 인터페이스 구현

public class BookDao implements InitializingBean, DisposableBean {

	// 기타 요소 생략
    
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("빈(Bean)객체 생성 단계");
	}

	@Override
	public void destroy() throws Exception {
		System.out.println("빈(Bean)객체 소멸 단계");
	}
}

스프링에서 제공하는 인터페이스를 구현하여 사용한다.

2) init-method, destroy-method 속성 사용

설정파일에서 빈(Bean) 객체를 작성할 때 init-method, destroy-method 속성을 사용한 후 해당 객체의 클래스파일에서 메서드를 작성한다.

<bean id="bookRegisterService" class="com.brms.book.service.BookRegisterService" 
init-method="initMethod" destroy-method="destroyMethod"/>
<bean id="bookSearchService" class="com.brms.book.service.BookSearchService" />
public class BookRegisterService {

	@Autowired
	private BookDao bookDao;
	
	public BookRegisterService() { }
	
	public void register(Book book) {
		bookDao.insert(book);
	}
	
	public void initMethod() {
		System.out.println("BookRegisterService 빈(Bean)객체 생성 단계");
	}
	
	public void destroyMethod() {
		System.out.println("BookRegisterService 빈(Bean)객체 소멸 단계");
	}
}

속성파일에 만든 메서드의 이름과 객체의 클래스파일에 만든 메서드의 이름이 같아야 한다.

어노테이션을 이용한 스프링 설정

XML파일을 Java파일로 변경하기

스프링 빈(Bean)을 만드는 작업을 XML파일이 아닌 Java파일에서 어노테이션을 이용해 적용하는 방법을 알아본다.

  • @Configuration : 해당 파일이 설정파일임을 스프링에 알려주는 어노테이션
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 		http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="studentDao" class="ems.member.dao.StudentDao" ></bean>
	
	
	<bean id="registerService" class="ems.member.service.StudentRegisterService">
		<constructor-arg ref="studentDao" ></constructor-arg>
	</bean>
	
	<bean id="modifyService" class="ems.member.service.StudentModifyService">
		<constructor-arg ref="studentDao" ></constructor-arg>
	</bean>
	
	<bean id="deleteService" class="ems.member.service.StudentDeleteService">
		<constructor-arg ref="studentDao" ></constructor-arg>
	</bean>
	
	<bean id="selectService" class="ems.member.service.StudentSelectService">
		<constructor-arg ref="studentDao" ></constructor-arg>
	</bean>
	
	<bean id="allSelectService" class="ems.member.service.StudentAllSelectService">
		<constructor-arg ref="studentDao" ></constructor-arg>
	</bean>
	
	<bean id="dataBaseConnectionInfoDev" class="ems.member.DataBaseConnectionInfo">
		<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe" />
		<property name="userId" value="scott" />
		<property name="userPw" value="tiger" />
	</bean>
	
	<bean id="dataBaseConnectionInfoReal" class="ems.member.DataBaseConnectionInfo">
		<property name="jdbcUrl" value="jdbc:oracle:thin:@192.168.0.1:1521:xe" />
		<property name="userId" value="masterid" />
		<property name="userPw" value="masterpw" />
	</bean>
	
	<bean id="informationService" class="ems.member.service.EMSInformationService">
		<property name="info">
			<value>Education Management System program was developed in 2015.</value>
		</property>
		<property name="copyRight">
			<value>COPYRIGHT(C) 2015 EMS CO., LTD. ALL RIGHT RESERVED. CONTACT MASTER FOR MORE INFORMATION.</value>
		</property>
		<property name="ver">
			<value>The version is 1.0</value>
		</property>
		<property name="sYear">
			<value>2015</value>
		</property>
		<property name="sMonth">
			<value>1</value>
		</property>
		<property name="sDay">
			<value>1</value>
		</property>
		<property name="eYear" value="2015" />
		<property name="eMonth" value="2" />
		<property name="eDay" value="28" />
		<property name="developers">
			<list>
				<value>Cheney.</value>
				<value>Eloy.</value>
				<value>Jasper.</value>
				<value>Dillon.</value>
				<value>Kian.</value>
			</list>
		</property>
		<property name="administrators">
			<map>
				<entry>
					<key>
						<value>Cheney</value>
					</key>
					<value>cheney@springPjt.org</value>
				</entry>
				<entry>
					<key>
						<value>Jasper</value>
					</key>
					<value>jasper@springPjt.org</value>
				</entry>
			</map>
		</property>
		<property name="dbInfos">
			<map>
				<entry>
					<key>
						<value>dev</value>
					</key>
					<ref bean="dataBaseConnectionInfoDev"/>
				</entry>
				<entry>
					<key>
						<value>real</value>
					</key>
					<ref bean="dataBaseConnectionInfoReal"/>
				</entry>
			</map>
		</property>
	</bean>
	
</beans>

위의 XML설정파일을 아래 Java파일로 변환.

@Configuration
public class MemberConfig {

    // <bean id="studentDao" class="ems.member.dao.StudentDao" />
    @Bean
    public StudentDao studentDao(){
        return new StudentDao();
    }

    /*
    <bean id="registerService" class="ems.member.service.StudentRegisterService">
		<constructor-arg ref="studentDao" ></constructor-arg>
	</bean> */
    @Bean
    public StudentRegisterService registerService(){
        return new StudentRegisterService(studentDao());
    }

    @Bean
    public StudentModifyService modifyService(){
        return new StudentModifyService(studentDao());
    }

    @Bean
    public StudentDeleteService deleteService(){
        return new StudentDeleteService(studentDao());
    }

    @Bean
    public StudentSelectService selectService(){
        return new StudentSelectService(studentDao());
    }

    @Bean
    public StudentAllSelectService allSelectService(){
        return new StudentAllSelectService(studentDao());
    }

    @Bean
    public DataBaseConnectionInfo dataBaseConnectionInfoDev(){
        DataBaseConnectionInfo infoDev = new DataBaseConnectionInfo();
        infoDev.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:xe");
        infoDev.setUserId("scott");
        infoDev.setUserPw("tiger");
        return infoDev;
    }

    @Bean
    public DataBaseConnectionInfo dataBaseConnectionInfoReal(){
        DataBaseConnectionInfo infoReal = new DataBaseConnectionInfo();
        infoReal.setJdbcUrl("jdbc:oracle:thin:@192.168.0.1:1521:xe");
        infoReal.setUserId("masterid");
        infoReal.setUserPw("masterpw");
        return infoReal;
    }

    @Bean
    public EMSInformationService informationService(){
        EMSInformationService info = new EMSInformationService();
        info.setInfo("Education Management System program was developed in 2015.");
        info.setCopyRight("COPYRIGHT(C) 2015 EMS CO., LTD. ALL RIGHT RESERVED. CONTACT MASTER FOR MORE INFORMATION.");
        info.setVer("The version is 1.0");
        info.setsYear(2015);
        info.setsMonth(1);
        info.setsDay(1);
        info.seteYear(2015);
        info.seteMonth(2);
        info.seteDay(28);

        ArrayList<String> developers = new ArrayList<>();
        developers.add("Cheney");
        developers.add("Eloy");
        developers.add("Jasper");
        developers.add("Dillon");
        developers.add("Kian");
        info.setDevelopers(developers);

        Map<String, String> administrators = new HashMap<String, String>();
        administrators.put("Cheney", "cheney@springPjt.org");
        administrators.put("Jasper", "jasper@springPjt.org");
        info.setAdministrators(administrators);

        Map<String, DataBaseConnectionInfo> dbInfos = new HashMap<String, DataBaseConnectionInfo>();
        dbInfos.put("dev", dataBaseConnectionInfoDev());
        dbInfos.put("real", dataBaseConnectionInfoReal());
        info.setDbInfos(dbInfos);

        return info;
    }
}
// GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationContext.xml");
AnnotationConfigApplicationContext ctx = 
				new AnnotationConfigApplicationContext(MemberConfig.class);

여러개의 설정파일을 하나의 설정파일처럼 적용하기

설정파일이 지나치게 길어지다보면 유지보수 측면에서 불리할 수 있다.
이럴때 설정파일을 여러개로 나누어 작성한다.

→ 보통은 기능별로 나눈다.
예) DB connection을 담당하는 DAO, service, 기타 유틸들

  • 스프링 빈 객체가 아무리 많이 만들어진들 스프링 컨테이너는 단 하나이며 그 안에 빈 객체가 생성된다.
    • A객체를 설정파일1에서 생성했다면 @Autowired를 이용해 설정파일2에서 A객체를 자동주입하여 사용할 수 있다는 뜻.
AnnotationConfigApplicationContext ctx = 
				new AnnotationConfigApplicationContext(MemberConfig1.class, MemberConfig2.class, MemberConfig3.class);

→ 위와 같이 배열형식으로 설정파일을 지정하면 된다.

@Import
@Import어노테이션을 통해 여러개의 파일을 하나의 파일처럼 사용할 수 있다.

@Configuration
@Import({MemberConfig2.class, MemberConfig3.class})
public class MemberConfigImport 

웹 프로그래밍 설계 모델

웹 프로그래밍은 보통 Model1, Model2로 구분한다.

Model 1


장점 : html내에 자바코드를 직접 넣어 개발하므로 개발속도가 빠르다.
단점 : 유지보수 및 코드 가시성이 낮음

Model 2


Model1의 단점을 해결하기 위해 모듈화를 통한 계층분리를 적용했다.
MVC구조라고 부른다.
요즘 대부분의 웹 프로그램은 Model2를 기본으로 한다.

장점 : 기능이 분리되어 있기 때문에 유지보수에 유리하다.
단점 : 구조가 복잡해질 수 있다.

스프링 MVC 프레임워크 설게 구조


HandlerMapping → DispatcherServlet → HandlerAdapter → DispatcherServlet → ViewResolver → DispatcherServlet → View

  1. HandlerMapping : 요청에 따른 알맞은 controller로 요청한다.
  2. HandlerAdapter : controller의 많은 메서드 중 요청에 가장 알맞은 메서드에 요청을 넣고, model로 요청에 대한 응답을 받는다.
  3. ViewResolver : 응답에 가장 적합한 view문서를 찾는다.
  4. View : 데이터를 화면에 표시한다.
  • DispatcherServlet는 spring framework에서 제공되는 객체이다.
  • 모든 요청에 대한 처리가 DispatcherServlet를 거치게 된다.
  • 신호등처럼 요청에 대한 교통정리를 해주는 역할을 한다.

DispatcherServlet의 동작방식에 대한 자세한 내용은 아래 참고자료의 1번 링크를 참고하자.

web.xml애서의 설정
스프링 MVC를 실행하려면 DispatcherServlet를 설정해야 하는데 이 설정은 web.xml에서 해주어야 한다.
이후 controller와 view부분은 개발자가, 나머지는 spring에서 자동으로 처리한다.

스프링 MVC 웹서비스

실제로 서비스할때는 웹 서버를 따로 만들고 그 안에 웹컨테이너로 Tomcat을 이용하곤 한다.
톰캣 설치 및 IDE 연동방법은 알고있으므로 생략.

스프링 MVC프레임워크를 이용한 웹프로젝트 분석

Service & Dao 객체 구현

순수 Java를 사용할때 new 키워드로 새로운 객체를 생성하는것과 달리 Spring을 사용하면 어노테이션을 이용해 객체를 생성 및 주입하여 사용한다.

1) Service 객체 등록
방법 1.

MemberService service = new MemberService();

방법 2.

<beans:bean id="service" class="com.bs.lec17.member.service.MemberService"></beans:bean>

@Autowired
MemberService service;

방법 3.

@Service
public class MemberService implements IMemberService { }

@Autowired
MemberService service;

보통은 3번 방법을 많이 사용한다.

2) Dao 객체 등록
@Component 혹은 @Repository 어노테이션을 이용하여 빈 등록을 한 후 생성자 주입 등을 사용해 service에서 객체를 주입해 사용한다.

@Repository
public class MemberDao implements IMemberDao { }


@Autowired
MemberDao dao;

Controller 객체 구현

예전에는 @RequestMapping 어노테이션을 사용했지만 요즘은 거의 @GetMappring, @PostMapping 등의 RESTapi 기반의 어노테이션을 사용한다.

공통 url은 컨트롤러 클래스에 @RequestMapping 어노테이션을 이용해 지정해두면 중복작업을 생략할 수 있다.

보통은 커맨드 객체(entity, dto class)를 생성하여 프론트로부터 값을 받아오는 방법을 사용한다.

@Controller
@RequestMapping("/member")
public class MemberController {
	// 생략
    
    @PostMapping("/memJoin")
    public String memJoin(Member member)
    // 서비스 단 작업
    return "memJoinOk";
}
ID : ${member.memId}
PW : ${member.memPw}

05. 연결

세션과 쿠키

웹 서비스는 HTTP 프로토콜을 기반으로 한다.
HTTP 프로토콜은 클라이언트와 서버의 관계를 유지하지 않는 특징Connectionless 이 있다.

관계를 유지하지 않으면 고객이 앞선 요청에서 넘긴 데이터를 확인할 수 없으므로 이러한 단점을 해결하기 위해 세션과 쿠키를 사용한다.

세션과 쿠키 모두 클라이언트와 서버의 연결을 유지하기 위해 사용한다.

1) 세션

서버에서 연결정보를 관리한다.

public String memLogin(Member member, HttpServletRequest request) {
	Member mem = service.memberSearch(member);
    HttpSession session = request.getSession();
    session.setAttribute("member", mem);
	// 생략
}

public String memLogin(Member member, HttpSession session) {
	Member mem = service.memberSearch(member);
	session.setAttribute("member", mem);
    // 생략
}
 
  @RequestMapping("/logout")
 public String memLogout(Member member, HttpServletRequest request)
 	// 생략
 	HttpSession session = request.getSession();
 	session.invalidate(); // 세션삭제
    return "/member/logoutOk";
}
 
 @RequestMapping("/logout")
 public String memLogout(Member member, HttpSession session)
 	// 생략
 	session.invalidate(); // 세션삭제
    return "/member/logoutOk";
}

HttpServletRequestHttpSession의 차이는 거의 없으며 세션객체를 얻는 방법에 약간의 차이가 있다.

HttpServletRequest

  • 파라미터로 HttpServletRequest를 받은 후 getSession()으로 세션을 얻음.

    HttpSession

  • 파라미터로 HttpSession을 받아 세션 사용.

2) 쿠키

클라이언트에서 연결정보를 관리한다.

@RequestMapping("/main")
 public String mallMain(Mall mall, HttpServletResponse response){
   Cookie genderCookie= new Cookie("gender", mall.getGender());
   
   if(mall.isCookieDel()) {
   	genderCookie.setMaxAge(0);	// 쿠키 삭제(유지시간 0 처리)
   	mall.setGender(null);
   } else {
   	genderCookie.setMaxAge(60*60*24*30);	// 쿠키 유지시간 설정
   }
   response.addCookie(genderCookie);
   
   return "/mall/main";
 }

 @RequestMapping("/index")
 public String mallIndex(Mall mall, @CookieValue(value="gender", required=false) Cookie genderCookie, HttpServletRequest request) {
 	if(genderCookie != null) 
	mall.setGender(genderCookie.getValue());
 	
    return "/mall/index";
 }

@CookieValuevalue에 명시한 쿠키가 없을 경우 예외가 발생한다.
required=false설정 시(기본: true) 명시한 쿠키가 없어도 예외가 발생하지 않는다.
파라미터로 값을 받아올때와 같은 원리라고 생각하면 된다.

리다이렉트와 인터셉트

작성중...


🔗참고자료

  1. [Spring] Dispatcher-Servlet(디스패처 서블릿)이란? 디스패처 서블릿의 개념과 동작 과정
profile
천 리 길도 가나다라부터

0개의 댓글