Developer Note/국비과정 수업내용 정리&저장

24년 11월 14일

DH_PARK 2024. 11. 24. 21:02

스프링에서의 트랜잭션

스프링에서도 SQL 을 배울 때 처럼 CRUD 를 사용할 때 예외가 발생한다면 중간에 있는 코드가 실행되지 않게 하는 트랜잭션 처리를 해주어야 하는데 이 때 여러가지 기술들을 사용하게 된다.

알아보자.

스프링 트랜잭션 의존성 추가

		<!-- 스프링 트랜잭션 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

의존성 추가할 때 버전 맞추는법 :

		<version>${org.springframework-version}</version>

이 부분에서 기존 버전을 지우고 안에 ${org.springframework-version} 을 써주면 동적으로 스프링의 버전과 일치시켜준다.

스프링 설정을 할 때보면 버전을 맞추는게 있고 따로 있는게 있는데, 이런거는 기본적으로 알아놔야 한다고함.

스프링에서 트랜잭션 사용하기

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class TxConfig {

	@Autowired
	private DataSource dataSource3;
	
	@Bean
	public DataSourceTransactionManager transactionManager() {
		
		return new DataSourceTransactionManager(dataSource3);
	}
	
}

우선 트랜잭션 속성을 지정하려는 곳에 두개의 어노테이션을 추가해준다.

@Configuration @EnableTransactionManagement

트랜잭션의 사용

트랜잭션은 보통 비즈니스 로직에서 사용한다.(서비스 계층)

	@Transactional(rollbackFor =  SQLException.class)
	public boolean memoAddTx(MemoDto memoDto) {
		
		int result = memoDaoImpl.insertTx(memoDto);
		return result>0;
	}

SQL 예외가 날시에는 rollback이 되도록한다.

트랜잭션 전파속성

[ 트랜잭션 전파 속성(Transaction Propagation)이란? ]Spring이 제공하는 선언적 트랜잭션(트랜잭션 어노테이션, @Transactional)의 장점 중 하나는 여러 트랜잭션을 묶어서 커다란 하나의 트랜잭션 경계를 만들 수 있다는 점이다. 작업을 하다보면 기존에 트랜잭션이 진행중일 때 추가적인 트랜잭션을 진행해야 하는 경우가 있다. 이미 트랜잭션이 진행중일 때 추가 트랜잭션 진행을 어떻게 할지 결정하는 것이 전파 속성(Propagation)이다.

@Transactional 의 추가 옵션 정리

propagation: 트랜잭션 전파 방식을 설정합니다. 다른 트랜잭션 내에서 메서드가 호출될 때 어떻게 트랜잭션을 전파할지를 결정합니다.
예를 들어, REQUIRED, REQUIRES_NEW, SUPPORTS 등이 있습니다.

isolation: 트랜잭션 격리 수준을 설정합니다. 여러 트랜잭션이 동시에 실행될 때 데이터의 일관성을 보장하기 위해 어떤 수준의 격리를 유지할지를 결정합니다.
예를 들어, DEFAULT, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE 등이 있습니다.

timeout: 트랜잭션 타임아웃을 설정합니다. 특정 시간 내에 트랜잭션이 완료되지 않으면 롤백됩니다. 단위는 초(seconds)입니다.

readOnly: 읽기 전용 트랜잭션 여부를 설정합니다. 읽기 전용 트랜잭션은 해당 트랜잭션 동안 데이터를 수정하지 않음을 나타냅니다. 기본값은 false이며, true로 설정하면 성능을 향상시킬 수 있습니다.

rollbackFor / noRollbackFor: 롤백을 수행할 예외 클래스를 지정하거나 롤백을 수행하지 않을 예외 클래스를 지정합니다.

ViewResolver란?

  • 🗸 실행할 뷰를 찾는 일을 한다.
  • 🗸 페이지 컨트롤러가 리턴한 뷰 이름에 해당하는 뷰 콤포넌트를 찾는 역할.

컨트롤러 계층에서 찾는다.

그리고 어떤 뷰로 응답을 생성할지 결정하는 역할을 한다.


REST 란 ?

[ RestController ]@RestController는 @Controller에 @ResponseBody가 추가된 것입니다. 당연하게도 RestController의 주용도는 Json 형태로 객체 데이터를 반환하는 것입니다. 최근에 데이터를 응답으로 제공하는 REST API를 개발할 때 주로 사용하며 객체를 ResponseEntity로 감싸서 반환합니다. 이러한 이유로 동작 과정 역시 @Controller에 @ReponseBody를 붙인 것과 완벽히 동일합니다.

출처:

https://mangkyu.tistory.com/49

[MangKyu's Diary:티스토리]

@Controller와 @RestController 어노테이션의 차이

일단 둘다 스프링에서 Controller 로 지정해주는 어노테이션은 맞다.

여기서 차이점은 ResponseBody가 생성되는 방식이다.

Controller로 View 를 반환할 경우

컨트롤러는 받은 요청을 처리하고 View 이름을 반환하는데 이 때

DispatcherServlet 이 뷰 리졸버를 통해 일치하는 view 를 찾아 사용자에게 반환함. (포워딩처리)

[Controller로 Data를 반환할 경우]

Controller 가 view 가 아닌 Data 를 반환해야 하는 경우도 있는데 , 그럴 때는 데이터를 반환하기 위해서 ResponseBody를 사용해야 하는데 이 때 @ResponseBody 를 사용한다.

이 어노테이션으로 Controller 도 View 뿐이 아닌 JSON 형태의 데이터도 반환을 할 수 있다.

Dyunge_100.log 출처

 

 

이처럼 ResponseBody 에 Data를 담아 다른 View 에 이동할 때 model 객체에 데이터를 실어서 보낼 수 있다.

※ 주로 Controller 메서드의 반환값은 View 이름으로 간주된다.


@RestController

 

RestController 구조

 

 

@RestController 는 Controller 와 ResponseBody 가 합쳐진 어노테이션이라고 생각하면 된다.

@Controller 와 다르게 반환하는 주 데이터는 JSON 형태의 객체 데이터이다.

REST API를 개발할 때 주로 사용하며 마찬가지로 ResponseEntity로 감싸서 주로 반환한다.

예시

@RestController
public class MyRestController {
    @GetMapping("/api/welcome")
    public Map<String, String> welcome() {
        Map<String, String> response = new HashMap<>();
        response.put("message", "Welcome to the site!");
        return response; // JSON 응답
    }
}

Json 데이터를 반환해준다.

	@PatchMapping(value="/patch",consumes= MediaType.APPLICATION_JSON_VALUE) //들어오는 타입 JSON 타입
	public ResponseEntity<Boolean> update_patch(@RequestBody MemoDto memoDto) {
		log.info("/patch... patch !! "+memoDto);			//patch 는 부븐을 수정   put 은 전체 매핑
		boolean isUpdate = memoServiceImpl.memoUpdate_patch(memoDto);
		return isUpdate? new ResponseEntity(isUpdate,HttpStatus.OK) : new ResponseEntity(isUpdate,HttpStatus.BAD_REQUEST);					//결국 이 responseEntity 는 웹의 반응결과를 같이 함수결과와 보내주기 위한 객체 용도인듯하다.
	
	}

Consume 을 사용한 rest 메서드

	@GetMapping(value="/getJsonEntity/{show}",produces = MediaType.APPLICATION_XML_VALUE)
	public ResponseEntity<MemoDto> t6(      //반환 타입이 XML 파일로 강제된다.
				@PathVariable boolean show
			) {
		log.info("getjsonlist ffkfkfkffk");
		if(!show)
			return new ResponseEntity(null,HttpStatus.BAD_GATEWAY);
		
		return new ResponseEntity(new MemoDto(20,"memo","ex@ex.com",null),HttpStatus.OK);
	}

produce를 사용한 메서드

Consume 과 Produce 메서드의 차이

  • Consume : consume 은 들어오는 데이터를 정의한다 (주로 get 같이 데이터를 받을 때 사용)
  • produce : produce 는 반환 데이터타입을 정의한다 (Post 같이 데이터를 보낼 때 사용)

@ResponseEntity , @RequestEntity

응답 데이터를 포함하는 클래스

HttpEntity 클래스를 상속받아 구현하는 클래스이다.

 public ResponseEntity<MemoDto> update // 
 
 boolean isUpdate = memoServiceImpl.memoUpdate_patch(memoDto);
 new ResponseEntity(isUpdate,HttpStatus.OK) 

(바디, 헤더 , 상태코드) 의 정보를 객체에 담을 수 있다.


이렇게 Controller 와 RestController 를 잘 사용하면

파라미터를 쿼리스트링으로 날리거나 바디에 숨겨서 날릴수있다. !

'Developer Note > 국비과정 수업내용 정리&저장' 카테고리의 다른 글

24년 11월 18일  (0) 2024.11.24
24년 11월 15일  (0) 2024.11.24
24년 11월 13일  (0) 2024.11.24
24년 11월 12일  (0) 2024.11.22
24년 11월 11일  (1) 2024.11.21