[ KOSTA 교육 43일차 ] MyBatis 실습 2 | @PathVariable을 사용하는 이유 | 트랜잭션 설정 & AOP | Spring Data | DI : @Autowired vs @Resource vs @Inject 어노테이션 | Spring과 Spring Boot의 차이

junjun·2024년 6월 28일
0

KOSTA

목록 보기
41/48

@PathVariable 사용 이유 ( vs @RequestParam )

  • 보안을 위해 사용 ( URL 매핑 규칙을 해커가 추론하지 못하게 )
  • RESTful 서비스 설계 시 URL 매핑 규칙을 고려

  • 이렇게 2014587이라는 쓸데없는 더미 주소를 넣어줄 수도 있다.
    • 어떤 특별한 알고리즘이 적용되어 해석이 필요하도록 만들 수도 있을 것인다.
    • 이제 해커가 이를 보더라도 내부 구조를 알 수가 없고, 해킹이 불가능하다.

@Transactional과 XML 기반 트랜잭션 설정의 우선순위

  • Spring은 구체적인 것이 추상적인 것보다 먼저 적용된다.

  • @Transactional 설정 > XML 설정

기존 SQLSessionFactoryBean 설정에서 Mapper 설정들을 넣어줬던 것을, MapperScannerConfigurer에 넣어줄 수 있다.

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="com.lec09.orm.mybatis.mapper"/>
  <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
  • basePackage 설정값을 기반으로 mapper를 스캔한다.

@Repository 어노테이션을 I/F 위에도 쓸 수 있다 ( MyBatis Mapper에 @Repository 어노테이션 )

  • @Controller, @Service, @Repository 어노테이션은 런타임에 해당 어노테이션이 붙어있는 클래스를 스프링 컨테이너가 인스턴스화하여 각 역할에 맞는 스테레오타입 빈으로써 관리한다 알고 있었다.

    • 즉, 메모리에 올라갈 수 있는 대상들에만 마킹해놓을 수 있는 줄 알았다.
  • 하지만 MyBatis를 사용하게 되면 DAO, 즉 DB와의 실제 연결 및 SQL을 이용한 통신을 담당하는 클래스는 없어지고, Mapper I/F만 남게 된다.

  • 스프링 컨텍스트의 내부 구현을 뜯어보면, @Repository가 붙어있는 부모 타입 인터페이스에 대해 프록시를 생성하여 ( 즉 Child Instance ) 인터페이스에서 명시한 기능을 Mapper XML과 연결한 빈을 만들어 사용한다. ( 스프링 컨텍스트를 통해 POJO 클래스의 기능을 보강한 예시 중 하나 )

  • Spring에서 I/F를 쓴다는 것은 무조건 다형성을 사용한다는 의미이다.

    • 인터페이스 위에 @가 있다는 것은, 이걸 이용한 Child Instance가 생성되는 것이다.

@Autowired vs @Resource vs @Inject

  • 공통점 : 컨테이너에 생성된 빈(Bean) 객체를 자동으로 주입 받을 수 있도록 해주는,
    즉 DI를 위한 어노테이션

  • Bean 객체 의존성을 이용할 때 코드를 아주 간결하게 해주기에 필수로 사용되는 어노테이션

  • @Autowired는 스프링이 제공해주는 어노테이션, 즉 스프링에 의존적이라 나중에 프레임워크를 바꿀 계획이 있다면 @Resource, @Inject 어노테이션을 사용하는 것이 좋습니다. ( Java 기반 다른 웹 프레임워크 ), @Autowired는 @Inject와 거의 유사하게 동작합니다.

  • 차이점

    • @Autowired는 Spring의 어노테이션이고, @Resource/@Inject 는 Java EE의 어노테이션이다.
    • @Autowired는 DI 시, 해당 의존성 빈을 타입 -> 이름 순으로 검색해 가져오지만, @Resource는 이름-> 타입 순으로 빈을 가져옵니다.
    • @Inject는 같은 타입의 Bean을 먼저 찾습니다. 같은 타입의 Bean 객체가 여러 개 있으면, 이름으로 찾고 그래도 없다면 예외가 발생합니다. @Named 어노테이션을 이용하여 Bean ID를 지정해줄 수 있습니다.
  @Resource @Inject @Autowired
의존 Javax Javax Spring
사용 가능 위치

- 필드

- 파라미터가 한 개인 setter

- 필드

- 생성자

- setter

- 필드

- 생성자

- setter

Bean 검색

우선순위

이름 -> 타입 타입 -> 이름 타입 -> 이름
Bean 강제 지정 @Resource(name="ID")

@Inject

@Named("ID")

@Autowired

@Qualifier("ID")

Bean 없을 경 예외 발생

예외 발생

@Autowired(required=false) 처리하면 예외 발생 방지


Java 플랫폼 ( Java SE vs Java EE vs Java ME )

  • Java ME = Micro Edition ( 안드로이드 )

  • Java EE = Enterprise Edition ( Servlet, JDBC )

  • Java SE = Standard Edition

  • 이와 같은 것을 Java Platform이라 한다.

자바 플랫폼을 무엇을 썼는지 물어본다면...
  • Java 17, 11? => 이건 Java Version

  • Servlet/JDBC을 위해 Java EE를 사용하고, Collection Framework와 같은 자바 기본 기능을 사용하기 위해 Java SE를 사용했단 것이 좀 더 좋은 표현일 것이다.

플랫폼의 의미

  • 운영체제 위에 탑재되어 프로그램을 돌아가게 하기 위한 구동환경
    • Java = Java Platform
    • .Net Framwork = .Net Platform

트랜잭션 & 스프링 트랜잭션 정리

 
 -------------------------------------------------------------------
트랜잭션(Transaction)
-------------------------------------------------------------------
	 데이터베이스와 같은 시스템에서 (여러 연산을 논리적으로 하나의 단위로 묶어서 처리)하는 (일련의 작업)
	
-------------------------------------------------------------------
[트랜잭션의 특징]
-------------------------------------------------------------------
1. Atomity(원자성)
	* 여러 단계의 작업이 모두 성공적으로 수행되어야만 완료, 어느 하나라도 에러가 발생하면 트랜잭션 전부가 취소되어야 함
2. Consistency(일관성)
	* 특정 작업이 완료된 상태에서만 다음 작업이 수행되어야 함
	* 트랜잭션이 커밋되기 전까지는 데이터베이스가 일관된 상태를 유지
3. Isolation(고립성, 격리성)
	* 둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행중에 다른 트랜잭션의 연산이 끼어들 수 없음
	* 수행중인 트랜잭션은 완전히 완료될 때까지 다른 트랙잭션에서 수행 결과를 참조할 수 없음
4. Durability(영속성, 지속성)
	* 성공적으로 완료된 트랜잭션의 결과는 영구적으로 반영되어야 함
	* commit, rollback 

[트랜잭션의 상태]
	* Active(활동) : 트랜잭션이 실행중에 있는 상태
	* Failed(장애) : 트랜잭션 실행에 오류가 발생되어 중단된 상태
	* Aborted(철회) : 트랜잭션이 비정상적으로 종료되어 Rollback 연산을 수행한 상태
	* Partially Committed(부분 완료) : 트랜잭션의 마지막 연산까지 실행했지만, Commit 연산이 실행되기 직전의 상태
	* Committed(완료) : 트랜잭션이 성공적으로 종료되어 Commit 연산을 실행한 후의 상태


-------------------------------------------------------------------
선언적 트랜잭션(Declarative Transaction Management)  : https://velog.io/@limdae/%EC%B2%AB%EB%B2%88%EC%A7%B8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-16.-Transactional
-------------------------------------------------------------------
XML 기반 설정
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		   <property name="dataSource" ref="MY_tomcat_ds" />
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="*" rollback-for="Exception"/>
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut id="cut" expression="execution(* com.lec09..*Impl.*(..))"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="cut" />
	</aop:config>
	


-------------------------------------------------------------------
어노테이션 기반 설정
@Transactional   : https://velog.io/@limdae/%EC%B2%AB%EB%B2%88%EC%A7%B8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-16.-Transactional
-------------------------------------------------------------------
<tx:annotation-driven transaction-manager="txManager"/> 

@Transactional
public class UserServiceImpl {
	@Transactional
    public int userInsert(Uservo uvo) { .. }
    
    public int userDelete(int seq)    { .. }
    
    
}


	@Transactional 어노테이션이 붙은  메서드 또는 클래스의 모든 메서드는 하나의 트랜잭션으로 처리
	1) 메서드 레벨에서의 사용(원자성 보장 :일괄커밋 일괄롤백)
		: 해당 메서드에서 수행되는 모든 작업이 하나의 트랜잭션으로 처리
	2) 클래스 레벨에서의 사용
		: 해당 클래스의 모든 메서드에 적용
		: 주로 클래스 내의 모든 메서드가 하나의 트랜잭션으로 묶여야 하는 경우에 유용
		: 메서드 레벨의 설정이 우선
	3) 속성
		: 읽기전용 @Transactional(readOnly = true) 
			트랜잭션이 커밋되지 않고 종료
		: 격리수준 @Transactional(isolation = Isolation.READ_COMMITTED) 
			Isolation.READ_COMMITTED, Isolation.REPEATABLE_READ, Isolation.SERIALIZABLE 등
			여러 트랜잭션이 동시에 실행될 때 트랜잭션 간의 격리 수준을 지정
		: 전파동작 @Transactional(propagation = Propagation.REQUIRED)	
			Propagation.REQUIRED, Propagation.REQUIRES_NEW, Propagation.NESTED 등
			다른 트랜잭션 내에서 메서드가 호출될 때 해당 메서드가 참여할지, 새로운 트랜잭션을 시작할지를 결정
		: 타임아웃 @Transactional(timeout = 30)
			timeout은 초 단위로 설정하며, 기본값은 -1로서 타임아웃이 없음
			지정된 시간 내에 트랜잭션이 완료되지 않으면 롤백
		: 예외지정 @Transactional(		rollbackFor = { CustomException.class, AnotherException.class },
               			      	  noRollbackFor = { AllowedException.class })
		: 멀티속성 @Transactional(readOnly = true, timeout = 30)
			
	
	
 
-------------------------------------------------------------------
* 주의사항
-------------------------------------------------------------------
1. @Transactional 은 public 메소드에서만 정상 작동한다.

 2. @Transactional 을 달아놓은 메소드가 동일한 클래스 내의 다른 메소드에 의해 호출된다면 트랜잭션이 정상 작동하지 않는다.
		ex: 퍼사드 패턴이나 템플릿 패턴처럼 여러 메소드를 내부적으로 묶어 사용하고 있는 메소드가 있다면 구성요소 메소드에 @Transactional 를 달지 않고 구성요소를 묶고 있는 상위개념의 메소드에 @Transactional 을 달아주어야 한다. 
		구성요소 메소드에 @Transactional 을 달아 주어 트랜잭션으로 관리 할 경우 rollback 이 정상적으로 작동하지 않는 경우가 발생한다.
	https://woowabros.github.io/experience/2019/01/29/exception-in-transaction.html
	propagation 속성이 required 인 경우, 트랜잭션안에서 호출되는 메소드가 트랜잭션으로 같이 묶이게 되어 예상치 못한 결과가 나올 수 있다는 내용이다.
	※ required propagation 속성은 트랜잭션이 이미 존재하면 append를 하고, 트랜잭션이 존재하지 않다면 새로 생성한다. (공식 doc)

public class PayServiceImpl {
    @Transactional
	public boolean pay(Uservo uvo) {
		userInsert();
		payLog();
	}
}
public class UserServiceImpl {
	@Transactional
    public int userInsert(Uservo uvo) { .. }    
}

*********************************************************************************
3. Spring Transaction 은 기본적으로 unchecked Exception (RuntimeException) 만 관리하며 
                                   checked Exception (IOException, SQLException 등) 은 관리하지 않는다.

	처리방법 1: @Transactional(rollbackFor=Exception.class) 와 같이 설정하여 모든 Exception 발생시 rollback 이 발생하게 처리하거나
	(unchecked Exception, checked Exception 모두 Exception.class 밑에 있다.)

	처리방법 2: checked Exception 이 발생할 가능성이 있는 부분을 
	try ~ catch (SQLException se){  .... throw new RuntimeException(); } 과 같이 처리
	(checked Exception 발생시 unchecked Exception 으로 예외를 바꾸어 던지게 처리)하여 Transaction의 관리대상으로 묶어버릴 수 있다.
*********************************************************************************

	
4. pointcut 을 사용한 Transaction 설정과 어노테이션을 사용한 Transaction 설정을 동시에 사용하게 될 경우, 
   어노테이션이 무조건적으로 우선적용(precedence)된다.
   : @Transactional 붙은 메서드 처리 이후 
     이외 나머지 메서드들은 pointcut 적용 대상이 될 경우 xml기반의 tx 설정을 따른다.
     <aop:pointcut id="cut" expression="execution(* com.lec09..*Impl.*(..))"/>
     
   (https://stackoverflow.com/questions/32057910/custom-spring-aop-around-transactional/33509777#33509777)

Spring Data

  • 데이터 영속성을 위해 사용할 수 있는 모듈의 집합

    • JDBC, ORM, JPA
  • 관계형 / 비관계형 DB에 관계없이 DB 접근에 대해 일관된 방법을 제공

Spring Boot

  • Spring Framework의 복잡한 환경설정을 최소화함.

  • 설정부분을 자동화하여 편안하게 Spring을 사용할 수 있음.

  • spring-boot-starter를 사용하여 의존성 자동 관리

  • 내장 톰캣으로 WAS를 실행시킴, jar 배포 가능

  • 실행 환경, 의존성에 대한 고려를 최소화하여 코드 개발 가능

0개의 댓글