배경 : 진현님 고등학교 베프 학생분과 이야기를 하면서, 이 친구에게 조금이라도 독려를 해주고 싶은 마음과, 도움을 주고 싶은마음에, 마침 나도 회사에서 중요한 업무들이 끝나는 시점이라 같이 따라하면서 기본을 챙기고, 그 친구에게 조금이라도 좀 더 도움을 주고 싶은 마음에서 시작함.
참고 : 아래 글은 점프 투 스프링부트 위키독스 내용을 공부하였고, 그 내용을 정리하였습니다
내용:
1장 스프링 부트 개발 준비하기
스프링부트를 향한 첫걸음 -> 절반은 성공! ㅋㅋ
"흐름" 이 중요, "시작" 이 중요!
1-01 스프링 부트란?
- 웹 프로그램(어플리케이션)을 쉽고 빠르게 만들 수 있도록 도와주는 (자바의) 웹 프레임워크
- 스프링(Spring) 프레임ㅋ워크 + 톰캣(Tomcat) 서버 내장, 여러 편의 기능을 추가.
웹 프레임워크란?
쿠키, 세션, 로그인/로그아웃, 권한, 데이터베이스 등 기능들을 웹 프레임워크에 이미 기능들이 만들어져 있어서, 이 웹 프레임워크에 있는 기능을 익혀서 사용하기만 하면 된다. (웹 프로그램을 만들기 위한 스타터 키트)
예제) 웹 프라우저에 Hello World 출력
@Controller
public class HelloController {
@GetMapping("/")
@ResponseBody
public String hello() {
return "Hello World";
}
}
스프링 부트를 배워야 하는 이유
1. 튼튼한 웹 프레임워크
보안 기능
SQL 인젝션[악의적인 SQL 주입], XSS(cross-site scripting)[자바스크립트 삽입], CSRF(Cross-Site Request Forgery)[위조된 요청], 클릭재킹(clickjacking)[의도치 않은 클릭 유도]과 같은 보안 공격을 막아준다.
여러 기능
로그인 : 네이버나 구글 로그인 처럼 사용자 인증 하는 기능]
페이징 : 한 페이지에 데이터가 많으면 페이지별 나누어 조회할 수 있계 하는 기능]
WAS가 필요없다.
스프링부트에는 톰캣 서버가 내장되어 있고, 설정도 자동 적용됨
배포되는 jar 파일에도 톰캣 서버가 내장되어 실행.
WAS란
- 웹 어플리케이션과 서버 환경을 연결하는 중간 역할을 하는 소프트웨어 플랫폼
- 사용자가 웹 브라우저로 서버에 요청을 보내면, WAS는 사용자의 요청을 해석하여 그에 맞는 서버 프로그램을 구동 한 후 그 결과를 사용자에게 보여줌
2. 설정이 쉽다
스프링으로 개발시 복잡한 설정 때문에 많은 어려움을 겪음.
이 복잡한 설정을 자동화,단순화 하여, 누구나 쉽게 스프링을 사용할 수 있도록 한 프레임워크
3. 재미 있다
레고를 조립하는 것 처럼 웹 애플리케이션이 완성되어 가는 과정을 즐기게 된다. (필자 왈 ㅎㅎ)
1-02 스프링 부트 개발 환경 준비하기
1~3 생략.
4 는 IntelliJ 로 진행.
프로젝트 --> 프로젝트 생성 --> 아래 정보로 입력 --> 다음 클릭
스프링 부트 버전은 3.3.6, 의존성은 Web --> Spring Web 선택 후 생성 버튼 클릭
프로젝트가 생성 완료 된 것을 확인 할 수 있다.
막 뭔가 다운로드 받다가.. 오류 메세지 나서 Gradle 재 빌드를 했더니 아래와 같이 정상 노출되었다
1-03 스프링 부트 맛보기
Hello World 출력 하는 웹 프로그램 만들어보기.
웹 서비스는 어떻게 동작할까?
클라이언트와 서버 구조 이해하기
요청
웹브라우저 --> 웹 서버
↗ html 문서 <-- html 문서 ↖
응답
[클라이언트] [서버]
브라우저 --> 서버 요청 보낼때는 서버의 주소(IP) 또는 서버의 주소를 대체할 수 있는 도메인명 을 알아야 함.
예시) naver.com 입력 --> 네이버에서 운영하는 웹 서버 호출 --> 서버는 요청에 대한 응답을 브라우저에 돌려준다.
즉 웹 서버는 요청에 대한 응답으로 HTML 문서나 다른 리소스들을 브라우저에 표시.
IP 주소와 포트 이해하기
프로토콜 | 서비스 내용 | 포트 |
HTTP | 웹 서비스 | 80 |
HTTPS | SSL을 적용한 웹 서비스 | 443 |
FTP | 파일 전송 서비스 | 21 |
SSH, SFTP | 보안이 강화된 TELNET, FTP 서비스 | 22 |
TELNET | 원격 서버 접속 서비스 | 23 |
SMTP | 메일 전송 서비스 | 25 |
(필요에 따라 포트 번호를 별도로 정의, 변경 가능. 예시 - HTTP 포트를 80 대신 8080 사용할 수 있음)
localhost:8080 이해하기
localhost(로컬호스트) : 도메인명, 127.0.0.1 이라는 ip 주소를 의미. (127.0.0.1 = 내 컴퓨터 의미)
localhost:8080 = 내 컴퓨터(localhost)에 8080번 포트로 실행된 서비스를 의미
내 컴퓨터에 실행된 서버는 로컬 서버 이므로, 외부에서는 접속 불가. (외부에서 접속하게 하는 방법은 4장에서 설명)
컨트롤러 만들기
http://localhost:8080/hello 와 같은 브라우저의 요청을 처리하려면 컨트롤러가 필요함
컨트롤러 : 서버에 전달된 클라이언트의 요청을 처리하는 자바 클래스.
HelloController Class 생성 후 책 본 내용을 입력
package com.ksko.sbb;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller//HelloController 클래스가 컨트롤러의 기능을 수행 한다는 의미
public class HelloController {
/*
용어 설명
1. 애너테이션(annotation) : 자바의 클래스, 메서드, 변수 등에 정보를 부여하여 부가 동작을 할 수 있게 하는 목적으로 사용
2. 매핑(mapping)하다 : 특정 URL 경로를 서버의 특정 메서드와 연결하는 것을 의미
3. Get 방식, Post 방식 차이
- Get과 Post는 HTTP 프로토콜을 사용하여 데이터를 서버로 전송하는 방식
1) Get 방식 : 데이터를 URL에 노출시켜 요청하며, 주로 서버에서 데이터를 조회하거나 읽기 위한 목적으로 사용
2) Post 방식 : 데이터를 숨겨서 요청하므로 로그인 정보와 같은 민감한 데이터를 서버에 제출하거나 저장하는 목적으로 사용
@GetMapping : Get 방식으로 URL 요청
@PostMapping : Post 방식으로 URL 요청
*/
@GetMapping("/hello") // http://localhost:8080/hello URL 요청이 발생하면 hello 메서드가 실행됨을 의미. 즉 /hello URL과 hello 메서드를 매핑하는 역할. 이때 URL명과 메서드명이 동일할 필요는 없다. 즉, /hello URL 일때 메서드명을 hello가 아닌 hello2 와 같이 써도 상관 없음
@ResponseBody // hello 메서드의 출력 결과가 문자열 그 자체임을 나타냄.(출력결과는 이런 String 문자열 보다, html 파일과 같은 템플릿이 주로 사용)
public String hello() {
return "Hello World";
}
}
로컬 서버 실행하기
SbbApplication 실행
Hello World (하 얼마만에 헬로월드냐 ㅠㅠ)
1-04 스프링 부트 도구 설치하기
라이브러리 : 웹 프로그램 개발을 도와주는 스프링 부트의 도구. // 개발시 자주 사용하는 코드를 모아 둔 것
Spring Boot Devtools 설치하기
리턴 문자값을 변경하고 URL 붙어도 Hello World로 나온다. 그 이유는 프로그램이 변경되어도, 별도의 과정 없이는 로컬 서버가 변경된 클래스를 즉시 반영하지 않기 때문이다.
프로그램을 간단히 수정하더라도, 변경된 사항을 확인하기 위해서는 매번 서버를 재시작 해야 하므로, 개발 과정이 꽤 번거롭다.
Devtools : 서버를 매번 재시작하지 않고 수정한 내용이 반영된다.
Devtools 설치 방법
build.gradle
developmentOnly : 개발 환경에만 적용. 운영 환경에 배포 되는 jar, war 파일에는 이 라이브러리가 포함되지 않는다.
build.gradle 파일에 작성한 내용 적용하려면 gradle 재 빌드 또는 갱신 해준다.
[참고] 인텔리제이에서는 자동빌드 옵션 안쓰고 하기로 함.
그래도 다른분들이 정리한 내용 아래 적어둔다.
https://wikidocs.net/blog/@ilco/391/
[점프투스프링부트3] 인텔리제이에서 devtools 자동빌드 적용하기
[점프투스프링부트3] 인텔리제이에서 devtools 자동빌드 적용하기
wikidocs.net
롬복 설치하기
롬복(Lombok) 라이브러리 : 소스 코드 작성할 때, 자바 클래스에 애너테이션을 사용하여 자주 쓰는 Getter, Setter, 생성자 등을 자동으로 만들어주는 도구
- Getter, Setter : 자바 클래스의 속성값을 읽거나 저장할 때 사용
SBB 게시판 만들면서, 게시물과 관련된 데이터를 처리하기 위해 엔티티 클래스나 DTO 클래스 등을 사용해야하는데, 그러기 위해서는 먼저 이 클래스들의 속성값을 읽고 저장하는 Getter, Setter 메서즈를 만들어야 한다.
- 엔티티 클래스 : 데이터베이스에 데이터를 저장하고 조회하기 위한 클래스
- DTO 클래스 : 데이터 베이스로 조회한 데이터들을 관리하기 위한 클래스
롬복 설치 방법
build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
compileOnly 'org.projectlombok:lombok' //롬복
annotationProcessor 'org.projectlombok:lombok' // 롬복
}
위 추가 후 Refresh Gradle Project 진행. 라이브러리 다운 완료.
> Task :prepareKotlinBuildScriptModel UP-TO-DATE
Download https://repo.maven.apache.org/maven2/org/projectlombok/lombok/1.18.36/lombok-1.18.36.pom, took 109 ms
Download https://repo.maven.apache.org/maven2/org/projectlombok/lombok/1.18.36/lombok-1.18.36.jar, took 214 ms
BUILD SUCCESSFUL in 1s
롬복(Lombok)으로 Getter, Setter 메서드 만들기
HelloLombok.java
package com.ksko.sbb;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class HelloLombok {
private String hello;
private int lombok;
public static void main(String[] args) {
HelloLombok helloLombok = new HelloLombok();
helloLombok.setHello("헬로");
helloLombok.setLombok(5);
System.out.println(helloLombok.getHello());
System.out.println(helloLombok.getLombok());
}
}
실행결과
[참고] 인텔리제이 한글 깨짐 현상 인코딩 (참고 : https://nsmchan.tistory.com/17)
vm 설정
인텔리제이 에서 쉬프트 2번 클릭 --> 검색창에 vm 입력 --> 사용자 지정 VM 옵션 편집 클릭
-Dfile.encoding=UTF-8
-Dconsole.encoding=UTF-8
어? 이거 이렇게 되어있음..
인텔리제이 재기동 해도 마찬가지임
근데.. 일반 컨트롤러로 하면 한글안깨지는데 메인메서드 를 따로 해서 실행하면 한글 깨짐 왜지?
chatGPT 통한 해결
B. Windows 기본 콘솔 설정 변경
Windows에서는 기본 콘솔 출력이 깨질 수 있으므로 다음 단계를 통해 변경합니다.
- IntelliJ 터미널에서 코드 페이지 변경
- IntelliJ 터미널 또는 명령 프롬프트에서 다음 명령을 실행:
shell코드 복사chcp 65001
- IntelliJ 터미널 또는 명령 프롬프트에서 다음 명령을 실행:
- PrintStream으로 강제 설정 후 출력 확인 코드를 약간 수정하여, 콘솔 출력 스트림을 UTF-8로 설정한 후 직접 출력해보세요:
-
java
package com.ksko.sbb;
import lombok.Getter;
import lombok.Setter;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
@Getter
@Setter
public class HelloLombok {
private String hello;
private int lombok;
public static void main(String[] args) {
System.out.println("Default Charset: " + java.nio.charset.Charset.defaultCharset());
System.out.println("file.encoding: " + System.getProperty("file.encoding"));
System.out.println("Default Locale: " + java.util.Locale.getDefault());
System.setOut(new PrintStream(System.out, true, StandardCharsets.UTF_8)); // 콘솔 출력 스트림을 UTF-8로 설정후 하니 나옴 ㅠㅠ
HelloLombok helloLombok = new HelloLombok();
helloLombok.setHello("헬로");
helloLombok.setLombok(5);
System.out.println(helloLombok.getHello());
System.out.println(helloLombok.getLombok());
}
}
롬복으로 생성자 만들기.
package com.ksko.sbb;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
@Getter
//@Setter
@RequiredArgsConstructor
public class HelloLombok {
//1.롬복으로 getter, setter 만들기
/*
private String hello;
private int lombok;
*/
private final String hello;
private final int lombok;
public static void main(String[] args) {
//한글 인코딩 깨짐 현상 확인 및 수정
System.out.println("Default Charset: " + java.nio.charset.Charset.defaultCharset());
System.out.println("file.encoding: " + System.getProperty("file.encoding"));
System.out.println("Default Locale: " + java.util.Locale.getDefault());
System.setOut(new PrintStream(System.out, true, StandardCharsets.UTF_8));
//1.롬복으로 getter, setter 만들기
/*
HelloLombok helloLombok = new HelloLombok();
helloLombok.setHello("헬로");
helloLombok.setLombok(5);
System.out.println(helloLombok.getHello());
System.out.println(helloLombok.getLombok());
*/
HelloLombok helloLombok = new HelloLombok("헬로", 5);
System.out.println(helloLombok.getHello());
System.out.println(helloLombok.getLombok());
}
}
hello, lombok 속성에 final 추가하고 @RequredArgsConstructor 애너테이션을 적용하면, 해당 속성(hello, lombok)을 필요로 하는 생성자가 롬복에 의해 자동으로 생성된다.
- final : 뒤에 따라오는 자료형과 변수 등을 변경할 수 없게 만드는 키워드. 만약 클래스 속성을 정의한 코드에 final이 없다면 생성자에 포함되지 않는다. 또한 final을 적용하면 속성값을 변경할 수 없기 때문에, @Setter 는 의미가 없고, Setter 메서드 또한 사용할 수 없다.
2장 스프링 부트의 기본 기능 익히기
스프링 부트 개발 하는 데 필요한 기본 내용 다룸!
SBB 게시판은 빌딩 --> 기본 기능은 기초 공사!
목표
- 컨트롤러를 이용해 URL과 매핑되는 메서드를 관리한다.
- JPA를 이용해 데이터베이스를 제어한다.
- HTML, CSS 등을 활용하여 웹 프로그램을 꾸민다.
2-01 스프링 부트 프로젝트의 구조 이해하기
프로젝트 전체 구조
src/main/java 디렉터리 살피기
자바 파일을 저장하는 공간
com.ksko.sbb 패키지
컨트롤러, 폼과 DTO, 데이터베이스 처리를 위한 엔티티, 서비스 등의 자바파일 위치
- 컨트롤러 : URL 요청을 처리하고 폼은 사용자의 입력을 검증한다.
- DTO, 엔티티, 서비스 : 데이터베이스를 처리하기 위해 필요한 파일 .
SbbApplication.java 파일
모든 프로그램에는 프로그램의 시작을 담당하는 파일이 있다. 스프링 부트로 만든 프로그램(=스프링 부트 애플리케이션)에도 시작을 담당하는 파일이 있는데. 그 파일이 바로 "프로젝트명 + Application.java" 파일이다. 스프링 부트 프로젝트를 생성할 때 프로젝트 명으로 'sbb' 라는 이름을 입력하면, 다음과 같이 SbbApplication.java 파일이 자동으로 생성된다.
package com.ksko.sbb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SbbApplication {
public static void main(String[] args) {
SpringApplication.run(SbbApplication.class, args);
}
}
@SpringBootApplication 애너테이션을 통해 스프링 부트 애플리케이션을 시작할 수 있다.
src/main/resources 디렉터리 살펴보기
자바파일을 제외한 HTML, CSS, 자바스크립트, 환경 파일(프로젝트 설정 정보를 저장하는 파일) 등을 저장하는 공간.
- HTML : 웹 페이지의 기본 구조를 만들 수 있는 마크업 언더
- CSS : 웹 페이지에 옷을 입히는 스타일 시트 언어
- 자바스크립트 : 웹 페이지의 상호 작용과 동작 등을 할 수 있게 만드는 프로그래밍 언어
templates 디렉터리
src/main/resources 디렉토리 하위 디렉터리인 templates 에는 템플릿 파일을 저장
템플릿 파일 : 자바 코드를 삽입할 수 있는 HTML 형식의 파일.
스프링 부트에서 생성한 자바 객체를 HTML 형태롤 출력할 수 있음.
static 디렉터리
스타일시트(css 파일), 자바스크립트(js 파일) 그리고 이미지 파일(jpg파일, png파일 등) 등을 저장한다.
application.properties 파일
sbb 프로젝트의 환경 변수, 데이터베이스 등의 설정을 파일에 저장.
src/test/java 디렉터리 살펴보기
sbb 프로젝트에서 작성한 파일을 테스트하는 코드를 저장하는 공간
JUnit 과 스프링 부트의 테스트 도구를 사용하여 서버를 실행하지 않은 상태에서 src/main/java 디렉터리에 작성한 코드를 테스트 할 수 있다.
- JUnit : 테스트 코드를 작성, 작성한 테스트 코드를 실행할 때 사용하는 자바의 테스트 프레임워크
build.gradle 파일 살펴보기
그레이들(Gradle)이 사용하는 환경 파일. 그루비(Groovy) 기반으로 한 빌드도구.
- 그루비 : 그레이들 빌드 스크립트를 작성하는데 사용하는 스크립트 언어
- 빌드 도구 : 소스 코드를 컴파일 하고 필요한 라이브러리를 내려받을 때 사용한다. sbb 프로젝트 완성시 단 한개의 jar 파일로 패키징하여 서버에 배포할 수 있는데 이떄에도 빌드 도구를 사용
2-02 간단한 웹 프로그램 만들기
웹 브라우저에서 http://localhost:8080/sbb 페이지를 요청했을 때 '안녕하세요 sbb에 오신 것을 환영합니다.'라는 문자열을 출력하도록 만들어 보자.
URL 매핑과 컨트롤러 이해하기
로컬 서버 구동 후 http://localhost:8080/sbb 페이지 요청하자
status=404 는 HTTP 오류 코드 중 하나로, 브라우저가 요청한 페이지를 찾을 수 없다. 는 의미
즉, 스프링 부트 서버가 http://localhost:8080/sbb 라는 요청을 해석할 수 없기 때문에 이와 같은 오류가 발생한 것이다.
(위 URL로 요청 --> 스프링부트 서버에서는 404오류 (스프링부트 로컬 서버에는 그런 URL은 없던데?)
이 오류를 해결하려면? --> /sbb URL에 대한 매핑을 추가하면 해결할 수 있음.
- URL 매핑 : URL과 컨트롤러의 메서드를 일대일로 연결하는 것을 말한다.
컨트롤러 만들어서 URL 매핑하기
웹 브라우저와 같은 클라이언트의 요청이 발생하면 서버 역할을 하는 스프링 부트가 응답해야 한다. 그러기 위해서, URL이 스프링 부트에 매핑되어 있어야 하고, 이를 위해서는 먼저 컨트롤러를 만들어야 한다.
1. MainController.java
package com.ksko.sbb;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
@GetMapping("/sbb")
public void index() {
System.out.println("index");
}
}
- MainController 클래스에 @Controller 애너테이션을 적용하면. MainController 클래스는 스프링 부트의 컨트롤러가 된다.
- index 메서드에 @GetMapping 애너테이션은 요청된 URL (/sbb)과의 매핑을 담당한다. (브라우저가 URL을 요청하면 스프링부트는 요청하는 페이지와 매핑되는 메서드를 찾아 실행한다.)
실행결과
이번에는 500 오류 발생.
http://localhost:8080/sbb 요청 --> MainController 클래스의 index 메서드가 호출되긴 했지만, 오류 발생
원래 URL과 매핑된 메서드는 결과값을 리턴해야 하는데 아무 값도 리턴하지 않아. 이런 오류가 발생한 것.
즉, 오류를 해결하려면 클라이언트(브라우저)로 응답을 리턴해야 한다.
- 콘솔 로그를 보면 index 메서드에서 실행한 System.out.println("index");가 실행되어 ‘index’라는 문자열이 출력된 것을 확인할 수 있다. 따라서 index 메서드가 호출되었음을 알 수 있다.
수정 해보자
package com.ksko.sbb;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MainController {
@GetMapping("/sbb")
@ResponseBody
public String index() {
return "index";
}
}
응답으로 "index" 문자열을 브라우저에 출력하기 위해
1. index 메서드의 리턴 자료형을 String으로 변경 하고 문자열 'index'를 리턴함
- @ResponseBody 애너테이션 : URL 요청에 대한 응답으로 문자열을 리턴 하라
- 만약 @ResponseBody 애너테이션을 생략한다면 스프링 부트는 'index' 라는 문자열을 리턴하는게 아니라, index 라는 이름의 템플릿 파일을 찾게 된다.
다시 서버 재기동 하고 실행하면 index가 잘 나온다.
문자열 index 대신 '안녕하세요 sbb에 오신 것을 환영합니다.'를 출력해 보자.
잘 되었다.
여기까지 공부한 것을 github 에 올려보자.
https://github.com/ksko1/sbb_study
GitHub - ksko1/sbb_study
Contribute to ksko1/sbb_study development by creating an account on GitHub.
github.com