안녕하세요. 이번 포스팅에서는 spring 빌드 시에 npm 라이브러리를 추가하는 방법에 대해 포스팅하도록 하겠습니다.
저희가 흔히 타임리프 혹은 jsp와 같은 템플릿 엔진을 사용하게되면, javascript라이브러리를 링크를 통해 첨가하는 경우가 많습니다.
가령
html head태그에
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
위와 같이 https:~~ 링크를 통해 해당 라이브러리를 추가하는 경우를 볼 수 있습니다. 특별한 경우가 아니면 위 방식도 괜찮은 방법입니다.
하지만 생각을 조금 바꾸어보면, 링크주소가 변경되거나 추가 버전이 릴리즈 되어 구 버전을 더 이상 활용할 수 없게 될 수도 있습니다. 또한 네트워크 문제에 따라 서비스가 불안정해질 수도 있습니다. 만약에 위 라이브러리들을 사전에 받아놓고, 저희가 빌드 시에 추가할 수 있다면 위 방식보다 훨씬 좋은 방법일 것입니다.
결과적으로 저희가 첨부하고 싶은 방식은 아래와 같습니다.
<head th:fragment="head">
<meta charset="UTF-8">
<title>StudyOlle</title>
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="/node_modules/font-awesome/css/font-awesome.min.css" />
<script src="/node_modules/jdenticon/dist/jdenticon.min.js"></script>
<script src="/node_modules/jquery/dist/jquery.min.js"></script>
<script src="/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<style>
.container {
max-width: 100%;
}
</style>
</head>
node_modules라는 디렉토리를 빌드 시에 자동으로 생성하여 저희가 필요한 라이브러리들을 넣어놓고, 서비스 도중 끊기지 않고 사전에 받아놓은 라이브러리들을 사용하게 만드는 것이 이번 포스팅의 목적입니다.
src/main/resources/static 디렉토리로 이동하여 npm을 설치하여 줍니다. src/main/resources/static 디렉토리 이하는 정적 리소스를 제공합니다. 이 디렉토리에 package.json 파일을 활용하여 빌드 시 필요한 라이브러리들을 받고, 정적 리소스로 서비스에 제공하겠습니다.
npm init
npm install ... (ex bootstrap, jquery)
가장 중요한 것은 반드시 위 디렉토리 이하에 npm을 설치해 주셔야 합니다. npm init을 한 뒤, 필요한 라이브러리들을 설치해주시면 됩니다.
설치가 끝났으면 package.json 파일이 생성된 것을 보실 수 있습니다.
{
"name": "static",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "echo Building frontend",
"check": "echo Checking frontend && npm run lint && npm run test",
"clean": "echo Cleaning frontend",
"lint": "echo Linting frontend"
},
"author": "",
"license": "ISC",
"dependencies": {
"bootstrap": "^4.4.1",
"cropper": "^4.1.0",
"font-awesome": "^4.7.0",
"jdenticon": "^2.2.0",
"jquery": "^3.4.1",
"jquery-cropper": "^1.0.1"
}
}
scripts부분은 수동으로 추가해주시면 됩니다.
이제 빌드 설정을 하셔야 합니다. build.gradle 파일로 이동하셔서 필요한 코드를 추가해줍니다.
buildscript{
ext {
springBootVersion = '2.5.2'
}
repositories {
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath "com.github.node-gradle:gradle-node-plugin:3.1.0"
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: "com.github.node-gradle.node"
node {
version = '11.15.0'
download = true
nodeModulesDir = file("${projectDir}/src/main/resources/static")
}
task copyFrontLib(type: Copy) {
from "${projectDir}/src/main/resources/static"
into "${projectDir}/build/resources/main/static/."
}
copyFrontLib.dependsOn npmInstall
compileJava.dependsOn copyFrontLib
group = 'com.StudyProject'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
... (dependency 생략)
testCompile('org.projectlombok:lombok')
testAnnotationProcessor('org.projectlombok:lombok')
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}
test {
useJUnitPlatform()
}
주의깊게 보셔야 할 부분은 우선 classpath에 node-plugin을 추가하여 주시고, plugin에 com.github.node-gradle.node를 추가해 주셔야 합니다. 위 코드와 똑같이 작성하시면 됩니다.
node {
version = '11.15.0'
download = true
nodeModulesDir = file("${projectDir}/src/main/resources/static")
}
이부분에서 version은 현재 사용하고 계신 npm 버전을 적어주시면 됩니다. nodeModulesDir경로를 만들어 주세요.
task copyFrontLib(type: Copy) {
from "${projectDir}/src/main/resources/static"
into "${projectDir}/build/resources/main/static/."
}
이 부분에서 이제 src/main/resources/static에 있는 정적 리소스들을 build시에 /build/resources/main/static/으로 옮겨 서비스에서 정적 리소스로 사용할 수 있게 copy task를 수행하여 줍니다.
만약 성공적으로 위 작업이 끝났다면, gradle build시에
아래와 같이 node_modules라는 디렉토리가 생깁니다. 여기에 저희가 원하는 라이브러리들이 담겨있고, 빌드 시에 /build/resources/main/static/ 로 옮겨집니다.
*추가로 만약에 security를 적용한 프로젝트라면 security에 node_modules 디렉토리에 대한 권한을 풀어주셔야 합니다. 그렇지 않다면 위 디렉토리에 대한 권한이 없기 때문에 빌드 시에 라이브러리를 가져올 수 없습니다.
<*securityConfig>
package com.communityProject.config;
... import 생략
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final DataSource datasource;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("/", "/sign-up", "/login", "...", ...).permitAll()
.anyRequest().authenticated();
http.formLogin()
.loginPage("/login").permitAll();
http.logout()
.logoutSuccessUrl("/");
}
@Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.ignoring()
.mvcMatchers("/node_modules/**")
.requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}
}
여기까지 진행이 되셨다면 이제 실제로 확인을 해보시면 됩니다.
저같은 경우는 bootstrap의 기본적인 css들을 사용하였는데 정상적으로 빌드 시에 추가된 것을 볼 수 있습니다.
추가로 가시적이지 않지만 정상적으로 라이브러리가 빌드된 것을 확인하시고 싶으시면 f12를 눌러 Network tab에서 정상적으로 라이브러리들이 가져와졌는지 확인해보시면 됩니다. 제 경우 정상적으로 작동합니다.
이번 포스팅을 마치도록 하겠습니다.
*저의 글에 대한 피드백이나 지적은 언제나 환영합니다.
'Backend > Spring' 카테고리의 다른 글
[Spring Boot] JWT token, refresh token을 활용한 회원 도메인 구현 (4) | 2021.09.30 |
---|---|
[Spring/SpringBoot] Spring Security - Remember Me (0) | 2021.08.11 |
[Spring/SpringBoot] SpringSecurity를 API Server에 적용하기(JWT) (0) | 2021.07.27 |
[Spring/SpringBoot] RestController에서 Validation Api 사용하기 + MethodArgumentNotValidException 예외 처리하기 (2) | 2021.07.21 |
[Spring/SpringBoot] 예외처리 Controller 정의하기 (0) | 2021.07.20 |