공상하는 개발자

[Spring/JAVA] 스프링 파헤치기. 본문

개발

[Spring/JAVA] 스프링 파헤치기.

공상과학소설 2020. 5. 23. 23:52
반응형

ssafy에서 스프링 프로젝트를 진행하는 공부의 필요성을 느끼고

블로그 포스팅을 하게 되었다.

스프링을 살짝 맛보긴 했는데, servlet, jsp의 불편한 점을 간편하게 만들어주어서 사용하기에 편리했다.

이 요물 스프링에 대해서 좀 더 파헤쳐보자.


스프링이란?

※ 자바 애플리케이션을 만들기 위한 프레임워크

 

★ 여기서 잠깐! 프레임 워크와 라이브러리의 차이점은 무엇일까?

라이브러리 : 애플리케이션 개발에 필요한 기능을 제공.

프레임워크 : 비즈니스 로직이 빠진 뼈대만 갖춰진 애플리케이션.

→ 개발자는 프레임워크의 뼈대에 적합한 비즈니스 로직만 집중해서 공급! (로직에만 집중할 수 있어서 편리하다!)

 

※ Light Weight FrameWork

◆ 스프링 애플리케이션은 특정 JavaEE 클래스를 상속받을 필요가 없음

◆ 프로그래머는 POJO 형태로 일반적인 Java 애플리케이션 작성.

 

자바 애플리케이션을 만들기 위한 Container

◆ 스프링은 애플리케이션의 객체를 위한 컨테이너로써 동작.

  • 스프링은 객체의 생성 및 관계 주입하는 객체의 lifecycle 관리자로써 동작.
  • 개발자가 객체들 간에 서로를 찾거나 연걸하기 위해 신경 쓸 필요가 없음.

DI (Dependency injection)

※ 의존 관계

객체간 참조로 인해 참조되는 객체 변경 시 참조하는 객체가 영향을 받는 것.

● Client는 메타정보와 함께 DI Container(ApplicationContext의 구현체)를 생성.

● Client는 DI Container를 통해 Service 획득.

 

DI의 흐름


스프링의 @Configuration 어노테이션

▶ 스프링의 @Configuration 어노테이션은 어노테이션 기반 환경 구성을 돕는다. 이 어노테이션을 구현함으로써 클래스가 하나 이상의 @Bean 메서드를 제공하고 스프링 컨테이너가 Bean 정의를 생성하고 런타임 시 그 Bean들이 요청들을 처리할 것을 선언하게 된다.

 

스프링의 구조(MVC 패턴)

구조는 크게 dto, repository, service, Controller 가 있다.

Controller에서 Service를 부르고 Service에서 Repo를 불러 디비에 접근하는 방식이다. 따로 객체를 생성할 필요 없이 @Autowired를 통해 주입해주면 쓸 수 있다. 

 

Controller

@Controller
public class HomeController {

	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

	@Autowired
	ProductService service;

	@GetMapping("/productlist")
	public String productList(Model model) {
		model.addAttribute("product", service.selectAll());
		return "productlist";
	}

	@PostMapping("/productlist")
	public String productRegist(Model model, @ModelAttribute Product product) {
		service.insert(product);
		model.addAttribute("product", service.selectAll());
		return "productlist";
	}

	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		System.out.println("Asdsa");
		return "home";
	}

controller는 서버의 요청을 처리해주는 역할을 한다. @GetMapping을 통해 Get의 요청을 처리하고, @PostMapping을 통해 Post의 요청을 처리해준다. 이 로직에서는 service의 함수를 호출하여 디비에 접근하려고 하고 있다. 

그럼 서비스를 살펴보자.

 

Service

@Service
public class ProductServiceImpl implements ProductService {

	@Autowired
	ProductRepo repo;

	@Override
	public Product select(String id) {
		return repo.select(id);
	}

	@Override
	public int insert(Product product) {
		return repo.insert(product);
	}

	@Override
	public List<Product> selectAll() {
		return repo.selectAll();
	}

}

service 인터페이스를 구현해놓은 serviceImpl 클래스이다. repo를 주입받아 repo의 메서드를 부르고 있다.

Repository

@Repository
public class ProductRepoImpl implements ProductRepo {

	static String ns = "com.ssafy.mapper.Product.";

	@Autowired
	SqlSessionTemplate temp;

	@Override
	public Product select(String id) {
		return temp.selectOne(ns + "select", id);
	}

	@Override
	public int insert(Product product) {
		return temp.insert(ns + "insert", product);
	}

	@Override
	public List<Product> selectAll() {
		return temp.selectList(ns+"selectAll");
	}

}

repository에서는 mapper를 이용해서 db의 쿼리문에 접근하여 수행하고 있다.

Mapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssafy.mapper.Product">

	<select id="select" parameterType="String" resultType="Product">
		select * from
		Product where id=#{id}
	</select>

	<select id="selectById" parameterType="String"
		resultType="Product">
		select id,name,price,description from Product where id=#{id}
	</select>

	<select id="selectAll" resultType="Product">
		select * from Product
	</select>

	<insert id="insert" parameterType="Product">
		insert into Product(id,name,price,description) value(#{id},#{name},#{price},#{description})
	</insert>
	
	<!-- 가장 안전한 것은 한땀 한땀 매핑 시켜주는 것 -->
	
</mapper>

mapper의 쿼리문이다. Repo로부터 불러지면 그에 해당하는 쿼리가 실행된다.

 

이 모든 DI는 config에서 Bean들을 생성하고 스캐닝을 통해 주입을 해줬기 때문이다.

Config

@Configuration
@ComponentScan(basePackageClasses = { ProductRepo.class, ProductService.class })
public class ApplicationConfig {

	@Bean
	public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource ds) {
		SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
		factoryBean.setDataSource(ds);
		String configLoc = "classpath:/mybatis/mybatis_config.xml";
		factoryBean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource(configLoc));
		return factoryBean;
	}

	@Bean
	public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactoryBean sfb) throws Exception {
		SqlSessionTemplate template = new SqlSessionTemplate(sfb.getObject());
		return template;
	}

	@Bean
	public DataSource ds() {
		DriverManagerDataSource ds = new DriverManagerDataSource();
		ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
		ds.setUrl("jdbc:mysql://127.0.0.1:3306/ssafydb?serverTimezone=UTC");
		ds.setUsername("ssafy");
		ds.setPassword("ssafy");
		return ds;
	}
}

@ComponentScan 어노테이션을 통해 스캔한 class의 패키지에서 불러올 수 있게 했다.


결론

Spring은 오지게 간단하다. servlet과 jsp를 이용해서 디비를 사용할 때도 번거로운 코드들을 만들어줬어야 했는데 그 수고로움과 복잡함을 70%는 덜어준 것 같다. 

왜 봄도 아닌 계절에도 스프링 스프링 거리는지 알게 된 거 같다. 아직 미숙하지만 좀 더 공부해서 익숙해지도록 하겠다!!

반응형
Comments