목차

    DI(Dependency injection)

    DI란 스프링이 다른 프레임워크와 차별화되어 제공하는 의존 관계 주입 기능으로, 객체를 직접 생성하는 게 아니라 외부에서 생성한 후 주입 시켜주는 방식이다. DI(의존성 주의)를 통해서 모듈 간의 결합도가 낮아지고 유연성이 높아진다.
    객체 생성 방식 설명
    기존방식
    A객체가 B, C객체를 new 생성자를 통해서 직접 생성하는 방법
    *의존성 주입 방식*
    외부에서 생성 된 객체를 setter()를 통해 사용하는 방법

    - A객체에서 B, C객체를 사용(의존)할 때, A객체에서 직접 생성하는 것이 아니라 외부(IOC컨테이너)에서 생성된 B, C객체를 조립(주입) 시켜 setter 혹은 생성자를 통해 사용하는 방식이다.

    - 스프링에서는 객체를 Bean 이라고 부르며, 프로젝트가 실행될때 사용자가 Bean으로 관리하는 객체들의 생성과 소멸에 관련된 작업을 자동적으로 수행해주는데 객체가 생성되는 곳에 스프링에서는 Bean 컨테이너라고 한다.

    의존성 주입이 생겨난 이유

    public class BugService {
        public void countLeg(){
            BugRepository bug = new Fly();
            bug.legCount();
        }
    }

    위 처럼 new 를 통해 직접 객체를 생ㅅ헝하면 BugRepository는 Fly클래스에 의존 되어버린다.

    내가 Fly가 아니라 다른 객체를 사용하고 싶어도 코드를 수정하기 전까진 불가능하다. 

     

    public class BugService {
        private BugRepository bugRepository;
    
        public BugService(BugRepository bugRepository){
            this.bugRepository = bugRepository;
        }
    
        public void countLeg(){
            bugRepository.legCount();
        }
    }
    
    //Test
    @Test
    public void testLeg(){
        BugRepository bug = new LadyBug(); // Fly(), Mantis()... 등등
        BugService bugService = new BugService(bug); //bugService의 생성자로 의존성주입!
        bugService.countLeg();
    }

     

    이렇게 생성자로 어떤 객체를 받아서 BugRepository를 생성해주면 의존성을 주입받았다고 할 수 있다. 즉 Test 쪽에서 보면 bug를 여러가지로 생성가능하다. 따라서 BugService에 넘겨주는 객체에 따라 의존성을 주입받을 수 있다.

    의존성 주입 방법 

    생성자를 이용하는 방법

     

    • 장점
      • 필수적으로 사용해야 하는 레퍼런스 없이는 인스턴스를 만들지 못하도록 강제함
      • 테스트 코드 작성시 생성자를 통해 의존성 주입 용이함
    • 단점
      • 어쩔 수 없는 순환 참조는 생성자 주입으로 해결하기 어려움(가급적 순환참조 발생하지 않는게 중요)
      • 순환 참조? A가 B가 참조하고 B가 A를 참조하는 경우
    @Service
    public class BugService {
    
    private BugRepository bugRepository;
        @Autowired
        public BugService(BugRepository bugRepository){
            this.bugRepository = bugRepository;
        }
    }

    Field 변수를 이용한 방법

    • 장점 
      • 간단하다.
    • 단점
      • 의존 관계가 눈에 잘 보이지 않아 추상적이고, 이로 인해 의존성 관계가 과도하게 복잡해질 수 있다.
      • SRP : 단일책임원칙에 반하는 안티패턴
      • 단위 테스트시 의존성 주입이 용이하지 않음
    @Service
    public class BugService {
        @Autowired
        private BugRepository bugRepository;
    }

    setter를 이용한 방법

    • 장점
      • 의존성이 선택적으로 필요한 경우에 사용(set을 불러올때 사용하니깐!?)
      • 생성자에 모든 의존성을 기술하면 과도하게 복잡해질 수 있는 것으로 선택적으로 나눠 주입 할 수 있게 부담을 덜어줌
      • 생성자 주입과 setter 주입 방법을 적절하게 분배하여 사용을 권장
    @Service
    public class BugService {
    
        private BugRepository bugRepository;
    
        @Autowired
        public void setBugRepository(BugRepository bugRepository) {
            this.bugRepository = bugRepository;
        }
    }

    DI(Dependency Injection) 세 가지 방법

    느슨한 결합

    - 객체를 주입 받는다는 것은 외부에서 생성된 객체를 인터페이스를 통해서 넘겨받는 것이다. 이렇게 하면 결합도를 낮출수 있고, 런타임시에 의존관계가 결정되기 때문에 유연한 구조를 가진다.

    - SOULD 원칙에서 O에 해당하는 Open Closed Principle을 지키기 위해서 디자인 패턴 중 전략 패턴을 사용하게 되는데, 생성자 주입을 사용하게 되면 전략 패턴을 사용하게 된다.

     

    Fielid Injection 필드 주입

    @Component
    public class SampleController {
        @Autowired
        private SampleService sampleService;
    }

    Field Injection을 사용하면 안되는 이유

    • 단일 책임(SRP)의 원칙 위반

    의존성을 주입하기가 쉽다.
    @Autowired 선언 아래 개수 제한 없이 무한정 추가할 수 있으니 말이다.

    여기서 Constructor Injection을 사용하면 다른 Injection 타입에 비해 위기감을 느끼게 해준다.

    Constructor의 parameter가 많아짐과 동시에 하나의 Class가 많은 책임을 떠안는다는 걸 알게된다.

    이때 이러한 징조들이 Refactoring을 해야한다는 신호가 될 수 있다.

    Setter Injection 세터 주입

    @Component
    public class SampleController {
        private SampleService sampleService;
     
        @Autowired
        public void setSampleService(SampleService sampleService) {
            this.sampleService = sampleService;
        }
    }

    Construtor Injection 생성자 주입 (권장)

    아래 처럼 Constructor에 @Autowired Annotation을 붙여 의존성을 주입받을 수 있다.

    @Component
    public class SampleService {
        private SampleDAO sampleDAO;
     
        @Autowired
        public SampleService(SampleDAO sampleDAO) {
            this.sampleDAO = sampleDAO;
        }
    }
    
    @Component
    public class SampleController {
    
    	private final SampleService sampleService = new SampleService(new SampleDAO());
        
    	...
    }

    Spring Framework Reference에서 권장하는 방법은 생성자를 통한 주입이다.

    생성자를 사용하는 방법이 좋은 이유는 필수적으로 사용해야하는 의존성 없이는 Instance를 만들지 못하도록 강제할 수 있기 때문이다.

    Spring 4.3버전부터는 Class를 완벽하게 DI Framework로부터 분리할 수 있다.

    단일 생성자에 한해 @Autowired를 붙이지 않아도 된다.
    Spring 4.3부터는 클래스의 생성자가 하나이고 그 생성자로 주입받을 객체가 Bean으로 등록되어 있다면 @Autowired를 생략할 수 있다.

    또한 앞서 살펴본 Field Injection의 단점들을 장점으로 가져갈 수 있다.

     

    • null을 주입하지 않는 한 NullPointerException 은 발생하지 않는다.

    의존관계 주입을 하지 않은 경우에는 Controller 객체를 생성할 수 없다.
    즉, 의존관계에 대한 내용을 외부로 노출시킴으로써 컴파일 타임에 오류를 잡아낼 수 있다.

    • final 을 사용할 수 있다.

    final로 선언된 레퍼런스타입 변수는 반드시 선언과 함께 초기화가 되어야 하므로 setter 주입시에는 의존관계 주입을 받을 필드에 final 을 선언할 수 없다.

    final의 장점은 객체가 불변하도록 할 수 있는 점으로, 누군가가 Controller 내부에서 Service 객체를 바꿔치기 할 수 없다는 점이다.

    • 순환 의존성을 알 수 있다.

    앞서 살펴 본 Field Injection에서는 컴파일 단계에서 순환 의존성을 검출할 방법이 없지만, Construtor Injection에서는 컴파일 단계에서 순환 의존성을 잡아 낼 수 있다.

    • 의존성을 주입하기가 번거로워 위기감을 느낄 수 있다.

    Construtor Injection의 경우 생성자의 인자가 많아지면 코드가 길어지며 개발자로 하여금 위기감을 느끼게 해준다.

    이를 바탕으로 SRP 원칙을 생각하게 되고, Refactoring을 하게 된다.

    이러한 장점들 때문에 스프링 4.x Documents에서는 Constructor Injection을 권장한다.

     

    굳이 Setter Injection을 사용하려면, 합리적인 default를 부여할 수 있고 선택적인(optional) 의존성을 사용할 때만 사용해야한다고 말한다.
    그렇지 않으면 not-null 체크를 의존성을 사용하는 모든 코드에 구현해야한다.

    결국 더 좋은 디자인 패턴과 코드 품질을 위해서는 Constructor Injection을 사용해야 한다.

    참고 : https://velog.io/@gillog/Spring-DIDependency-Injection-%EC%84%B8-%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95

    IoC(Inversion of Control)

    IoC란 '제어의 역전' 이라는 의미로 말 그대로 메소드나 객체의 호출작업을 개발자가 아닌 외부에서 결정되는 것이다. 스프링이 모든 의존성 객체를 스프링이 실행될때 다 만들어주고 필요한 곳에 주입시켜줌으로써 Bean들은 싱글턴 패턴의 특징을 가진다.

    'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

    Spring AOP 개념  (0) 2022.01.21
    Spring 커넥션풀(c3p0)  (0) 2022.01.09
    Spring JDBC 연동 & JDBC Template  (0) 2022.01.08
    리다이렉트, 인터셉트  (0) 2022.01.06
    세션, 쿠키  (0) 2022.01.03
    AOP에 대하여

    - 인프라 로직 (모든 서비스에 로그를 찍는 함수를 만들어라 (서비스 메서드:1203342개))

    • 애플리케이션의 전 전영역에서 나타날 수 있음
    • 중복코드를 만들어낼 가능성 때문에 유지보수가 힘들어짐
    • 비즈니스 로직과 함께 있으면 비즈니스 로직을 이해하기 어려워짐(코드가 복잡해짐)
    AOP 설명
    * 로그인 기능, 글 작성 기능, 글 삭제 기능

    횡단 관심사 (cores-cutting concern)
    중복이 되는 인프라 로직은 횡단으로 나타난다. (중복코드)

    - Aspect-Oriented Programming (OOP랑 대치되는 개념 아니라 보완하는 개념임) 

    AOP 시작하기
       
    AOP를 사용하기 위해서는 다음과 같은 Annotation들을 알아야 한다.
    참고 https://programforlife.tistory.com/107

     

       
    - UselessAdvice
    @Aspect 어노테이션
    @Component 어노테이션

    - stopWatch 기능(중복코드 발생여지가 있는 인프라 로직)
    @Around("excution(*org.aaa.aaa.AuthServiceImple)
    @Around : advice
    execution.. : point cut : 어떤 메서드에 적용 할 것인지.?


    중간에 프록시를 이용해서 갈아끼우는 기념?

     

     

     

    Spring AOP 사용(supported by @AspectJ)
    • Target
      • 어떤 대상에 부가 기능을 부여할 것인가?
    • Advice
      • 어떤 부가 기능? Before, AfterReturng, AfterThrowing, After, Around
    • Join Point
      • 어디에 적용할 것인가? 메서드, 필드, 객체, 생성자 등
    • Point cut
      • 실제 advice가 적용될 지점, Spring AOP에서는 advice가 적용될 메서드를 선정
    AOP의 구현 방법 (적용 시점)
    • 컴파일 시
      • J.java - > J.class
    • 클래스 로드 시
      • J.class
    • 프록시 패턴
      • 패턴 방법(Ioc, DI)이용
    Spring AOP와 AspectJ
       
     

    참고

    https://calgaryhomeless.tistory.com/6

     

    (개념) Spring AOP를 구현하는 Proxy Pattern

     스프링이 제공해주는 제일 큰 기능으로는 IoC, AOP, PSA가 있다. 이중 AOP는 Aspect Oriented Programming의 줄임말이라고 하는데 강의를 들어보니 Aspect가 핵심이다. Aspect는 관점이라는 뜻이 있는데 나는..

    calgaryhomeless.tistory.com

    https://www.youtube.com/watch?v=Hm0w_9ngDpM 

     

    'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

    DI(Dependency injection)  (0) 2022.01.24
    Spring 커넥션풀(c3p0)  (0) 2022.01.09
    Spring JDBC 연동 & JDBC Template  (0) 2022.01.08
    리다이렉트, 인터셉트  (0) 2022.01.06
    세션, 쿠키  (0) 2022.01.03

    목차 돌아가기

    Spring 커넥션풀
    데이터베이스 연결을 미리 준비해 놓고 사용하는 방법
    25-1 c3p0 모듈의 CombopolledDataSource
       
    'c3p0'를 이용해서 dataSource에 db정보를 set 해준다.
    25-2 스프링 설정파이를 이용한 DataSource 설정
       
    스프링 설정파일을 통해서 dataSource를 저장한다.
    new를 선언하는 방식(bean 등록x)
    //1. dataSource 선언
    private ComboPooledDataSource dataSource;
    //2. new
    dataSource = new ComboPooledDataSource();
    //3. db정보 set
    dataSource..setDirver(driver);
    dataSource.setJdbcUrl(url);
    dataSource.setUser(userId);...
    //4. template 연동
    template = new JdbcTemplate();
    template.setDataSource(dataSource);
    bean 등록(servlet-context.xml) -> 객체 @AutoWired(권장)
    <!-- bean 등록 -->
    <beans:bean id ="dataSource" class="com.hchange.v2.c3p0.ComPooledDataSource">
    	<beans:property name="dirverClass" value="oracle..."/>
    ...
    </beans>
    @Autowired
    public MenberDao(ComboPooledDataSource dataSource){
    	this,template = new JdbcTemplate(dataSource);
    }
    Config 방법 -> @Autowired (권장)
    @Configuration
    public class DBconfig { 
    	
        @Bean
        public ComPooledDataSource dataSource() throws PropertyVetoExcetion(){
        ComPooledDataSource dataSource = new ComPooledDataSource();
        
        dataSource.setDriver("oracle...");
        ...
        return dataSource;
    }

    'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

    DI(Dependency injection)  (0) 2022.01.24
    Spring AOP 개념  (0) 2022.01.21
    Spring JDBC 연동 & JDBC Template  (0) 2022.01.08
    리다이렉트, 인터셉트  (0) 2022.01.06
    세션, 쿠키  (0) 2022.01.03

    목차 돌아가기

    Java 언어를 사용해서 DB와 통신하기 위한 방벙베 대해서 학습
    23-1 기본 SQL
    • 테이블 생성
    CREATE TABLE member (
        memId VARCHAR2(10) CONSTARINT mmdId_pk PRIMARY KEY,
        memPw VARCHAR2(10),
        memMail VARCHAR2(15),
        memPurcNum NUMBER(3) DEFAULT 0 CONSTARINT memPurcNum_ck CHECK (memPurcNum) < 3 )
    )l
    • 테이블 계정(컬럼) 삽입
    INSERT INTO member (memId, memPw, memMail)
    values ('b', 'bb', 'bbb@gmail.com');
    • 테이블에서 'memId'가 'b'인 회원을 삭제한다.
    DELETE FROM memeber WHERE memId = 'b';
    • 테이블의 모든 회원정보를 출력한다.
    SELECT * FROM member;
    • 테이블을 삭제한다.
    DROP TABLE member;
    23-2 JDBC
    JDBC 흐름 중요내용
    SQL작성 및 전송 까지는 개발자가 직접해야한다. (매번 바뀌니깐)
    하지만 자원해제는 개발자가 딱 한 번만만 해도 된다. 그래서 JdbcTemplate가 나오는 것이다.
    JDBC INSERT
    @Override
    	public int memberInsert(Member member) {
    		
    		int result = 0;
    		
    		try {
    			Class.forName(driver);
    			conn = DriverManager.getConnection(url, userid, userpw);
    			String sql = "INSERT INTO member (memId, memPw, memMail) values (?,?,?)";
    			pstmt = conn.prepareStatement(sql);
    			pstmt.setString(1, member.getMemId());
    			pstmt.setString(2, member.getMemPw());
    			pstmt.setString(3, member.getMemMail());
    			result = pstmt.executeUpdate();
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if(pstmt != null) pstmt.close();
    				if(conn != null) conn.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    		
    		return result;
    		
    	}
    JDBC SELECT
    @Override
    	public Member memberSelect(Member member) {
    		
    		Member mem = null;
    		
    		try {
    			
    			Class.forName(driver);
    			conn = DriverManager.getConnection(url, userid, userpw);
    			String sql = "SELECT * FROM member WHERE memId = ? AND memPw = ?";
    			pstmt = conn.prepareStatement(sql);
    			pstmt.setString(1, member.getMemId());
    			pstmt.setString(2, member.getMemPw());
    			rs = pstmt.executeQuery();
    			
    			while (rs.next()) {
    				String memId = rs.getString("memid");
    				String memPw = rs.getString("mempw");
    				String memMail = rs.getString("memMail");
    				int memPurcNum = rs.getInt("memPurcNum");
    				
    				mem = new Member();
    				mem.setMemId(memId);
    				mem.setMemPw(memPw);
    				mem.setMemMail(memMail);
    				mem.setMemPurcNum(memPurcNum);
    			}
    			
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if(rs != null) rs.close();
    				if(pstmt != null) pstmt.close();
    				if(conn != null) conn.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    		
    		return mem;
    		
    	}
    JDBC UPDATE
    @Override
    	public int memberUpdate(Member member) {
    		
    		int result = 0;
    		
    		try {
    			
    			Class.forName(driver);
    			conn = DriverManager.getConnection(url, userid, userpw);
    			String sql = "UPDATE member SET memPw = ?, memMail = ? WHERE memId = ?";
    			pstmt = conn.prepareStatement(sql);
    			pstmt.setString(1, member.getMemPw());
    			pstmt.setString(2, member.getMemMail());
    			pstmt.setString(3, member.getMemId());
    			result = pstmt.executeUpdate();
    			
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if(pstmt != null) pstmt.close();
    				if(conn != null) conn.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    		
    		return result;
    		
    	}
    JDBC DELETE 
    	@Override
    	public int memberDelete(Member member) {
    		
    		int result = 0;
    		
    		try {
    			
    			Class.forName(driver);
    			conn = DriverManager.getConnection(url, userid, userpw);
    			String sql = "DELETE member WHERE memId = ? AND memPw = ?";
    			pstmt = conn.prepareStatement(sql);
    			pstmt.setString(1, member.getMemId());
    			pstmt.setString(2, member.getMemPw());
    			result = pstmt.executeUpdate();
    			
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if(pstmt != null) pstmt.close();
    				if(conn != null) conn.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    		
    		return result;
    		
    	}
    소스들의 자원해제 부분이 너무 중복된 코드들이 많다라는 단점이 발생한다.
    해결 : JDBC Template
    사실상 JDBC는 쓸 일이 없고 JDBC Template를 사용한다.

    JDBC Template

    Java언어를 사용해서 DB 연동하는 방법 학습

    24-1 JDBC의 단점을 보완한 JdbcTemplate
       
    반복되고 동일한 작업을 막기 위해 'JdbcTemplte'를 사용
    24-2 DataSource클래스
    제공 클래스  
    c3p0 : 커넥션 풀 할 때 이용
    pom.xml 의존설정
    maven에 없기 때문에 pom.xml에 추가해줘야 하는 내용
    <!-- DB -->
        <dependency>
           <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>12.1.0.2</version>
        </dependency>
        <!-- JDBC Template 사용 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.1.6.RELEASE</version>
        </dependency>
        <!-- c3p0 사용 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5</version>
        </dependency>
    Template 사용
    Template 사용 하므로 연결부터 해제까지 각각 안해줘도 된다. 
    방법은 3가지 정도 있다.
    방법(3가지)
    1. PreparedStateMentSetter().. 
    2. PreparedSattementCreator()..
    3. RowMapper<Member>().. 
    //데이터소스(데이터정보저장) 만들기
    private DriverManegerDataSource datasource;
    
    //처음에 초기 설정 한 번만 해준다.
    public MemberDao(){
        datasource = new DriverManegerDataSource();
        datasource.setDriver(driver);
        datasource.setJdbcUrl(url);
        datasource.setUser(userId);
        datasource.setPassword(userpw);
    
        template = new JdbcTemplate();
        template.setDataSource(datasource);
    }
    
    
    //1. 주입 insert
    @Override
    public int memberInsert(Member member){
      ...
      int result = template.update(sql,member.getMemId(),member.getMempw(),member.getMail());
      ...
      return result;
    }
    
    //2. 주입 Select
    @Override
    public Member memberSelect(final Member member) {
    		
    	List<Member> members = null;
    	//final로 해주면 다른 곳에서 사용 못함
    	final String sql = "SELECT * FROM member WHERE memId = ? AND memPw = ?";
    
        members = template.query(sql, new Object[]{member.getMemId(), member.getMemPw()}, new RowMapper<Member>() {
    
            @Override
            public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
                Member mem = new Member();
                mem.setMemId(rs.getString("memId"));
                mem.setMemPw(rs.getString("memPw"));
                mem.setMemMail(rs.getString("memMail"));
                mem.setMemPurcNum(rs.getInt("memPurcNum"));
                return mem;
            }
                
        });
    
        if(members.isEmpty()) 
            return null;
    
        return members.get(0);
    }

    'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

    Spring AOP 개념  (0) 2022.01.21
    Spring 커넥션풀(c3p0)  (0) 2022.01.09
    리다이렉트, 인터셉트  (0) 2022.01.06
    세션, 쿠키  (0) 2022.01.03
    Controller 객체 구현  (0) 2021.12.31

    목차로 돌아가기

    컨트롤러에서 뷰를 분기하는 방법과 컨트롤러 실행 전/후에 특정 작업을 가능하게 하는 방법에 대해서 학습합니다.

    리다이렉트(redirect)
    지금의 페이지에서 특정 페이지로 전환하는 기능
    리다이렉트 구조 내용
    순서
    1) 회원정보 수정 요청
    2) 회원인증 여부 결정(Y/N) : (로그인 되어있나?)
    2-1) Y이면 회원정보 수정 페이지로 유도
    2-2) N이면 return "redirect:/";
    // Modify
    	@RequestMapping(value = "/modifyForm")
    	public String modifyForm(Model model, HttpServletRequest request) {
    		
    		HttpSession session = request.getSession();
    		Member member = (Member) session.getAttribute("member");
    		
    		// 리다이렉트 코드
    		if(null == member) {
    			return "redirect:/";
    		} else {
    			model.addAttribute("member", service.memberSearch(member));
    		}
    		
    		return "/member/modifyForm";
    	}
    인터셉터(interceptor)
    리다이렉트를 하는 경우가 많은 경우 HandlerInterceptor를 사용
    구조 설명
    1) 클라이언트가 요청한다.
    2) 원래면 핸들러,뷰(4,5,7,8)로 바로가야하지만 3, 6, 9를 거치는 인터페이스(HanderfInterceptor)를 발생 시킨다.

    - preHandle() 컨트롤러 작업전에 작동(가장 많이 사용)
    - postHandle() 컨트롤러 작업후에 작동
    - afterHandle() 컨트롤러 뷰 이후에 작동

    직접 구현은 어렵고 HanderfInterceptorAdaptor를 사용(spring에서 사용)
    bean 객체 등록
    mapping으로 적용되는 범위를 한정 지어준다. /member/modifyForm or /member/removeForm 이 작동하면 해당 경로의 인터셉터를 작동시켜라 라는 의미 
    	<interceptors>
    		<interceptor>
    			<mapping path="/member/modifyForm"/>
    			<mapping path="/member/removeForm"/>
    			<beans:bean class="com.bs.lec21.member.MemberLoginInterceptor"/>
    		</interceptor>
    	</interceptors>

     

    'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

    Spring 커넥션풀(c3p0)  (0) 2022.01.09
    Spring JDBC 연동 & JDBC Template  (0) 2022.01.08
    세션, 쿠키  (0) 2022.01.03
    Controller 객체 구현  (0) 2021.12.31
    Service & Dao 객체 구현  (0) 2021.12.30

    목차 돌아가기

    클라이언트와 서버의 연결을 유지하는 방법

    20-1 세션(Session)과 쿠키
      세션 쿠키
    특징
    Connectionless Protocol
    - 웹 서비스는 HTTP 프로토콜을 기반으로 하는데, HTTP 프로토콜은 클라이언트와 서버의 관계를 유지 하지 않는 특징이 있다. 
    - Http 통신은 한 번 연결하고 나서 끝나면 끊어버린다. 그 이유는 클라이언트의 요청이 너무 많아 서버의 부하를 줄이기 위해서이다.

    불편한점 : 이러한 Connectionless Protocol의 불편함을 해결하기 위해서 세션과 쿠키를 이용한다. 세션과 쿠키는 클라이언트와 서버의 연결 상태를 유지해주는 방법으로, 세션은 서버에서 연결정보를 관리하는 반면 쿠키는 클라이언트에서 연결정보를 관리하는데 차이가 있다.
    차이점 서버에서 서버연결정보 관리 클라이언트에서 연결정보 관리 
    20-2 HttpAervletRequest를 이용한 세션 사용
      설명
    서버에 세션 정보가 있다.
    HttpServletRequest 이용

     

    20-3 HttpSession을 이용한 세션 사용
    방법 설명
    HttpSession 이용 HttpServletRequest와 차이점은 거의 없으며, 단지 세션객체를 얻는 방법에 차이가 있을 뿐이다. 단 바로 httpSession을 바로 받았으므로 getSession을 해줄 필요가 없다. (이게 더 편한 것 같다.)
    20-4 세션 삭제 (Invalidate())
      설명
    로그아웃 또는 회원탈퇴 시 session.invalidate();를 통해 세션을 삭제 할 수 있다.
    관련 코드
    20-5 세션 주요 메서드 및 플로어
    자주 쓰이는 메소드  
     
    - 세션에서 자주 쓰이는 메소드 1, 2, 3번 마지막

    20-6 쿠키(Cookie)
    쿠키를 생성하는 방법 설명
    1) mallMain()에서 쿠키를 생성하고, 파라미터로 받은 HttpServletResponse에 쿠키를 담고 있다.
    2) 쿠키를 생성할 때는 생성자에 두 개의 파라미터를 넣어주는데 첫 번째는 쿠키이름을 넣어 주고 두 번째는 쿠키값을 넣어준다.

    - setMaxAge(60*60*24*30) :
    60초 * 60 * 24 * 30 = 1달
    @CookieValue 에노테이션
    : value속성은 쿠키이름을 나타내며 만약 value에 명시한 쿠키가 없을 경우 exception이 발생한다 그런 것을 방지하고자 required 속성이 있다. Required 속성은 기본 true인데 true인 경우 value값에 해당하는 쿠키가 없으면 exception이 발생하고 false이면 exception이 발생하지 않는다.
    실제 실무에선 세션을 사용한다.(보안에 쿠키에 비교적 좋음) 쿠키는 보통 중요정보가 아닐 때 사용한다.

    'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

    Spring JDBC 연동 & JDBC Template  (0) 2022.01.08
    리다이렉트, 인터셉트  (0) 2022.01.06
    Controller 객체 구현  (0) 2021.12.31
    Service & Dao 객체 구현  (0) 2021.12.30
    스프링 MVC 웹서비스  (0) 2021.12.29

    목차 돌아가기

    컨트롤러의 URL 맵핑과 파라미터 처리 방법에 대해서 학습

    18-1 웹 어플리케이션 준비
    주요 구조
    18-2 @RequestMapping을 이용한 맵핑(여러가지 속성)
    html, controller 비교 설명
    *좌측 : Controller 우측: html 파일
    - html의 <form action>에서 액션명과 메서드를 명시한다.
    - method 를 각각 get or porst로 맞춰준다. 
    - 단, get은 defalut여서 기입안해도 get이다.(생략가능)
     - 써주는 것이 가독성은 좋다.
    • value속성
      • 메서드를 연결해준다.
    • method속성
      • get방식인지 post방식인지 구분한다.
        • post방식 보안에 좋다. (아이디, 비밀번호 등)
    18-3 요청 파라미터

    컨트롤러의 URL 맵핑과 파라미터 처리 방법에 대해서 학습

     

    19-1 @ModelAttribute
    예제 설명
    컨트롤러에서 사용한 객체(Member member)를 뷰단에서 그대로 사용가능하다.
    특정한 이유를 (커멘더)객체의 이름을 변경할 때 @ModelAttribute를 사용한다.


    @ModelAttribute 사용 예시
    객체명 바꿔주는 기능
    @ModelAttribute 사용 예시
    메서드명을 바꿔주는 기능
    19-2 커멘드 객체 프로퍼티 데이터 타입
    단일 커맨드(기존방식)  
     
    중첩 커맨드  
    1. List<MemPhone>



    1. MemPhone이라는 객체를 하나 더 생성한다.
    2. html에서 중첩관련 데이터는 음영 처럼 input 태그를 여러개 단다.
    19-3 Model & ModelAndView

     

    Model & ModelAndView 비교 설명
    기존 Model 뷰 사용 방법
    1. model.addAtribute를 이용하여 모델에 값을 설정한다.
    2. return memModdifyOK는 memModifyOk.jsp를 호출하는 것이다.
    3. memBef, memAft는 뷰단에서 사용가능하다.
    ModelAndView는 기존 Model이 데이터만 전달하는 것에 대비 데이터와 뷰의 이름을 함께 전달하는 객체이다.
    *setViewsName("뷰이름")
    차이점 정리

     

    'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

    리다이렉트, 인터셉트  (0) 2022.01.06
    세션, 쿠키  (0) 2022.01.03
    Service & Dao 객체 구현  (0) 2021.12.30
    스프링 MVC 웹서비스  (0) 2021.12.29
    웹 프로그래밍 설계 모델(MVC)  (0) 2021.12.28

    목차 돌아가기

    웹 프로그래밍의 구조에서 Service와 DAO 객체의 구현에 대해서 학습합니다.

     

    17-1 웹 어플리케이션 준비
    특히 Service, DAO(Data Access Object) 쪽을 추가적으로 다룰 예정이다.
    17-2 한글처리

    web.xml에 한글처리 관련 코드를 추가해준다.

    <!-- 한글처리 -->
    	<filter>
    		<filter-name>encodingFilter</filter-name>
    		<filter-class>
    			org.springframework.web.filter.CharacterEncodingFilter     
    		</filter-class>
    		<init-param>
    			<param-name>encoding</param-name>   
    			<param-value>UTF-8</param-value>
    		</init-param>
    		<init-param>
    			<param-name>forceEncoding</param-name>  
    			<param-value>true</param-value>
    		</init-param>
    	</filter>    
    
    	<filter-mapping>
    		<filter-name>encodingFilter</filter-name>
    		<url-pattern>/*</url-pattern>  <!-- 모든 것 -->                
    	</filter-mapping>

     

    17-3 서비스 객체 구현
    방법 설명
    Service 객체 생성
    MemberService service = new MemberService();
    - 과거 순수 자바 이용 방법


    Service 객체 생성
    @Autowired
    MemberService service;
    - @Autowired 빈 객체 주입 

    가장 실무에서 많이 쓰이는 방법

    1. Service 객체 명시한다.
    - @Service를 맨위에 붙힌다. (기타 : @Component, @Repository 셋 다 가능. ) 
    2. MemberService service
    17-4 DAO 객체 구현
    방법 설명
     

    1. 맨위에 @Component, @Repository를 명시한다.
    - 쓰고 싶을 때 @Autowired를 붙여서 사용하면 된다.
    1. Contoller를 통해 파라미터를 받아온다.
    2. Service를 통해서 해당 파라미터에 특정한 기능(System.out.print() 등등)과 같은 기능을 처리 한후 DAO로 전달한다.
    3. DAO에서는 DB에 (수정, 삭제, 추가)를 직접 담당한다.

    'Spring > [인프런] Spring FrameWork' 카테고리의 다른 글

    세션, 쿠키  (0) 2022.01.03
    Controller 객체 구현  (0) 2021.12.31
    스프링 MVC 웹서비스  (0) 2021.12.29
    웹 프로그래밍 설계 모델(MVC)  (0) 2021.12.28
    어노테이션을 이용한 스프링 설정 -1  (0) 2021.12.27

    + Recent posts