본문 바로가기

Spring boot/Bank App 만들기(deployment)

Bank App 만들기 ( deployment ) - 2단계 ( ResourceHandler, 초기 파라미터 사용 )

WebMvcConfigurer 인터페이스는 Spring MVC 설정을 맞춤화할 수 있는 메서드를 제공한다. 개발자는 이 인터페이스를 구현하여 기본 제공되는 스프링 부트의 자동 구성을 수정하거나 추가적인 설정을 할 수 있다.

 

 

  1. ViewResolver : 뷰 리졸버는 컨트롤러에서 반환된 뷰 이름을 바탕으로 실제 뷰의 위치를 찾아내고 렌더링하는 역할을 한다. 예를 들어, JSP 파일이나 Thymeleaf 템플릿 등의 실제 경로를 결정한다.
  2. addResourceHandlers : 정적 리소스(예: CSS, JavaScript, 이미지 파일 등)핸들링을 위한 경로를 추가하는 데 사용됩니다. 이를 통해 정적 리소스에 대한 매핑을 정의하고 리소스 캐싱 정책을 설정할 수 있다.
  3. setApplicationContext : 스프링 컨텍스트에 접근하거나 커스텀 리소스 로딩 등의 설정을 할 때 사용된다. ApplicationContextAware : 인터페이스를 통해 애플리케이션 컨텍스트를 설정하고 관리한다.
  4. Template Engine : 템플릿 엔진 설정은 주로 addViewControllers 메서드와 함께 사용되며, 특정 URL 요청에 대해 템플릿 엔진을 통한 뷰를 렌더링하는 방법을 정의한다.
  5. Interceptor Registration: 인터셉터는 요청 처리의 전/후 또는 요청 처리 중에 특정 로직을 실행할 수 있게 해주는 컴포넌트이다. addInterceptors 메서드를 통해 인터셉터를 등록하고 설정할 수 있다.

 

 

WebMvcConfig 코드 추가
package com.tenco.bank.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.tenco.bank.handler.AuthInterceptor;

import lombok.RequiredArgsConstructor;

@Configuration   
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {
	
	@Autowired // DI
	private final AuthInterceptor authInterceptor;
	// @RequiredArgsConstructor <-- 생성자 대신 사용 가능
	
	// 우리가 만들어 놓은 AuthInterceptor 를 등록해야 함. 
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(authInterceptor)
			.addPathPatterns("/account/**")
			.addPathPatterns("/auth/**");
	}
	
	// 코드추가 
	// C:\Users\GGG\Documents\Lightshot\a.png <-- 서버 컴퓨터상에 실제 이미지 경로지만 
	// 프로젝트 상에서(클라이언트가 HTML 소스로 보이는 경로는) /images/uploads/**
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/images/uploads/**")
		.addResourceLocations("file:\\C:\\work_spring\\upload/");
	}
	
	@Bean // IoC 대상(싱글톤 처리) 
	PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}	
}

Spring MVC의 WebMvcConfigurer 인터페이스를 구현하는 클래스의 addResourceHandlers 메서드를 오버라이드하여, 웹 애플리케이션에서 정적 리소스를 제공하는 방법을 정의다. 여기서 정의된 설정은 애플리케이션의 /images/uploads/** URL 패턴으로 요청되는 모든 리소스를 처리하는 방법을 지정한다.

 

 

 

header.jsp - JSTL 태그 활용
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html>
<html lang="en">
<head>
<title>myBank</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/ko.ico" type="image/x-icon">
<link rel="stylesheet" href="/css/common.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
	<div class="m--flex-container">
		<div class="m--container">
			<div class="jumbotron text-center m--banner-img" style="margin-bottom: 0">
				<h1>My Bank</h1>
				<p>마이바티스를 활용한 스프링 부트 앱 만들어보기</p>
			</div>

			<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
				<a class="navbar-brand" href="/index">홈</a>
				<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
					<span class="navbar-toggler-icon"></span>
				</button>
				<div class="collapse navbar-collapse" id="collapsibleNavbar">
					<ul class="navbar-nav">
						<c:choose>
							<c:when test="${principal != null}">
								<%-- 사용자가 로그인 상태 --%>
								<li class="nav-item"><a class="nav-link" href="/user/logout">로그아웃</a></li>
							</c:when>
							<c:otherwise>
								<%-- 사용자가 로그인 하지 않은 상태 --%>
								<li class="nav-item"><a class="nav-link" href="/user/sign-in">로그인</a></li>
								<li class="nav-item"><a class="nav-link" href="/user/sign-up">회원가입</a></li>
							</c:otherwise>
						</c:choose>
					</ul>
				</div>
			</nav>

			<div class="container" style="margin-top: 30px">
				<div class="row">
					<div class="col-sm-4">
						<h2>About Me</h2>
						<h5>Photo of me:</h5>
						
						<!-- start 코드 수정 -->
						<!-- 1. 로그인 유무 확인 -->
						<c:choose>
							<c:when test="${principal != null}">
								<img class="m--profile" src ="${principal.setUpUserImage()}" alt="사용자 이미지">
							</c:when>
							<c:otherwise>
								<div class="m--profile"></div>
							</c:otherwise>
						</c:choose>
						
						<!-- end 코드 수정 -->
						
						<p>코린이 개발을 위한 뱅크앱</p>
						<h3>서비스 목록</h3>
						<p>계좌목록, 생성, 출금, 입금, 이체 페이지를 활용할 수 있어요!</p>
						<ul class="nav nav-pills flex-column">
							<li class="nav-item"><a class="nav-link" href="/account/list">나의계좌목록</a></li>
							<li class="nav-item"><a class="nav-link" href="/account/save">신규계좌생성</a></li>
							<li class="nav-item"><a class="nav-link" href="/account/withdrawal">출금하기</a></li>
							<li class="nav-item"><a class="nav-link" href="/account/deposit">입금하기</a></li>
							<li class="nav-item"><a class="nav-link" href="/account/transfer">이체하기</a></li>
						</ul>
						<hr class="d-sm-none">
					</div>

					<!-- end of header.jsp -->

 

 

 

 

초기 파라미터를 이용해서 경로를 수정해 보기

appliaction.yml 파일에 코드 추가 하기
logging:
  level:
    org.apache.ibatis: DEBUG #MyBatis 로깅 레벨을 DEBUG로 설정하여 실행되는 SQL 쿼리와 내부 로깅 정보를 콘솔에 출력합니다.

# 초기 파라메터 설정 
file:
  upload-dir: C:\\work_spring\\upload/

 

 

 

 

UserService
package com.tenco.bank.service;



@Service // IoC 대상( 싱글톤으로 관리) 
@RequiredArgsConstructor
public class UserService {
	
	//... 생략 	
	// 초기 파라메터 가져오는 방법 
	@Value("${file.upload-dir}")
	private String uploadDir;
	
	
	// ... 생략 
	
	/**
	 * 서버 운영체제에 파일 업로드 기능 
	 * MultipartFile getOriginalFilename : 사용자가 작성한 파일 명 
	 * uploadFileName : 서버 컴퓨터에 저장 될 파일 명 
	 * @return
	 */
	private String[] uploadFile(MultipartFile mFile) {
		
		if(mFile.getSize() > Define.MAX_FILE_SIZE) {
			throw new DataDeliveryException("파일 크기는 20MB 이상 클 수 없습니다.", HttpStatus.BAD_REQUEST);
		}
		
		// 코드 수정 
		// File - getAbsolutePath() : 파일 시스템의 절대 경로를 나타냅니다.
		// (리눅스 또는 MacOS)에 맞춰서 절대 경로가 생성을 시킬 수 있다. 
		// String saveDirectory = new File(uploadDir).getAbsolutePath();
		String saveDirectory = uploadDir;
		
		// 파일 이름 생성(중복 이름 예방) 
		String uploadFileName = UUID.randomUUID() + "_" + mFile.getOriginalFilename();
		// 파일 전체경로 + 새로생성한 파일명 
		String uploadPath = saveDirectory + File.separator + uploadFileName;
		System.out.println("----------------------------");
		System.out.println(uploadPath);
		System.out.println("----------------------------");
		File destination = new File(uploadPath);
		
		// 반드시 수행
		try {
			mFile.transferTo(destination);
		} catch (IllegalStateException | IOException  e) {
			e.printStackTrace();
			throw new DataDeliveryException("파일 업로드중에 오류가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR);
		} 	
		return new String[] {mFile.getOriginalFilename(), uploadFileName}; 
	}	
}
728x90