디자인 패턴은 소프트웨어 설계 시 특정 상황에서 자주 만나는 문제를 해결하기 위해 사용할 수 있는 재사용 가능한 솔루션으로 디자인 패턴에서 중요한 것은 각 패턴의 핵심이 담긴 목적 또는 의도이다.

 

1. 패턴을 적용할 상황

2. 해결해야 될 문제

3. 핵심 의도가 무엇인지

 

 

메서드를 추상 메서드(abstaract method)로 선언해서 자식 클래스가 이를 상속 받아 메서드를 구현하도록 하면 클래스 계층구조를 통해 관심을 분리할 수 있다. (DB의 커넥션 연결 등과 SQL, DB 접근 등의 로직을 분리)

 

상속을 통해 기능을 확장하는 방법으로 사용되는 2가지 패턴이 있는데 먼저 템플릿 메서드 패턴(template method pattern)은 부모 클래스에서 자주 변경되거나 확장할 기능을 추상 메서드나 오버라이드 가능한 메서드를 정의해둔 템플릿 메서드를 만들어서 자식 클래스에서 해당 메서드를 구현하도록 하는 패턴이다. (훅(Hook) 메서드 : 부모 클래스에서 디폴트 기능을 정의해두거나 비워뒀다가 자식 클래스에서 오버라이드할 수 있도록 만들어둔 메서드)

팩토리 메서드 패턴(factory method pattern)자식 클래스에서 객체 생성 방법과 클래스를 결정할 수 있도록 미리 정의해둔 메서드(팩토리 메소드)를 통해 객체의 생성을 부모 클래스의 기본 코드에서 독립시키는 패턴이다.

 

관심을 분리한다는 것은 내부 동작에 상관없이 관심을 두지 않고 필요한 기능만 가져다 사용한다는 것이다. 

 

템플릿 메서드 패턴, 팩토리 메서드 패턴을 사용하면 관심 사항이 다른 코드를 분리해내고, 서로 독립적으로 변경, 확장을 할 수 있다. 하지만 상속을 사용하기 때문에 클래스의 다중 상속이 허용되지 않는 자바에서는 비용이 큰 편이고, 결합력이 높기 때문에 관심 사항은 분리했더라도 변경 시 변화의 파급력이 큰 편이다. 그래서 토비의 스프링 책에서는 인터페이스를 사용하여 분리를 하는 방식을 권장하는데 인터페이스를 사용하면 다형성으로 인해 의존관계를 외부에서 주입하고 클래스에서는 인터페이스 타입의 참조 변수를 통해 구현체의 메서드를 사용하면 되기 때문에 완벽하게 분리를 할 수 있다. 구현체가 변경이 되더라도 외부에서 변경된 구현체로 주입을 해주면 된다.

 

이렇게 보면 인터페이스를 사용하면 될 것 같은데 템플릿 메서드 패턴을 왜 쓰는지, 어떤 상황에 쓰이는지 잘 모르겠다. 다른 블로그를 찾아보다보니 템플릿 메서드 패턴과 비슷하면서 상속의 단점을 제거할 수 있는 전략 패턴이 있다고 하는데 인프런 김영한님의 스프링 고급편에도 템플릿 메서드 패턴에 대한 목차가 있어서 강의를 통해 더 깊게 공부해보고 코드로 사용해보면서 정리를 해봐야겠다.

 

 

 

 

[참고]

토비의 스프링

 

Overriding in Java - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

 

 

팩토리 메서드, 템플릿 메서드 패턴

1. 팩토리 메서드 패턴 팩토리 메서드 패턴(Factory Method Pattern)이란 객체 생성을 하는 클래스를 따로 두는 것입니다. 그래서 공장(Factory)이라는 표현을 쓰나봅니다. 🙂 실질적인 클래스의 구현은

western-sky.tistory.com

 

 

Template Method (템플릿 메서드) 패턴

1. Overview 코드를 작성하다보면 로깅, 예외 처리 등등 반복되어 작성하는 코드가 발생합니다. 이런 경우 코드의 중복을 없애기 위한 패턴 중 하나가 템플릿 메서드 패턴입니다. AbstractClass (추상

bcp0109.tistory.com

 

 

SwaggerREST API를 문서화하여 보기 편하게 시각화하고, 테스트할 수 있는 라이브러리로 서버 가동시 @RestController를 읽어서 API 분석을 해서 HTML로 문서화를 하기 때문에 API 문서를 직접 만들어서 수정시마다 일일이 수정하는 번거로움이 없어진다.

 

1. build.gradle

 

springfox-boot-starter로 추가하면 필요한 하위 라이브러리들이 전부 추가된다.

 

 

2. application.properties

 

spring boot 2.6.0 버전 이상인 경우에는 application.properties에서 spring.mvc.pathmatch.matching-strategy=ant_path_matcher을 추가하거나 2.6.0 밑으로 버전을 낮춰야 한다.

 

 

3. SecurityConfig

 

 

 

스프링 시큐리티를 사용하는 경우 해당 경로가 필터에 걸리지 않도록 permit해준다.

 

 

4. SwaggerConfig

 

Swagger 3.0을 사용하는 경우 Swagger2.x에서 사용하던 @EnableSwagger2 애노테이션을 사용하면 안 되고 Docket 생성시 DocumentationType.OAS_30으로 설정을 해야한다.

 

Swagger UI 화면을 보면 Contact와 ApiInfo에 입력한 정보들이 어디에 입력이 되는지 비교가 될 것이다.

 

 

그리고 JWT를 사용하기 때문에 관련 설정들을 해줘야 하는데 securitySchems는 API를 보호하는데 사용되는 보안 체계를 설정하는 것으로 ApiKey(또는 BasicAuth, OAuth)를 등록해서 JWT가 Authorization Header에 포함되도록 한다.

securityContext는 ApiKey로 정의한 JWT의 authorizationScope를 설정해서 SecurityReference를 포함해서 생성을 한다.

 

이제 실행을 하고 http://localhost:8080/swagger-ui/index.html 로 접속을 하면 아래와 같은 메인 화면이 뜬다. 

 

 

Authorize를 누르면 ApiKey로 등록한 정보가 나온다.

 

 

 

 

Spring Boot를 이용한 RESTful Web Services 개발 - 인프런 | 강의

이 강의는 Spring Boot를 이용해서 RESTful Web Services 애플리케이션을 개발하는 과정에 대해 학습하는 강의으로써, REST API 설계에 필요한 기본 지식에 대해 학습할 수 있습니다., - 강의 소개 | 인프런..

www.inflearn.com

 

Springfox Reference Documentation

The Springfox suite of java libraries are all about automating the generation of machine and human readable specifications for JSON APIs written using the spring family of projects. Springfox works by examining an application, once, at runtime to infer API

springfox.github.io

 

[swagger3] 설정 및 authroize button 활성화하기(Bearer 사용)

버전 2보다 좋은 점은 url에 다음과 같이 되어있을때 http://localhost:9001/swagger-ui/index.html#/1.Login/loginUsingPOST 브라우저로 접속하면 해당 api가 바로 펼쳐지면서 이동한다. (아마 그게 전부... 대신..

lemontia.tistory.com

 

Spring Boot Swagger 3.x 적용

1. Swagger 란? Swagger 는 OAS(Open Api Specification)를 위한 프레임워크입니다. 개발자들의 필수 과제인 API 문서화를 쉽게 할 수 있도록 도와주며, 파라미터를 넣어서 실제로 어떤 응답이 오는지 테스트도

bcp0109.tistory.com

 

Spring Boot2.6에서 Springfox3 실행 실패 에러

Intro Kotlin 프로젝트 였지만, Spring Boot 설정과 관련된 내용이기 때문에 java 로 프로젝트를 진행 하시는 경우에도 문제 해결을 하실 수 있습니다. Kotlin 과 스프링 부트를 이용해 API 서버를 만드는

shanepark.tistory.com

 

SpringBoot 2.6 이상 springfox-swagger3.0 적용 시 에러 해결

원인 spring boot 2.6.0부터 요청 경로를 ControllerHandler에 매칭시키기 위한 전략의 기본값이 ant_path_matcher 전략 -> path_pattern_parser 전략으로 변경되었기 때문이다. 해결 방안 2가지 application

velog.io

면접에서 리다이렉트(Redirect)와 포워드(Forward)의 차이점을 물어보는 질문이 나왔는데 포워드가 정확히 기억이 안 나서 대답을 못 했다.

 

먼저 리다이렉트는 웹 브라우저에게 해당 url로 다시 요청을 하라고 응답을 보낸다. 그래서 새로운 요청이 보내지기 때문에 url도 바뀌게 된다. 리다이렉트는 주로 POST 요청에서 사용을 하는데 HTTP 메서드중 POST는 예외적으로 멱등성이(똑같은 요청에 대해 같은 결과가 나오는 것) 성립하지 않기 때문에 새로고침 같은 반복 요청이 올 경우 리소스 생성이 여러번 일어나면서 문제가 생길 수 있다. 그래서 일반적으로 PRG(Post -> Redirect -> Get) 패턴으로 리다이렉트를 해준다.

 

리다이렉트를 할 때 redirectAttributes에 addAttribute() addFlashAttribute()를 사용하는 이유는 addAttribute의 경우에는 GET 요청 시 쿼리파라미터로 생성된 게시글의 id값을 넘겨주기 위함이고, addFlashAttribute()는 쿼리 파라미터로 넘겨지지 않고 일회성 용도로 사용이 된다. (저장이 완료되었다는 알림창을 띄우는 등)

 

redirect:/ 를 사용하면 UrlBasedViewResolver가 viewName이 "redirect"로 시작하는 것을 인식하고 동작을 한다.

 

 

타임리프의 th:if 문법으로 result의 값이 true일 경우 리다이렉트로 넘어온 것을 확인해서 저장이 완료되었다고 출력하게 하였다.

 

그리고 redirect 과정이 어떻게 되는지 보려고 디버깅을 해보았는데 블로그분처럼 따라가는게 어려워서 나중에 다시 해봐야겠다. 

(invokeForRequest 반환으로 returnValue에 "redirect:/board/read"가 넘어오는 것까지 확인)

 

중요한 것은 리다이렉트와 포워드의 차이점인데 리다이렉트는 302 상태코드로 응답을 하고 Location으로 새로운 GET 요청을 한다.

아래와 같이 응답 리다이렉트를 받고 다시 요청이 오게 된다.

반면 포워드는 온전히 서버측에서 발생하는데 웹 브라우저로 이동하여 새로운 요청이 생기는 것이 아니라 서블릿 컨테이너에서 동일한 요청을 해당 Url로 다시 보내는 것이기 때문에 url은 브라우저에서 바뀌지 않고 처음 요청한 url로 보이게 된다. (Request 객체가 살아있는 것)

사실 리다이렉트만 필요시 사용을 해보고 포워드를 활용해서 다른 url로 넘겨서 사용해본 적이 없어서 어떤 상황에 쓰이는지 잘 모르겠다.

 

 

 

IntelliJ 디버깅 해보기

안녕하세요? 이번 시간엔 intellij의 debugging 을 간단하게 진행해보려고 합니다. 모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다. (공부한 내용을 정리하는 Github와

jojoldu.tistory.com

 

Spring) 스프링의 "redirect:" 리다이렉트 처리

Intro Spring Framework 를 사용한다면 컨트롤러에서 리턴타입은 String으로 하고 view 이름 대신 "redirect:" 로 시작하는 문자열을 반환 하면 해당 주소로 리다이렉트를 시켜 줍니다. "redirect:" 를 했는데 리

shanepark.tistory.com

 

A Guide To Spring Redirects | Baeldung

A guide to redirect and forward in Spring MVC, with a focus on the code and implementation of each strategy.

www.baeldung.com

 

 

[Web] Forward와 Redirect 차이

웹은 현재 작업중인 페이지에서 다른 페이지로 이동하기 위해 2가지 페이지 전환 기능을 제공합니다. 오늘은 2가지의 페이지 전환 방법의 차이와 사용법에 대해 알아보도록 하겠습니다. 1. Forward

mangkyu.tistory.com

 

 

스프링에서 Mybatis를 사용하기 위해서는 Mybatis 스프링 연동 모듈이 필요한데 이는 마이바티스와 스프링을 편하고 간단하게 사용할 수 있도록 지원해준다.

 

SqlSessionFactory

 

데이터 베이스의 연결과 SQL 실행에 대한 모든 것을 가지고 있으며 DataSource를 필요로 한다.

@Configuration
public class MyBatisConfig {
  @Bean
  public SqlSessionFactory sqlSessionFactory() throws Exception {
    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
    factoryBean.setDataSource(dataSource());
    return factoryBean.getObject();
  }
}

스프링은 SqlSessionFactoryBean에서 getObject() 메서드를 호출하여 반환된 SqlSessionFactory를 빌드하여 sqlSessionFactory 라는 이름으로 저장한다. SqlSessionFactoryBean이나 SqlSessionFactory를 직접 사용할 일은 없고 MapperFactoryBean를 확장하는 다른 DAO에 주입 될 것이다.

 

 

 

MapperFactoryBean

 

MapperFactoryBean SqlSession을 생성하고 닫는 역할을 하며 실행중인 스프링 트랜잭션을 관리하고 예외 발생시 스프링의 DataAccessException예외로 변환해준다. 

@Configuration
public class MyBatisConfig {
  @Bean
  public UserMapper userMapper() throws Exception {
    SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory());
    return sqlSessionTemplate.getMapper(UserMapper.class);
  }
}

 

SqlSesssion과 SqlSessionTemplate

SqlSession SqlSessionFactory에 의해 생성되며 매핑 구문을 실행하거나 트랜잭션 커밋, 롤백 등을 할 수 있는데 마이바티스 스프링 연동 모듈은 자동으로 SqlSession을 스프링 빈에 주입하고 스프링이 직접 트랜잭션을 관리한다. 

스프링이 관리하는 SqlSession에서는 SqlSession.commit(), SqlSession.rollback() 또는 SqlSession.close() 메서드를 호출할수가 없다. (사용 시 UnsupportedOperationException 예외가 발생)

 

SqlSessionTemplate은 인자로 SqlSessionFactory를 받아서 생성되는데 SqlSession이 현재의 스프링 트랜잭션에서 사용 될 수 있도록 보장하는데 필요한 시점에 세션을 닫고, 커밋하거나 롤백하는 것을 포함한 세션의 생명주기를 관리한다. 또한 마이바티스 예외를 스프링의 DataAccessException로 변환하는 작업도 처리한다.

 

TransactionManager

 

마이바티스 스프링 연동 모듈은 스프링 PlatformTransactionManager의 구현체인 DataSourceTransactionManager를 사용하여 스프링 트랜잭션에 자연스럽게 연동될 수 있는데 DataSourceTransactionManager는 Connection 객체에 존재하는 트랜잭션 API를 사용하여 트랜잭션을 관리해주는 TransactionManager다.

 

참고)

JPA는 JpaTransactionManager를 사용하며 EntityManagerFactory가 스프링 빈으로 등록된 DataSource를 사용하는데 JPA에서 사용하는 DataSource를 Mybatis에서도 사용할 수 있다. Mybatis만 사용할 경우 DataSourceTransactionManager를 스프링 빈으로 등록하지만, JPA를 사용할 경우 JPATransactionManager로 같이 관리가 가능하기 때문에 별도의 TransactionManager를 등록할 필요가 없다.

 

Spring boot :: JPA, Mybatis Transaction Manager 정리

Introduction 이번에는 Mybatis 와 JPA 를 동시에 적용한 환경에서 어떤 transactionManager 를 사용해야되는지 살펴보려고 한다. 해당 글은 스프링에서 트랜잭션을 담당하는 핵심 인터페이스인 PlatformTransact

wave1994.tistory.com

 

 

Mapper Interface

Mybatis XML 파일에 SQL을 호출하기 위한 인터페이스로  편리하게 XML의 데이터를 찾아서 호출해주고 MyBatis에서 발생한 예외를 스프링 예외 추상화인 DataAccessException에 맞게 변환해주는 등 지금까지 말한 기능들을 담당한다.

 

Mybatis 3.0 이후 버전부터는 SqlSessionTemplate를 직접적으로 사용하는 DAO를 생성하지 않고 다른 빈에 직접 주입할 수 있는 쓰레드에 안전한 매퍼를 생성하여 사용한다. 리포지토리에 Mapper 인터페이스를 주입하여 사용하는 것을 생각하면 된다. 여러 설정들이 간편하게 자동화되며 스프링 부트를 사용하면 Mapper 인터페이스를 Bean으로 등록할 필요도 없이 @Mapper 애노테이션만 사용하면 된다.

 

 

Mybatis-Spring-Boot-Starter

  • DataSource 자동 감지
  • SqlSessionFactoryBean을 사용해서 DataSource를 전달하는 SqlSessionFactory의 객체를 생성하고 등록
  • SqlSessionFactory를 이용해 SqlSessionTemplate를 생성하고 등록
  • Mapper를 스캔한 뒤 SqlSessionTemplate에 연결하고 Mapper 인터페이스를 프록시 구현체로 생성하여 스프링 빈으로 등록해서 리포지토리에 주입할 수 있게 해준다.

 

 

Mybatis-Spring-Boot-Starter 소개 문서 번역

마이바티스-스프링 부트-스타터 문서 번역

kgmyh.github.io

 

 

mybatis-spring –

소개 MyBatis-Spring 은 무엇일까? 마이바티스 스프링 연동모듈은 마이바티스와 스프링을 편하고 간단하게 연동한다. 이 모듈은 마이바티스로 하여금 스프링 트랜잭션에 쉽게 연동되도록 처리한다.

mybatis.org

 

[Mybatis]란? / SqlSessionTemplate, MapperInterface 개념/빈 등록 설정

[MyBatis]란 무엇인가 에 대해서 또 SqlSessionTemplate/MapperInterface 두가지 방식에 따른 전체적인 구조 차이와 Mapper.xml 속성 차이에 대해 정리합니다. [MyBatis]란? 앞서 사용해 보았던 Jdbc-Template도..

u-it.tistory.com

 

+ Recent posts