본문 바로가기
Spring

2024_07_31_수

by 알케니브 2024. 7. 31.

오늘의 코딩순서

(폴더: oBootHello) (줌 강의 10:25 ~ )

메인페이지 http://localhost:8381/members/memberForm

  • (어제 강의의 DI방식) MemberController.class + MemberService.class + memoryMemberRepository.interface

(폴더: oBootDbConnect ) (줌 강의 11:00~)

메인페이지 http://localhost:8382/

  • application.properties
  • Member7.class + memberList.html + createMemberForm.html + MemberController.class (현장 HW 3) + MemberService.class (현장 HW 2) + MemberRepository.interface + MemoryMemberRepository.class (현장 HW 1) + index.html
  • HomeController.class + home.html
  • jdbcMemberRepository.class

 

오늘의 코딩 포인트

(폴더: oBootHello) 

2. DI 방식 사용

DB를 이용하지 않고, Memory에 TBL을 보관하여 저장과 조회를 하는 방법으로 코딩하기

  • MemberController.class
    Tip)
    • @Autowired
      • MemberController과 MemberService를 연결(injection)시키는 기능을 함
      • 생성자에 @Autowired 가 있으면 스프링 컨테이너가 해당 타입의 빈을 자동으로 주입해줌
      • 객체 의존관계를 외부에서 넣어주는 것을 DI (Dependency Injection), 의존성 주입이라 함
      • 이전 버전에서는 개발자가 직접 주입했고, 여기서는 @Autowired에 의해 Spring이 주입함
    • this.
      • 자기 자신의 메모리를 가리키는 역할을 함
      • 이 주소를 참조 타입인 클래스 변수에 저장해두면 변수를 통해 객체를 사용할 수 있다
      • 동일한 클래스 내에서 객체 자신의 또 다른 생성자를 호출하는 데 사용
    • DI (Dependency Injection, 의존성 주입) 방식을 사용하는 이유
      • 인터페이스를 사이에 둬서 클래스 레벨에서는 의존관계가 고정되지 않도록 하고 런타임 시에 관계를 동적으로 주입하여 유연성을 확보하고 결합도를 낮출 수 있게 해줌
      • 외부에서 개발자가 건드리지 않아도, 컨테이너가 연결을 설정할 수 있게 하기 위해
package com.oracle.oBootHello.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import com.oracle.oBootHello.dto.Member1;
import com.oracle.oBootHello.service.MemberService;

@Controller
public class MemberController {
	private static final Logger Logger = LoggerFactory.getLogger(MemberController.class);
    // 이렇게 선언하고 나면 logger를 쓸 수 있음
	
	// 1. 클래식한 방법
	// MemberService memberService = new MemberService();
	
	// 2. DI ==> 생성자
	private final MemberService memberService;
	
	@Autowired
	public MemberController(MemberService memberService) {
		this.memberService = memberService;
	}
	
	
	@GetMapping(value = "members/memberForm")
    	//괄호안의 값을 따라 template명과 html을 만들기
	public String memberForm() {
		System.out.println("MemberController /members/memberForm Start...");
		
		return "members/memberForm";
        // viewResolver에 의해 DispatcherServlet으로 이동하는 값
        // 즉, memberForm.html로 이동하게 함 
	}
	
	@PostMapping(value= "members/save")
	public String save(Member1 member1) {
		//Java와 달리, getparameter를 쓰지 않고 DTO에서 곧장 객체가 넘어온다
       	//memberService 로 이동
		System.out.println("MemberController /members/save Start...");
		System.out.println("MemberController /members/save member1.getName()->"+member1.getName());
		Long id = memberService.memberSave(member1);
		System.out.println("MemberController /members/save id->"+id);
		
		return "redirect:/";
	}
	
	@GetMapping(value= "members/memberList")
	public String memberListString(Model model) {
		Logger.info("memberList Start...");
		List<Member1> memberLists = memberService.allMembers();
		Logger.info("memberLists.size()-> {}", memberLists.size());
		model.addAttribute("memberLists",memberLists);
		
		return "members/memberList";
	}
	
}
  • MemberService.class
    Tip)
    • @Service
      • 스프링 프레임워크에서 사용되는 애노테이션 중 하나로, 비즈니스 로직을 처리하는 서비스(Service) 클래스에 적용됨↳ 비즈니스 로직?: 비즈니스 로직은 비즈니스 요구사항에 따라 데이터 처리, 알고리즘, 규칙 등과 관련된 작업을 수행하며, 소프트웨어 시스템에서 실제 비즈니스 요구사항을 구현하기 위한 중요한 부분임.
        이는 조직 또는 기업의 핵심 비즈니스 프로세스나 규칙을 정의하고 구현하는 코드로 이루어져 있음. 
      • 해당 클래스를 스프링의 빈(Bean)으로 등록하는 역할을 함
      • @Service Annotation을 걸지 않고 DI만 기술하면 오류가 뜸 
        ∵Bean이 생성되지 않았고 당연히 memberRepository도 인스턴스화 되지 않음 + final 상수는 인스턴스화 하여 연결하지 않으면 오류가 남
        ∴ @Service를 입력하여 인스턴스화 시킴 => @Autowired(injection)해서 DI 방식 활용가능함 
    • Spring Container
      • Beanfactory ApplicationContext로 구성됨
package com.oracle.oBootHello.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.oracle.oBootHello.dto.Member1;
import com.oracle.oBootHello.repository.MemberRepository;
import com.oracle.oBootHello.repository.MemoryMemberRepository;

@Service
// @Service Annotation을 걸지 않고 DI만 기술하면 오류가 뜸 
// ∵Bean이 생성되지 않았고 당연히 memberRepository가 인스턴스화 되지도 않음
// ++ final 상수는 인스턴스화 하여 연결하지 않으면 오류가 남
// ∴ @Service를 입력하여 인스턴스화시킴 => @Autowired(injection)해서 DI 방식 활용가능함 

public class MemberService {
	// 1. 클래식한 방법
	// MemberRepository memberRepository = new MemoryMemberRepository();
    	// MemberRepository는 interface
        // MemoryMemberRepository()는 실제 구현할 객체
	
	// 2. 생성자 DI 방식 : 한 번만 설정하고 다시는 바꾸지 않겠다는 선언, setter로 변동 불가능
	// MemoryMemberRepository에서 전달된 component화된 값이 여기로 전달됨 
	private final MemberRepository memberRepository;
		//final:상수이므로 나중에 교체 불가능

	
	@Autowired
	public MemberService(MemberRepository memberRepository) {
		this.memberRepository  = memberRepository;
	}
	
	
	// 회원가입
	public long memberSave(Member1 member1) {
		System.out.println("MemberService memberSave start...");
		memberRepository.save(member1);
        	//memberRepository로 이동
		
		return member1.getId();		
	}
	
	public List<Member1> allMembers() {
		System.out.println("MemberService allMembers start...");
		List<Member1> memList = null;
		memList = memberRepository.findAll();
		System.out.println("memList->"+memList.size());
		return memList;
	}
	
	
}

 

  • MemoryMemberRepository.interface
    Tip)
    • @Repository
      • 스프링 프레임워크에서 사용되는 어노테이션 중 하나로, 주로 데이터 엑세스 객체(DAO)를 구현하는 클래스에 적용됨
      • 해당 클래스가 데이터베이스와의 상호작용을 위한 기능을 제공함
      • 예외 변환 및 rollback 등의 데이터 엑세스 예외 변환 처리 기능을 함
      • 빈(Bean)으로 등록하는 역할을 함
      • Data Access Object 나 Persistence Layer에 명시함
        ↳ persistence Layer
        • Persistence Layer의 주요 목적은 데이터를 영구적으로 저장하고 관리함으로써 데이터의 지속성을 보장하는 것
        • 데이터베이스와의 상호작용을 담당하며, 데이터베이스와의 통신, 데이터의 CRUD(Create, Read, Update, Delete) 작업, 데이터베이스 트랜잭션 관리 등을 수행함
비교⭐⭐⭐
(면접질문)
@Repository DAO
공통점 퍼시스턴스 로직에 대한 객체-지향적인 인터페이스를 제공하고,
도메인 로직과 퍼시스턴스 로직을 분리하여 관심의 분리(separation of concerns) 원리를 만족시키는데 목적이 있음
목적 - Repository는 데이터베이스 액세스를 추상화하고 도메인 객체(Entity)를 저장하고 검색하는 데 사용됨

- 로 스프링 데이터 JPA와 같은 ORM(Object-Relational Mapping) 기술과 함께 사용됨

- 도메인 모델을 지원하며, 보다 객체 지향적인 방식으로 데이터 액세스를 수행함
- DAO는 데이터베이스와 상호 작용하기 위한 데이터 액세스 계층을 나타내는 디자인 패턴

-  주요 목적은 데이터베이스에 대한 저수준 데이터 액세스를 캡슐화하고 추상화하는 것

- DAO는 데이터베이스 연결, 쿼리 작성, 데이터 검색 및 업데이트와 같은 데이터 액세스 작업을 처리함
구현방식 자동화된 구현
- 스프링 데이터 JPA와 같은 프레임워크를 사용하면 Repository 인터페이스를 정의하고 구현하지 않아도 됨
- 프레임워크가 자동으로 CRUD(Create, Read, Update, Delete) 메서드를 생성하고 도메인 객체(Entity)와 상호 작용함
- 직접적인 구현: 개발자가 데이터베이스 연결을 열고 닫는 등의 로우 레벨 작업을 수동으로 처리해야 함
package com.oracle.oBootHello.repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;

import com.oracle.oBootHello.dto.Member1;

@Repository
	//MemoryMemberRepository memoryMemberRepository = new MemoryMemberRepository의 역할
	//자체적으로 내부에서 component화 시키고 그 값을 Service로 가져감
public class MemoryMemberRepository implements MemberRepository {
	
	private static Map<Long, Member1> store = new HashMap<Long, Member1>();
    	// 메모리에 저장하기 위해 사용한 객체: Map방식***
        // Map<k,v>에서 k:멤버번호 v:객체번호, Map방식을 통해 통째로 저장
	private static Long sequence = 0L;
    				// 멤버번호 0부터 시작

	@Override
    	// 저장할 프로그램
	public Member1 save(Member1 member1) {
		member1.setId(++sequence);
        	// 멤버번호가 늘어나서 계속 들어와도 처리할 수 있도록 하는 로직
		store.put(member1.getId(), member1);
		System.out.println("MemoryMemberRepository sequence->"+sequence);
		System.out.println("MemoryMemberRepository member1.getName()->"+member1.getName());
		
		return member1;
	}

	@Override
    	// 조회할 프로그램
	public List<Member1> findAll() {
		System.out.println("MemoryMemberRepository findAll start...");
		List<Member1> listMember = new ArrayList<>(store.values());
			// store의 value(Member1)값만 List<Member1>로 돌려주는 로직
		System.out.println("MemoryMemberRepository findAll slistMember.size()->"+listMember.size());

		return listMember;
	}
	

}

 


(폴더: oBootDbConnect)

  • 폴더 생성

DB 연결용 폴더 생성 설정

↳ JSP에 넣어둔 ojdbc6과 버전이 달라서 레거시에서 오류가 날 수 있으니 염두해둘것

  • DB 생성 ==> Member7 TBL 만들기
CREATE TABLE "SCOTT"."MEMBER7" 
   (	"ID"      NUMBER(7), 
	"NAME" VARCHAR2(20 BYTE)
    )
    ;


DB를 이용하는 방법1. 회원등록, 회원정보

메인페이지 

  • application.properties
    Tip)
    • JSP의 Web.xml같은 역할을 함
spring.application.name=oBootDbConnect
server.port=8382
# Oracle Connect
//Spring의 내장 객체들
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/xe
spring.datasource.username=scott
spring.datasource.password=tiger
  • Member7.class
package com.oracle.oBootDbConnect.domain;

public class Member7 {

	private Long	id;
	private String	name;
	
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	
}
  • memberList.html ==> templates안에 templates.members 폴더 만들고나서 그 안에 html만들기
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>회원 조회</h1>
<div class="container">
    <div>
        <table border="1">
            <thead>
            <tr>
                <th>No</th>
                <th>이름</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="member : ${members}">
                <td th:text="${member.id}"></td>
                <td th:text="${member.name}"></td>
            </tr>
            </tbody>
        </table>
    </div>
</div> <!-- /container -->

</body>
</html>
  • createMemberForm.html
<!DOCTYPE html>
<html xmlns="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>회원등록</h1>
<div class="container">
    <form action="/members/newSave" method="post">
        <div class="form-group">
            <label for="name">이름</label>
            <input type="text" id="name" name="name" placeholder="이름을 입력하세요">
        </div>
        <button type="submit">등록</button>
    </form>
</div> <!-- /container -->
</body>
</html>

 10. return된 getId 값이 id에 저장되고, redirect:/ 를 통해 HomeController로 이동

  • MemberController.class (현장 HW 1-3)
     Tip)
    • SpringBean 을 등록하는 2가지 방법 중 첫 번째
      1. 컴포넌트 스캔과 자동 의존관계 설정
package com.oracle.oBootDbConnect.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import com.oracle.oBootDbConnect.domain.Member7;
import com.oracle.oBootDbConnect.service.MemberService;

@Controller
public class MemberController {
	//현장 HW 3. DI 방식
	//  생성자에 @Autowired 가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어줌
	//  객체 의존관계를 외부 에서 넣어주는 것을 DI (Dependency Injection), 의존성 주입이라 함
	//  이전 에서는 개발자가 직접 주입했고, 여기서는 @Autowired에 의해 스프링이 주입
	//  @Component 를 포함하는 다음 애노테이션도 스프링 빈으로 자동 등록된다.
	//    @Controller, @Service, @Repository
	
	//  스프링 빈을 등록하는 2가지 방법
	//    1. 컴포넌트 스캔과 자동 의존관계 설정
	//    2. 자바 코드로 직접 스프링 빈 등록하기
	private final MemberService memberService;
	
	@Autowired
	public MemberController(MemberService memberService) {
		this.memberService = memberService;
	}

	@GetMapping(value = "/members/memberForm")
    			// HandlerMapping 의 역할을 함
	public String createMemberForm() {
	    System.out.println("MemberController /members/memberForm start..");
	    return "members/createMemberForm";
	}
	
	@PostMapping(value = "/members/newSave")
	public String memberSave(Member7 member) {
		System.out.println("MemberController memberSave start...");
		memberService.memberSave(member);
		return "redirect:/";
	}
	
	@GetMapping(value = "/members/memberList")
	public String memberList(Model model) {
		List<Member7> memberList = memberService.findMembers();
		model.addAttribute("members",memberList);
		return "members/memberList";
	}
}
  • MemberService.class (현장 HW 1-2)
package com.oracle.oBootDbConnect.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.oracle.oBootDbConnect.domain.Member7;
import com.oracle.oBootDbConnect.repository.MemberRepository;

@Service
public class MemberService {
	//현장 HW 2
	private final MemberRepository memberRepository;
	
	@Autowired
	public MemberService(MemberRepository memberRepository) {
		this.memberRepository = memberRepository;	
	}
	
	// 회원가입
	public Long memberSave(Member7 member7) {
		System.out.println("MemberService memberSave start...");
		memberRepository.save(member7);
		return member7.getId();
		
	}
	
	// 전체회원 조회
	public List<Member7> findMembers() {
		System.out.println("MemberService findMembers start...");
		return memberRepository.findAll();
		
	}
}
  • MemberRepository.interface
package com.oracle.oBootDbConnect.repository;

import java.util.List;

import com.oracle.oBootDbConnect.domain.Member7;

public interface MemberRepository {
	Member7			save(Member7 member7);
	List<Member7>	findAll();

}
  • MemoryMemberRepository.class (현장 HW 1-1)
package com.oracle.oBootDbConnect.repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;

import com.oracle.oBootDbConnect.domain.Member7;

//현장 HW 1
@Repository
public class MemoryMemberRepository implements MemberRepository {
		// class에서 상속받은 추상메소드는 implements를 꼭 해야함
	
	private static Map<Long, Member7> store = new HashMap<Long, Member7>();
	private static Long sequence = 0L;
	
	@Override
	public Member7 save(Member7 member7) {
		System.out.println("MemoryMemberRepository save start...");
		member7.setId(++sequence);
		store.put(member7.getId(), member7);
		
		System.out.println("MemoryMemberRepository sequence->"+sequence);
		System.out.println("MemoryMemberRepository member7.getName()->"+member7.getName());
		return member7;
	}

	@Override
	public List<Member7> findAll() {
		System.out.println("MemoryMemberRepository findAll start...");
		return new ArrayList<>(store.values());
		
		// return부터의 한 줄이, 아래 세 줄과 같은 기능
		// List<Member7> listMember = new ArrayList<>(store.values());
		// System.out.println("MemoryMemberRepository findAll slistMember.size()->"+listMember.size());
		// return listMember;
	}

}

  • index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a href="/members/memberForm">회원가입(index)</a>
	<a href="/members/memberList">회원목록(index)</a>
</body>
</html>

 11. redirect:/  를 통해 건너온 id 값이 /에 저장되어 실행됨,
이때 static의 index.html이 아닌 home.html이 실행됨

  • HomeController.class
package com.oracle.oBootDbConnect.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {
	
	@GetMapping("/")
	public String home() {
		System.out.println("HomeController home start...");
		return "home";
	}
}
  • home.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>home</h1>
	<a href="/members/memberForm">회원가입(home)</a>
	<a href="/members/memberList">회원목록(home)</a>
</body>
</html>

회원등록
회원 조회

 


DB를 이용하는 방법 2. Member 번호가 아닌, sequencer 이용하여 회원정보 등록

  • DB에 새 sequence 등록

    • JdbcMemberRepository.class (현장 HW 2-1)
      Tip)
      • Spring Bean⭐ ==>@Repository와 관계성 ↑↑
        • Bean은 인스턴스화된 객체를 의미하며, Spring 컨테이너에 등록된 객체를 Spring Bean이라고 함
          ↳ Bean?: 스프링 컨테이너에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트
          즉, 스프링 컨테이너가 관리하는 자바 객체를 뜻하며, 하나 이상의 빈(Bean)을 관리함
        • @Bean 어노테이션을 통해 메서드로부터 반환된 객체를 스프링 컨테이너에 등록함
        • 빈은 클래스의 등록 정보, Getter/Setter 메서드를 포함하며, 컨테이너에 사용되는 설정 메타데이터로 생성됨
          ↳ 설정 메타데이터?: XML 또는 자바 어노테이션, 자바 코드로 표현하며, 컨테이너의 명령과 인스턴스화, 설정, 조립할 객체 등을 정의함
        • JdbcMemberRepository나 MemoryMemberRepository를 둘 다 실행할 때, @Repository는 하나만 사용가능함 ==> 따라서 나머지는 주석처리하거나 지워줘야함
          즉, SingleBean만 필요하고 두 개 이상은 오류나므로, 여기서는 MemoryMemberRepository.class의 @Repository를 주석처리해줌
        • Oracle이 아닌 다른 프로그램을 사용하게 된다 하더라도 유지보수와 외부 컨텍스트 주입, 부품 교체 등이 쉬워지는 장점이 있음
        • @Component 를 포함하는 다음 애노테이션도 스프링 빈으로 자동 등록됨
          ==> @Controller, @Service, @Repository
      • DataSourceUtils
        • JDBC 코드를 직접 짤 때 트랜잭션을 이용하는 방법중 하나
        • 버전이 올라가도 호출만 하면 알아서 메모리를 최적화해주는 효율적인 객체이기 때문에 자주 사용함
        • Connection을 직접 사용하는 방식에서는 트랜잭션 동기화를 위해 Connection을 계속 파라미터로 주고받았지만, Spring 에서는 트랜잭션 동기화 매니저를 통해 DataSourceUtils를 사용하여 Connection을 close, getConnection을 활용함
        • DataSourceUtils.releaseConnection(): 동기화된 Connection은 닫지 않고 그대로 유지하고, 트랜잭션 동기화 매니저가 관리하는 커넥션이 없는 경우는 바로 Connection을 닫음
        • IllegalStateException: @RequestMapping의 값이 중복되어 나타나는 에러
      • 시퀸스명_seq.nextval
        • 형식: sequence를 사용 => values(시퀸스명(board_seq).nextval,?,?...)
package com.oracle.oBootDbConnect.repository;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Repository;

import com.oracle.oBootDbConnect.domain.Member7;

@Repository
public class JdbcMemberRepository implements MemberRepository {
	// JDBC 사용
	private final DataSource dataSource;
	
	@Autowired
	public JdbcMemberRepository(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	
	private Connection getConnection() {
		return DataSourceUtils.getConnection(dataSource);				
	}	
	
    // 현장 HW 2-1
    // DB에 insert 되는 로직 만들기
	@Override
	public Member7 save(Member7 member7) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String sql = "insert into member7(id,name) values(member_seq.nextval,?)";
        	//id는 request 데이터라 들어오지 않았기 때문에, sequence 값으로 넘겨주기
		System.out.println("JdbcMemberRepository save sql->"+sql);
		
		try {
			conn = getConnection();
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, member7.getName());
			pstmt.executeUpdate();
			return member7;
			
		} catch (Exception e) {
			throw new IllegalStateException();
		} finally {
			close(conn, pstmt, rs);
		}		
		
	}
	
    // DB에 있는 내용을 가져와서 ArrayList에 넣기
	@Override
	public List<Member7> findAll() {
		Connection conn = null;
		PreparedStatement pstmt =null;
		ResultSet rs = null;
		String sql = "select * from member7";
		System.out.println("JdbcMemberRepository findAll() sql->"+sql);
		
		try {
			conn = getConnection();
			pstmt = conn.prepareStatement(sql);
			rs = pstmt.executeQuery();
			
			List<Member7> members = new ArrayList<>();
			while(rs.next()) {
				Member7 member = new Member7();
				member.setId(rs.getLong("id"));
				member.setName(rs.getString("name"));
				members.add(member);
			}
			return members;
			
		} catch (Exception e) {
			throw new IllegalStateException();
		} finally {
			close(conn, pstmt, rs);
		}
	}

		// 메모리 해제
	private void close(Connection conn , PreparedStatement pstmt , ResultSet rs)
	{
    	//JSP에서 한 방식으로 close를 해도 되고, 아래의 방식으로 해도 됨
		try {
			if (rs != null) rs.close();
		}   catch (SQLException e) {
				e.printStackTrace();
	    }
	     
	    try {
	         if (pstmt != null) 	pstmt.close();
		}    catch (SQLException e) {
				e.printStackTrace();
	    }
	     
	    try {
	         if (conn != null) 		close(conn);
		}    catch (SQLException e) {
				e.printStackTrace();
	    }		
	}
	
	private void close(Connection conn) throws SQLException {
		DataSourceUtils.releaseConnection(conn, dataSource);
		
	}
	

}

 

 


질문목록

 


수업교재

1. FrameWork ⭐⭐

2. 종류 ==> 면접에 질문이 나오면  정의와 함께 종류 다섯 가지를 설명하기

1. CORE: IoC, DI, DDD를 기반으로하는 디자인 패턴

  1. IOC (Inversion Of Control)
    • IOC의 개념
      1. 기존의 프로그래밍에서 객체의 생성, 제어, 소멸 등의 객체의 라이프 사이클을 개발자가 관리하던 것을 컨테이너 에게 그 제어권 위임하는 프로그래밍 기법
      2. 특정 작업을 수행하기 위해 필요한 다른 컴포넌트들을 직접 생성하거나 획득하기보다는 이러한 의존성들을 외부에 정의하고 컨테이너에 의해 공급받는 프로그래밍기법. 객체의 생성에서부터 생명주기의 관리까지 모든 객체에 대한 제어권이 바뀌었다는 것을 의미
    • IOC 적용 장점
      1. 유지보수 용이성: Loosely coupling을 통해 코드변경에 쉽게 대처가 가능하여 유지보수가 용이
      2. 용이한 환경설정: 어플리케이션 로직으로부터 의존관계를 분리하여 상황에 따라 자유로운 환경 설정이 가능
      3. 재사용 용이성: 의존관계를 일일이 Lookup할 필요없이 외부에서 조립하여 재사용성이 강화됨
      4. 테스트 용이성: 의존관계에 대한 고려를 최소화하여 컴포넌트를 개별적으로 테스트할 수 있음. Mock 객체를사용하여 DB를 사용하지 않고도 테스트 가능
    • 구현 방법
      1. DL(Dependency Lookup) 의존성 검색
        저장소에 저장되어 있는 빈(Bean)에 접근하기 위하여 개발자들이 컨테이너에서 제공하는 API를 이용하여 사용하고자 하는 빈(Bean)을 Lookup 하는 것 
      2. DI(Dependency Injection) 의존성 주입
        • 각 계층사이, 각 클래스 사이에 필요로 하는 의존관계를 외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴
        • 인터페이스를 사이에 둬서 클래스 레벨에서는 의존관계가 고정되지 않도록 하고 런타임 시에 관계를 동적으로 주입하여 유연성을 확보하고 결합도를 낮출 수 있게 해줌
        • DL 사용시 컨테이너 종속성이 증가하여, 이를 줄이기 위하여 DI를 사용
        • 종류: Setter Injection, Constructor Injection, Method Injection
    • IOC의 종류
      • Setter Injection
        • 인자가 없는 생성자나 인자가 없는 static factory 메소드가bean를 인스턴스화 하기 위해 호출된 후 bean의 Setter 메소드를 호출하여 실체화하는 방법
        • 객체를 생성 후 의존성 삽입 방식이기에 구현시에 좀 더 유연하게 사용
        • 세터를 통해 필요한 값이 할당되기 전까지 객체를 사용할 수 없음
        • Spring 프레임워크의 빈 설정파일에서 property 사용
        • 장점
          1. 생성자 Parameter 목록이 길어지는 것 방지
          2. 생성자의 수가 많아지는 것 방지
          3. Circular dependencies 방지
      • Constructor Injection
        • 생성자를 이용하여 클래스 사이의 의존관계를 연결
        • Setter 메소드를 지정함으로 생성하고자 하는 객체가 필요로 하는 것을 명확하게 알 수 있음
        • Setter 메소드를 제공하지 않음으로 간단하게 필드를 불변값으로 지정이 가능
        • 생성자의 파라미터가 많을 경우 코드가 복잡해 보일 수 있음
        • 조립기 입장에서는 생성의 순서를 지켜야 하기에 상당히 불편함
        • Spring 프레임워크의 빈 설정파일에서 Constructor-arg 사용
        • 장점
          1. 강한 의존성 계약강제
          2. Setter 메소드 과다사용억제
          3. 불필요한 Setter 메소드를 제거함으로써 실수로 속성 값을 변경하는 일을 사전에 방지

오늘의 숙제

'Spring' 카테고리의 다른 글

2024_08_06_화~08_07_수  (0) 2024.08.06
2024_08_05_월~08_06_화  (0) 2024.08.05
2024_08_02_금  (0) 2024.08.02
2024_08_01_목  (0) 2024.08.01
2024_07_30_화  (0) 2024.07.30