Spring Boot 프로젝트를 진행하던 중 평소처럼 서비스단에서 transaction 처리를 해주던 중 transaction이 제대로 구현되지 않는 문제가 발생했다. 

알고 보니 특정 케이스에 대해 명시적으로 throw 해준 부분(Checked Exception)에 대해서는 자동으로 @Transactional 어노테이션이 작동하지 않았다. 추가 옵션으로 롤백할 클래스명을 지정해줘야한다는..!

@Trasaction(rollbackFor = {Exception.class}

단, try catch로만 명시적으로 처리해줄때에는 해당 Exception을 catch문에서 잡기때문에 Spring이 감지하여 transaction 처리를 해줄수 없기때문에 try catch를 쓰지않고 throw하거나 catch 문에서 throw를 해줘야한다. (

후 역시 공부는 해도해도 끝이 없는것같다.

찾아본김에 적는 자바의 Exception 종류도 정리해보았다.

Error (java.lang.Error)

주로 시스템(VM)에서 발생시키는 에러 상황. 애플리케이션단에서 처리는 어렵고 보통은 컴파일단에서 나타남

 

Checked Exception

개발자가 작성한 코드내에서 발생할 수 있는 예외상황.

Checked Exception은 Exception클래스의 자식 클래스이지만 RuntimeException 클래스은 상속받지 않음

 

Unchecked Exception

java.lang.RuntimeException 클래스를 상속받은 예외상황

예를 들어 NullPointerException, IllegalArgumentException 등등 개발자의 부주의로 발생할 수 있는 예외를 정의해놓은 클래스들.

 

 

최근 회사에서 프로젝트를 진행하면서 Spring Security CSRF를 도입했다.

CSRF는 사이트 간 요청 위조를 막는 방법이다.

사이트간 요청 위조를 막는 방법에는 Referrer 검증이나 CSRF 등이 있는데 

 

Referrer 검증request header에 있는 referrer 속성(요청페이지의 정보가 담긴 속성)을 검증하여 차단하는 방식으로

header를 파악하여 같은 도메인이 아니면 요청을 차단하는 식으로 요청위조를 차단할 수 있다.

 

CSRF는 랜덤한 토큰값을 세션에 저장하고 사용자의 모든 요청(Request)에 대하여 서버단에서 검증하는 방법이다.

spring5에서는 csrf enable이 디폴트 이므로 이를 구현하기 위해서는 csrf 토큰을 요청페이지마다 심어두기만 하면 적용가능하다. 사용하지 않을 경우 SecurityConfig 클래스에서 csrf().disable() 설정만 추가해주면 된다.

 

이번에 진행한 프로젝트에서 CSRF 적용된 프로젝트를 테스트하던 중 단일 개발서버에서는 문제가 되지 않는데, 이중화되어있는 운영서버에  올렸더니 페이지가 넘어가거나 ajax 같은 새로운 요청이 있을때마다 403에러가 뜨는 현상이 발생했다.(페이지마다 csrf토큰은 잘 넣어줬는데도.. ) 그래서 현재는 csrf 설정을 disable 시켜놓은 상태인데 왜 이런 현상이 생기는지 더 찾아봐야 할 것 같다.

 

 

 

 

 

'Web > Spring Framework' 카테고리의 다른 글

Spring Transaction 처리  (0) 2020.01.14
Spring Exception 처리 방법  (0) 2019.08.12
SpringMVC - View의 이해  (1) 2018.08.31
Spring Boot 세팅하기1 - 프로젝트 생성  (0) 2018.08.28
Spring Framework 세팅하기1 - 설치  (0) 2018.05.29

Spring에서 Exception 처리는 총 3가지

 

  • 전역 처리 Global Level using -  @ControllerAdvice
  • 컨트롤러단에서 처리 Controller Level using @ExceptionHandler 
  • 메소드단위 처리 Method Level using try/catch  

1. @ControllerAdvice 

- 공통 Exception 클래스를 만들고 해당 어노테이션 추가

- 서비스, 컨트롤러단에서는 exception을 throw 하는 역할만하고 공통 클래스에서 일괄처리

 

 

2. @ExceptionHandler 

- 컨트롤러 별로 Exception 처리 

 

3. try/catch

- 메소드 단위에서 exception 처리

- 안티패턴, 불가피한경우 구체적인 Exception 지정 

 

 

*** cheese10yun 블로그에 설명이 너무 잘돼있음 



출처: https://springboot.tistory.com/33 [스프링부트는 사랑입니다]

 

 

 

스프링부트 : REST 어플리케이션에서 예외처리하기

스프링부트 : REST어플리케이션에서 예외처리하기 (원문소스: http://www.ekiras.com/2016/02/how-to-do-exception-handling-in-springboot-rest-application.html) 기억할 점 스프링 부트 어플리케이션에서 예외..

springboot.tistory.com

https://cheese10yun.github.io/spring-guide-exception/

 

Spring Guide - Exception 전략 - Yun Blog | 기술 블로그

Spring Guide - Exception 전략 - Yun Blog | 기술 블로그

cheese10yun.github.io

https://groups.google.com/forum/#!topic/ksug/5xeN3gDSbu8

 

Google 그룹스

 

groups.google.com

 

express 4버전으로 프로젝트를 생성하니 기존에 앱을 실행하던 node app.js 명령어가 먹히지 않았다.

찾아보니 express3 에서 4로 버전업하면서 package.json 에 정의하던 시작 스크립트가 node ./bin/www 로 변경되었다고 한다.


따라서 기존처럼 node app.js 로 실행하도록 설정을 바꾸어보았다.



1. express 4 설치 

$ npm install -g express-generator


2. 프로젝트 생성

$ express nodejsproject       // 이전버전과 동일


3. package.json 시작 스크립트 수정


{

  "name": "nodejsproject",

  "version": "0.0.0",

  "private": true,

  "scripts": {

    "start": "node app.js"    -- 기존: node ./bin/www  

  },

  "dependencies": {

    "cookie-parser": "~1.4.3",

    "debug": "~2.6.9",

    "ejs": "^2.6.1",

    "express": "~4.16.0",

    "http-errors": "~1.6.2",

    "jade": "~1.11.0",

    "morgan": "~1.9.0"

  }

}


4. app.js 스크립트 수정


상단에 debug 변수 정의

var debug = require('debug')('nodejsproject');


하단에 module.exports 주석처리 하고 소스 추가

//module.exports = app;


app.set('port', process.env.PORT || 3000);


var server = app.listen(app.get('port'), function() {

  debug('Express server listening on port ' + server.address().port);

});




*설정을 변경하여 이전처럼 실행이 가능해졌다! 근데.. 이 방법을 권장하진 않는다고해서 /bin/www 파일과 구조를 살펴본 후에 다시 롤백하려고한다.


[ 참고글 발췌 ]

이제 ./bin/www의 기능이 다시 app.js로 이전되었습니다. 이러한 변경은 권장되지 않지만, 이러한 연습을 통해 ./bin/www 파일의 작동 원리를 이해하고 app.js 파일이 더 이상 자체적으로 시작되지 않는 이유를 이해할 수 있습니다.




참고글 : https://expressjs.com/ko/guide/migrating-4.html

jar, war, ear 은 모두 압축파일의 종류이다.

각 파일이 담고있는 규모를 따지면 class > jar > war > ear 순이다.


jar (java archive)

  • 하나의 application 기능이 가능하도록 java 파일을 압축하고 지원한다.
  • path 정보를 유지하여 압축되기 때문에 배포된 jar 파일을 이용하면 각 파일에 대한 path 문제를 신경쓰지 않아도 된다.
  • ex) ojdbc.jar



war (web archive)

  • war는 web application을 지원하기 위한 압축방식으로 jsp, servlet, gif, html, jar 등을 지원한다.
  • war는 단독으로 실행이 안되고 서버 컨테이너(was)에 의해 실행되어야하므로 배포디스크립터가 담겨있다.(web.xml)



ear (enterprise archive)

  • 하나의 web application 단위를 넘어 실제 서버에 배포하기 위한 단위이다.
  • jar와 war를 묵어서 각각의 기능을 지원한다. (jar는 애플리케이션 레벨(business layer), war는 웹애플리케이션 레벨(web layer)을 지원하도록)


JUnit


JUnit 은 자바 테스팅 프레임워크다. 사실상 표준이라고 할만큼 널리 사용되고 있다.



JUnit 장점


JUnit 을 사용하는 이유는 개발자가 설계하고 만든 코드가 원래 의도한대로 잘 동작하는지를 개발자 스스로 테스트하기 위해서이다.


테스팅 프레임워크를 사용하지 않을 때에는 System.out.println 메소드를 호출해서 일일이 확인하여 처리했었다.


하지만 이러한 테스트 방식은 화면, db 연결, 여러가지 설정까지 모두 해준뒤에야 테스트가 가능하다.


JUnit 은 이러한 점을 개선하여 작은 단위테스트까지 가능하도록 만들어졌다.



예를들어 테스팅 프레임워크를 쓰지않고 Dao 클래스를 테스트를 진행한다면 화면 폼을 만들고 DB 도 연동해 sysout 으로 확인해봐야하지만


JUnit을 이용하면 화면개발과 DB 연동 없이도 Dao 클래스만 독립적으로 테스트가 가능하다.



사용 방법


테스트 메소드를 만들기 위해서는 2가지 설정이 필요하다.

(테스트 클래스 생성하면 자동으로 설정되어있음)


  • 테스트메소드를 public으로 선언
  • 메소드 위에  @Test 어노테이션 설정 


JUnit 메소드 


JUnit 은 if~else 대신 assertThat 이라는 스태틱 메소드를 제공한다.


assertThat은 첫번째 파라미터의 값을 뒤에 나오는 매처라고 불리는 조건으로 비교해서 일치하면 다음으로 넘어가고 아니면 테스트가 실패하도록 만든다.


is() 는 매처의 일종으로 equals() 로 비교해주는 기능을 한다.


예)

assertThat(user2.getPassword(), is(user.getPassword());

JUnit 은 예외가 실패하거나 테스트가 실패하면 자동으로 알려주기때문에 System.out.println("테스트 성공") 같이 메시지를 직접 작성할 필요가 없다.


테스트가 성공할 경우, OK 메세지와 테스트실행시간, 몇개의 테스트 메소드가 실행됐는지 실패할 경우, 호출스택에는 실패원인, 테스트코드에서 검증에 실패한 위치 등을 알려준다.



JUnit 테스트

  • JPA 를 이용해 UserRepository.java 생성
  • UserRepository 클래스를 테스트하는 UserRepositoryTest 클래스 생성

1. JPA 를 이용해 UserRepository.java 생성


2. UserRepository 클래스를 테스트하는 UserRepositoryTest 클래스 생성

(src/test/java 내에서 New > JUnit Test Case 선택)
Name 에는 테스트 클래스 명을, Class under test 에는 테스트할 객체의 클래스를 입력 




3. UserRepository 클래스에 대한 테스트 코드 작성

@Test 어노테이션과 함께 @Before, @After 어노테이션도 사용할 수 있는데 이름대로 @Before 는 @Test 메소드 직전에, @After 는 직후에 실행됨.



4. JUnit 실행
테스트클래스 우클릭 > Run As > JUnit Test 클릭
성공하면 아래 그림처럼 초록바가 똬앟






참고 : 토비의 스프링 3.1 

MVC 의 View 란


Spring MVC의 View 는 DispatcherServlet이 직접 호출하는 오브젝트로, View 인터페이스를 구현하여 다양한 클래스를 만들 수 있다.

(따로 설정하지 않을 경우 디폴트는 InternalResourceView 라는 뷰리졸버로 세팅)


사실 찾아보기 이전까지는 보통 View 단을 jsp 로 구현해왔기 때문에 Spring에서는 무조건 jsp로 화면을 구현하는줄 알고있었다..


주로 JSP뷰라고 부르는 이유는 Spring 이외의 다른 MVC 프레임워크에서도 jsp를 광범위하게 사용하고, 실제로도 jsp에 뷰작업을 위임하기 때문이라고 한다.



다른 View 기술에는


Velocity 나 FreeMarker 등이 있다.



각 기술의 설정 예제를 보면 ViewResolver 구현체를 bean으로 등록하여 사용하는 것을 확인할 수 있다.


Velocity 설정


velocity 는 *.vm 확장자를 사용하지만 내부 문법은 html과 동일하다.




FreeMarker 설정


freemarker는 *.ftl 확장자를 사용







* 참고 : http://misoboy.tistory.com/36

개발 환경


1. OS 환경

- macOS Sierra (버전 10.12.6)


2. STS (Spring Tool Suite)

스프링 애플리케이션 개발을 위한 이클립스 기반 개발 환경

- Maven, Git, Gradle, AspectJ 와 연동 가능


3. Apache Tomcat 8.5 

- jsp, servlet, class, EJB 등을 실행시키는 웹 컨테이너 

- 웹서버의 기능도 포함


* STS와 톰캣 설치 방법 : [Spring Framework 세팅하기1 - 설치] 글 참고


Spring Boot 

  • 기존 SpringMVC 프로젝트에서 xml을 통해 설정하던 것들을 자동으로 셋업하여 만들어놓은 스프링 서브 프로젝트
  • STS 에서 프로젝트 생성할 때, spring legacy~로 생성하면 SpringMVC, spring starter~로 생성하면 SpringBoot 프로젝트이다!


프로젝트 생성 순서

1. 프로젝트 생성하기

STS 상단 메뉴 > File > New > Spring Starter Project 


2. 프로젝트 정보 입력

Name : 프로젝트 이름

Type : Gradle 또는 Maven 선택 (여기에서는 Gradle 선택)

Group, Package : 패키지 명





3. dependency 설정 


지금은 테스트 프로젝트이므로 간단하게 추가 > 더 추가하려면 검색 > Finish 클릭 

  • Security
  • Aspects
  • JPA
  • MySQL
  • H2
  • JDBC
  • Web





4. 웹페이지 테스트를 위한 Controller 추가


프로젝트 > com.bbchu.demo 패키지 선택 > 우클릭 > New > Class 선택 > TestController.java 생성


루트(/) 요청이 들어왔을 때 root 메소드로 매핑 


package com.bbchu.demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
	
	@RequestMapping("/")
	public String root()
	{
		return "Spring Boot Test";
	}
	
}


5. 테스트 

 

  • 톰캣 기본 포트는 8080이므로 http://localhost:8080/프로젝트이름/ 접속 
  • Server 탭에 톰캣 더블클릭 > Modules 탭 > Edit > Path 를 / 로 설정 시, url 에 프로젝트이름 생략 가능 (Context Root 를 / 로 지정)






** 이슈 : 실행 시 로그인 화면이 뜬다면 build.gradle 파일에서 security 주석처리


//compile('org.springframework.boot:spring-boot-starter-security')









[ 개발 환경 ]


1. OS 환경

- macOS Sierra (버전 10.12.6)


2. STS (Spring Tool Suite)

스프링 애플리케이션 개발을 위한 이클립스 기반 개발 환경

- Maven, Git, Gradle, AspectJ 와 연동 가능


3. Apache Tomcat 8.5 

- jsp, servlet, class, EJB 등을 실행시키는 웹 컨테이너 

- 웹서버의 기능도 포함


[ 설치 순서 ]

  • STS 설치

  • 톰캣 설치

  • STS 실행하여 톰캣 연동

  • 톰캣 서버 설정



1. STS 설치

사이트로 이동하여 자신의 환경에 맞는 버전 다운로드 ( https://spring.io/tools/sts/all )



2. 톰캣 설치

- 다운로드 사이트로 이동하여 8.5 버전 다운로드 ( http://tomcat.apache.org/download-80.cgi)

- 나는 맥 환경이므로 tar.gz 으로 다운로드



3. STS 실행하여 톰캣 연동

- STS 실행 > workspace 설정

- Server tab 에서 톰캣 서버 생성 링크 클릭





4. 다운받은 톰캣 버전으로 서버 설정 

- Apache > 8.5 버전 톰캣 선택 > Next > Finish

- 하단에 서버 목록이 생성되면 완료





+ Recent posts