1. 프로젝트 생성
2. 메이븐 Maven
3. 그레이들 Gradle
4. MVC 패턴 간략하게 알아보기
5. 웹서버 port 번호 변경하기
1. GET / DELETE API 만들기
2. POST / PUT API 만들기
3. ResponseEntity 활용
4. Swagger : REST API 명세를 문서화 해주는 도구
5. Logback : 로깅 라이브러리
- 프로젝트 생성
- 메이븐 Maven
- 그레이들 Gradle
- MVC 패턴 간략하게 알아보기
- 웹서버 port 번호 변경하기
spring initializr
인텔리제이 IDEA 얼티밋
Artifact
packaging
jar
war
pom.xml
빌드 관리 도구
maven
프로젝트 관리
빌드 및 패키징
테스트
배포
메이븐 생명주기
기본 생명주기
클린 생명주기
사이트 생명주기
gradle
컨트롤러 로직
was port 변경
스프링 부트 애플리케이션을
단계별로 개발하는 과정에서
어떤 개발 지식을 습득해야 하는지 살펴본다.
공식 사이트에서 프로젝트 정보를 설정한 후 다운 받아서 사용할 수 있게 되어있다.
하단의 GENERATE
버튼 클릭 시
설정 완료 된 프로젝트의 압축 파일을 다운 받을 수 있고,
EXPLORE
버튼 클릭 시
설정 된 프로젝트를 다운받기 전에 미리 살펴볼 수 있다.
SHARE...
버튼 클릭 시...
내가 설정한 프로젝트 정보를
다른 사람과 공유할 수 있게 링크를 만들어준다.
인텔리제이 IDEA 얼티밋
버전은
Spring Initializr
기능을 내장
하고 있다.
이 기능을 이용하면
외부에서 프로젝트를 생성할 필요 없이
인텔리제이 IDEA 에서 곧바로 스프링 프로젝트를 생성할 수 있다.
🔻 인텔리제이 IDEA 얼티밋 버전 실행 초기 화면
프로젝트
- 새 프로젝트
- Spring Initializr
진입
JVM 상에서 동작하는 언어 선택
빌드 툴 선택
이 프로젝트를 정의하는 고유 식별자.
세부 프로젝트를 식별하는 정보.
의존성 관리 및 라이브러리 관리에 사용된다.
Group과 Artifact를 설정하면 자동으로 입력된다.
애플리케이션을 쉽게 배포하고 동작하게 할 파일들의 패키징 옵션.
Jar
와 War
가 있다.
✏️ Jar : Java Archive
- 자바 클래스 , 리소스 , 라이브러리를 패키징 할 때 사용
- 자바 애플리케이션을 실행하기 위해 필요한 모든 클래스 및 리소스를 하나의 압축 파일로 만든 형태이다.
- java 애플리케이션의 실행 가능한 형태이다.
- 주로 독립 실행형 애플리케이션이나, 라이브러리로 사용된다.
- 자바 가상 머신 JVM에서 실행 될 수 있다.
✏️ War : Web Application Archive
- 자바 Web 애플리케이션을 패키징하는데 사용한다.
- 웹 애플리케이션의 구조, 웹페이지, 서블릿, JSP 등을 하나의 압축 파일로 만든 형태이다.
- 웹 애플리케이션의 구조와 배치 정보를 포함하여 서블릿 컨테이너(≒ 톰캣)에 배포 및 관리된다.
- Java EE (Enterprise Edition) 또는 웹 컨테이너에 배포되어 실행된다.
- 웹 애플리케이션은 war 파일을 통해 웹 컨테이너에 배포되고,
컨테이너는 war 파일의 내용을 로드하여 애플리케이션을 실행한다.
- 웹 애플리케이션 서버에 배포되어 다중 사용자 환경에서 실행된다.
jar war 찾아보다 헷갈려서 정래해보는
웹 컨테이너와 서블릿 컨테이너✏️ 웹 컨테이너 웹 컨테이너는 웹 애플리케이션의 실행 환경을 제공하는 소프트웨어이다. 웹 서버, 웹 애플리케이션의 배포, 관리, 보안 등의 기능도 포함될 수 있다. ✏️ 서블릿 컨테이너 서블릿 컨테이너는 웹 컨테이너의 일부로서 서블릿 기술을 처리하는 데 특화되어 있다. 서블릿의 생명주기, 멀티스레딩, 요청 및 응답 처리, 세션 관리 등을 담당. 👉 웹 컨테이너는 서블릿 컨테이너와 함께 동작할 수도 있지만, 서블릿 컨테이너를 포함하지 않을 수도 있다. 다른 기술을 지원하거나 웹 서버와 통합된 형태로 제공될 수도 있다. - 웹 컨테이너 소프트웨어 > 서블릿 컨테이너 포함 👉 Apache Tomcat , Jetty , Oracle WebLogic Server , GlassFish 등등 - 웹 컨테이너 소프트웨어 > 서블릿 컨테이너 미포함 👉 NGINX , Microsoft IIS , Caddy 등등
🔻 다음 화면에서 스프링 버전 선택(필수)와 의존성 도구들을 추가(선택)할 수 있다.
_____________________🐢🎈____________________
자바 기반의 프로젝트를 빌드하고 관리하는 데 사용하는 도구.
초창기 자바 프로젝트의 대표적 관리 도구였던 Ant를 대체하기 위해 개발되었다.
JVM 이나 WAS가 프로젝트를 인식하고 실행할 수 있게
우리가 작성한 소스 코드와 프로젝트에 사용된 파일들(xml , jar, properties , yml)을 빌드하는 도구이다.
메이븐의 기능을 사용하기 위해 작성하는 파일.
프로젝트, 의존성 라이브러리, 빌드 등의 정보 및
해당 프로젝트를 관리하는 데 필요한 내용이 기술되어 있다.
메이븐의 가장 큰 특징은
pom.xml
파일에 필요한 라이브러리를 추가하면
해당 라이브러리에 필요한 라이브러리까지 함께 내려받아 관리한다.
프로젝트 관리
프로젝트 버전과 아티팩트를 관리한다.
빌드 및 패키징
의존성을 관리하고 설정된 패키지 형식으로 빌드를 수행한다.
테스트
빌드를 수행하기 전에,
단위 테스트를 통해 작성된 애플리케이션 코드의 정상 동작 여부를 확인한다.
배포
빌드가 완료된 패키지를 원격 저장소에 배포한다.
메이븐의 기능은 생명주기 순서에 따라 관리되고 동작한다.
생명주기 단계는 크게 3단계로 구분할 수 있는데,
각 단계는 메이븐에서 제공하는 플러그인이 설정된 목표를 수행하는 방식으로 동작하며,
각 단계는 순차적으로 실행된다.
clean
이전 빌드가 생성한 모든 파일을 제거한다.
validate
프로젝트를 빌드하는 데 필요한 모든 정보를 사용할 수 있는지 검토
complie
프로젝트 소스 코드 컴파일
test
단위 테스트 프레임워크를 사용해 테스트 실행
package
컴파일한 코드를 가져와서 jar 등의 형식으로 패키징을 수행
verify
패키지가 유효하며 일정 기준을 충족하는지 확인
install
프로젝트를 사용하는 데 필요한 패키지를 로컬 저장소에 설치
deploy
프로젝트를 통합 또는 릴리스 환경에서 , 다른 곳에 공유하기 위해 원격 저장소에 패키지 복사
site
메이븐의 설정 파일 정보를 기반으로 프로젝트의 문서 사이트 생성
site-deploy
생성된 사이트 문서를 웹 서버에 배포
_____________________🐢🎈____________________
보고 배운 사이트 1 : dev-coco.tistory
보고 배운 사이트 2 : techblog.woowahan
보고 배운 사이트 3 : charlezz
빌트, 프로젝트 구성/관리, 테스트, 배포 도구
안드로이드 앱의 공식 빌드 시스템
빌드 속도가 Maven에 비해 10~100배 가량 더 빠름
Java, C, C++, Python 등을 지원
빌드 툴인 ant builder와 groovy(jvm에서 실행되는 스크립트 언어) 스크립트 기반으로 만들어져 기존 ant의 역할과 배포 스크립트 기능을 모두 사용
Domain Specific Language
특정 분야에 최적화 된 프로그래밍 언어를 뜻한다.
선언적 코드 형식을 따른다.
kotlin dsl 파일은 그레이들 5.0버전부터 지원하기 시작했다.
우선 이 두 파일은 확장자가 다르다.
kotlin dsl 파일은 groovy dsl 확장자 끝에 .kts
가 붙는다.
kotlin dsl 파일에서만 코드 자동 완성 기능 존재
kotlin dsl 파일에서만 오류 코드 강조 기능 존재
kotlin dsl 파일에서만 컴파일 타임에 에러 확인 가능
클린 빌드 시 kotlin dsl이 groovy dsl보다 느리다.
kotlin dsl은 java 8 이상
에서만 동작
_____________________🐢🎈____________________
레이아웃과 화면을 처리하며,
HTML , JSP 파일을 뷰라고 구분하여 사용한다.
컨트롤러에 포함된 로직에서는
애플리케이션의 사용자 또는 클라이언트가 입력한 값에 대한 응답을 수행한다.
특별한 경우를 제외한 모든 요청은 컨트롤러를 통해 진행되어야 한다.
컨트롤러에서 응답을 수행하는 과정에서
데이터를 다루거나, 별도의 로직을 처리해야 하는 경우
일반적으로 서비스 또는 데이터 액세스 레이어까지 요청을 전달하게 된다.
이 때 서비스 , 데이터에 접근하는 부분들은 모델로 구분한다.
_____________________🐢🎈____________________
스프링 부트에서 기본으로 사용하는 포트 번호는 8080이다.
이 포트번호를 변경하고 싶다면 application.properties 파일을 통해 변경할 수 있다.
🔻파일 경로
src/main/resource/application.properties
포트번호 설정
server.port = 9090
_____________________🐢🎈____________________
- GET / DELETE API 만들기
- POST / PUT API 만들기
- Swagger : REST API 명세를 문서화 해주는 도구
- Logback : 로깅 라이브러리
HTTP 메서드
GET
DELETE
POST
PUT
Swagger
문서화
Logback
HTTP 메서드에 해당하는 API를 간단하게 구현해본다.
아직 DB를 사용하지 않기 때문에 정확한 기능 구현은 어렵지만,
외부의 요청을 받아 응답하는 기능을 구현하여
컨트롤러가 어떻게 구성되는지 알아본다.
GET API는
웹 애플리케이션 서버에서
값을 가져올 때 사용하는 API이다.
DELETE API는
웹 애플리케이션 서버를 거쳐
데이터베이스 등의 저장소에 있는
리소스를 삭제할 때 사용하는 API이다.
DELETE API는
컨트롤러를 통해 값을 받는 단계에서는
간단한 값만을 다루기 때문에,
GET 메서드와 같이 URI에 값을 넣어 요청을 받는 형식으로 구현한다.
그렇기 때문에 GET 과 DELETE를 하나의 주제로 다뤄본다!
이 어노테이션은 별다른 설정 없이 선언하면 HTTP의 모든 요청을 받는다.
특정 HTTP 메서드 요청만 받기위해서는 별도의 설정을 해주어야 한다.
@RestController
public class RequestController {
// url = http://localhost:9090/hello
// HTTP method = GET
@RequestMapping(value = "/hello" , method = RequestMethod.GET)
public String getHello() {
return "Hello World";
}
}
@RestController
public class RequestController {
// url = http://localhost:9090/hello
// HTTP method = DELETE
@RequestMapping(value = "/hello" , method = RequestMethod.DELETE)
public String deleteHello() {
return "Bye Bye";
}
}
스프링 4.3 버전 이후로는
특별한 경우가 아니라면,
@RequestMapping 어노테이션은 더 이상 사용되지 않는다.
이제는 각 HTTP 메서드에 해당하는 어노테이션을 사용한다.
@GetMapping
@DeleteMapping
@PostMapping
@PutMapping
별도의 매개변수 없이 GET API를 구현하는 경우 아래와 같이 코드를 작성할 수 있다.
@RestController
public class RequestController {
// url = http://localhost:9090/name
@GetMapping(value = "/name")
public String getName() {
return "zhyun";
}
}
매개변수가 없는 메서드는 거의 쓰이지 않는다.
웹 통신의 기본 목적은 데이터를 주고받는 것이기 때문이다!
매개변수를 받을 때 자주 사용되는 방법 중 하나는 URL 자체에 값을 담아 요청하는 것이다.
URL에 값(변수)를 담는것이기 때문에
어노테이션 이름이 Path Variable !
@RestController
public class GetController {
// url = http://localhost:9090/var1/String-값
@GetMapping(value = "/var1/{yourName}")
public String getHello(@PathVariable String yourName) {
return "Hello " + yourName + " !";
}
}
@RestController
public class GetController {
// url = http://localhost:9090/var1/String-값
@DeleteMapping(value = "/var1/{yourName}")
public String deleteHello(@PathVariable String yourName) {
return "Bye " + yourName + " !";
}
}
부득이하게 매개변수의 이름과 url에 지정한 변수 이름이 다른 경우
아래와 같이 지정해줄 수도 있다.
@RestController
public class GetController {
// url = http://localhost:9090/var1/String-값
@GetMapping(value = "/var1/{yourName}")
public String getHello(@PathVariable("yourName") String welcome) {
return "Hello " + welcome + " !";
}
}
여기서
@PathVariable("yourName")
은
@PathVariable(value = "yourName")
와 같다.
PathVariable과 같이 URL 경로에 값을 담아 요청을 보내는 방법 외에도
쿼리 스트링 형식으로 값을 전달할 수도 있다.
쿼리 스트링 , 쿼리 파라미터, 두개의 단어 모두 같은 의미이다.
왜냐하면 URL은 문자열이기 때문이다.
쿼리 스트링은 URI에서 ?
를 기준으로
우측에 키1=값1&키2=값2
형태로 구성된 요청을 전송하는 방법이다.
@RestController
public class GetController {
// url = http://localhost:9090/request1?name=value&email=test@gmail.com
@GetMapping(value = "/request1")
public String getRequestParam1(
@RequestParam String name,
@RequestParam String email
) {
return name + email;
}
}
Data Transfer Object의 약자로,
다른 레이어 간의 데이터 교환에 활용된다.
간략히 설명하면
각 클래스 및 인터페이스를 호출하면서 전달하는
매개변수로 사용되는 데이터 객체이다.
데이터를 교환하는 용도로만 사용하는 객체이기 때문에
DTO는 별도의 로직이 포함되지 않는다.
✏️ VO : Value Object
데이터 그 자체로 의미가 있는 객체.
읽기 전용으로 설계된다.
DTO 클래스에는 전달하고자 하는 필드 객체를 선언하고
Getter / Setter 메서드를 구현한다.
DTO 클래스에 선언된 필드는 컨트롤러의 메서드에서 쿼리 파라미터의 키와 매핑된다.
DTO 클래스
@ToString
@Getter
@Setter
public class MyDto {
private String name;
private String email;
}
Controller
@RestController
public class GetController {
// url = http://localhost:9090/request2?name=value&email=test@gmail.com
@GetMapping(value = "/request2")
public String getRequest2(MyDto dto) {
return dto.toString();
}
}
_____________________🐢🎈____________________
post api는
웹 애플리케이션을 통해
데이터베이스 등의 저장소에 리소스를 저장할 때 사용되는 api이다.
앞서 살펴본 GET / DELETE API 와는 다르게,
저장하고자 하는 리소스나 값을 HTTP 바디
에 담아 서버에 전달한다.
이때 사용하는 어노테이션은 @RequestBody
이다.
put api는
데이터베이스 등의 저장소에 리소스를 업데이트 할 때 사용하지만,
컨트롤러에서 값을 받아오는 형태는 PUT과 같다.
그렇기 때문에 같은 주제로 묶어놓았다.
일반적으로 POST로 값을 주고 받을 때는 JSON 형식으로 값을 주고받는다.
@RestController
public class PostController {
// url = http://localhost:9090/hello
@PostMapping(value = "/hello")
public String postHello(@RequestBody MyDto dto) {
return dto.toString();
}
}
dto 데이터 클래스를 사용하면,
요청 메세지의 키와 매핑해 값을 담아온다.
_____________________🐢🎈____________________
스프링 프레임워크에는 HttpEntity라는 클래스가 있다.
HttpEntity는 헤더와 바디로 구성된
HTTP 요청과 응답을 구성하는 역할을 수행한다.
RequestEntity
와 ResponseEntity
는
HttpEntity를 상속받아 구현한 클래스이다.
이 중 ResponseEntity
는
서버에 들어온 요청에 대해 응답 데이터를 구성해서 전달할 수 있게 해준다.
public class ResponseEntity<T> extends HttpEntity<T> {
private final Object status;
..생략..
}
이 ResponseEntity 클래스를 활용하면
응답 코드 변경은 물론,
Header와 Body를 더욱 쉽게 구성할 수 있다.
@RestController
public class PostController {
// url = http://localhost:9090/hello
@PostMapping(value = "/hello")
public ResponseEntity<MyDto> postHello(@RequestBody MyDto dto) {
return ResponseEntity
.status(HttpStatus.ACCEPTED)
.body(dto);
}
}
_____________________🐢🎈____________________
api를 개발하면 명세를 관리해야 한다.
명세란 해당 api가 어떤 로직을 수행하는지 설명하고
이 로직을 수행하기 위해 어떤 값을 요청하며,
이에 따른 응답값으로는 무엇을 받을 수 있는지를 정리한 자료이다.
api는 개발 과정에서 계속 변경되므로 작성한 명세 문서도 주기적인 업데이트가 필요하다.
또한 명세 작업은 번거롭고 오랜 시간이 걸리는 문제가 있는데,
swagger는 이러한 문제를 해결하기 위해 등장한 라이브러리이다.
swagger 라이브러리를 사용하기 위한 설정과 관련된 클래스를 생성한다.
이러한 클래스는 config
라는 패키지를 생성한 후에 그 안에 생성하는 것이 좋다.
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
@Bean
public Docket api() {
return new Docket(DoucmentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("your.packages.name"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot Open API Test with Swagger")
.description("설명 부분")
.version("1.0.0")
.build();
}
}
.apis(RequestHandlerSelectors.basePackage("your.packages.name"))
Swagger 에서 스캔할 패키지 범위 지정.
지정된 패키지의 하위에 있는 모든 패키지와 클래스를 스캔해서 문서로 작성해줌
http://localhost:8080/swagger-ui.html
@ApiOperation(value = "GET 메서드 예제", notes = "@RequestParam을 활용한 GET Method")
@GetMapping("/request1")
public String getRequestParam1(
@ApiParam(value = "이름", required = true) @RequestParam String name,
@ApiParam(value = "이멜", required = true) @RequestParam String email) {
return name + email;
}
@ApiOperation
대상 API의 설명을 작성하기 위한 어노테이션
@ApiParam
매개변수에 대한 설명 및 설정을 위한 어노테이션.
메서드의 매개변수 뿐 아니라,
DTO 객체를 매개변수로 사용할 경우
DTO 클래스 내의 매개변수에도 정의할 수 있다.
_____________________🐢🎈____________________
로깅이란 ,
애플리케이션이 동작하는 동안
시스템의 상태나 동작 정보를
시간순으로 기록하는 것을 의미한다.
자바 진영에서 가장 많이 사용되는 로깅 프레임워크는 Logback이다.
Logback이란
log4j 이후에 출시된 로깅 프레임워크로,
slf4j를 기반으로 구현되었으며
spring-boot-stater-web 라이브러리 내부에 내장되어 있어,
별도의 의존성을 추가하지 않아도 사용할 수 있다.
ERROR
로직 수행 중에
시스템에 심각한 문제가 발생해서
애플리케이션의 작동이 불가능한 경우를 의미
WARN
시스템 에러의 원인이 될 수 있는
경고 레벨을 의미
INFO
애플리케이션의 상태변경과 같은
정보 전달을 위해 사용됨
DEBUG
애플리케이션의
디버깅을 위한 메시지를 표시하는 레벨을 의미
TRACE
DEBUG 레벨보다
더 상세한 메시지를 표현하기 위한 레벨을 의미
로그백 설정 파일은 리소스 폴더 안에 xml 확장자로 생성한다.
파일 이름은 아무거나 하면 안되고,
자바 또는 스프링 프로젝트에서는 logback.xml
스프링 부트 프로젝트에서는 logback-spring.xml
으로 작성해주어야 인식이 가능해진다.
설정 파일 작성 내용은
5가지 영역으로 구분해서 작성할 수 있다.
Property
Appender
Encoder
Pattern
Root
이 중 가장 중요한 Appender 영역과 Root 영역에 대해서 좀 더 자세히 알아본다!
로그의 형태를 설정하고,
어떤 방법으로 출력할지를 설정하는 곳이다.
Appender 자체는 하나의 인터페이스를 의미하며,
하위에 여러 구현체가 존재한다.
Appender 의 대표적인 구현체는 다음과 같다.
ConsoleAppender
: 콘솔에 로그 출력
FileAppender
: 파일에 로그 저장
RollingFileAppender
: 여러 개의 파일을 순회하면서 로그 저장
SMTPAppender
: 메일로 로그 전송
DBAppender
: 데이터베이스에 로그 저장
설정 파일에 정의된 Appender를 활용하려면
Root 영역에서 Appender를 참조해서 로깅 레벨을 설정한다.
만약 특정 패키지에 대해 다른 로깅 레벨을 설정하고 싶다면
root 대신 logger를 사용해 지정할 수 있다.
<root level="INFO">
<appender-ref ref = "console"/>
<appender-ref ref = "INFO_LOG"/>
</root>
<logger name="com.your.package.api.exception" level="DEBUG" additivity="false">
<appender-ref ref = "console"/>
<appender-ref ref = "INFO_LOG"/>
</logger>
여기서 additivity
속성은
앞에서 지정한 패키지 범위에 하위 패키지를 포함할지 여부를 작성한다.
기본값은 true이며, 이 경우 하위 패키지를 모두 포함한다.
_____________________🐢🎈____________________