🌟스프링 부트란?
✅스프링 프레임워크
- 자바에서 가장 많이 사용되는 프레임워크.
- 현재 우리나라의 '전자정부 표준 프레임워크'의 기반 기술로 채택.
- 애플리케이션 개발에 필요한 기반을 제공하여 개발자가 비지니스 로직 구현에만 집중할 수 있게끔 해준다.
1. 제어의 역전(IoC)
- 기존의 개발자가 객체를 직접 생성하고 관리하던 방식이 아닌, 사용할 객체를 직접 생성하지 않고 객체의 생명주기 관리를 스프링 컨테이너(IoC 컨테이너)에 위임하는 것.
- 객체의 관리를 컨테이너에 맡겨 제어권이 넘어간 것을 제어의 역전 이라고 하며, 이로 인해 DI 및 AOP가 가능해진다.
2. 의존성 주입(DI)
- 사용할 객체를 직접 생성하지 않고 외부 컨테이너가 생성한 객체를 주입받아 사용하는 방식.
- 예를 들어, 하나의 객체에서 사용할 기능 로직을 다른 클래스에 구현한 뒤 해당 클래스 객체를 주입 받아 사용하는 것을 말한다.
- 이러한 경우를 하나의 객체가 다른 객체에 의존하고 있다고 한다.
의존성 주입 방법 3가지
- 생성자를 통한 의존성 주입
- 필드 객체 선언을 통한 의존성 주입
- setter 메서드를 통한 의존성 주입
3. 관점 지향 프로그래밍(AOP)
- AOP는 OOP를 더욱 잘 사용하도록 돕기 위한 개념.
- AOP는 관점 지향 프로그래밍의 약어로써,
관점 이란 어떤 기능을 구현할 때 그 기능의 핵심 기능과 부가 기능으로 구분하여 각각을 하나의 관점으로 보는 것을 의미한다.
- 일반적으로 핵심 기능은 사용자 관점에서 필요한 기능이며, 부가 기능은 서버 개발자 관점에서 필요한 기능이다.
- AOP 방식으로 프로그래밍 하면, 공통되는 부가 기능을 별도로 구현함으로써 핵심 기능 구현 시 부가 기능을 반복하는 코드가 줄어들고, 한곳에 구현된 부가 기능 코드만 수정해도 적용되는 로직이 수정되기 때문에 유지보수가 편하다.
- 즉, 여러 비지니스 로직에서 반복되는 부가 기능을 하나의 공통 로직으로 처리하도록 모듈화하여 삽입해놓은 방식을 AOP라고 한다.
- SpringFramework에서는
프록시 패턴을 이용하여 AOP 기능을 제공한다.
✅스프링 프레임워크 VS 스프링 부트
- 스프링 부트를 이용하면 단독으로 실행 가능한 사용 수준의 스프링 기반 애플리케이션을 손쉽게 만들 수 있다.
1. 의존성 관리
- 스프링 프레임워크에서는 개발에 필요한 각 모듈의 의존성을 직접 설정해야 했지만, 스프링 부트에서는
spring-boot-starter라는 의존성을 제공하며, 이를 통해 각 라이브러리의 기능과 관련해서 자주 사용되고 서로 호환되는 버전의 모듈 조합을 제공한다. 이를 통해 개발자는 라이브러리 호환 문제 해결이 가능하다.
spring-boot-starter
-
spring-boot-starter-web : 스프링 MVC를 사용하는 RESTful 애플리케이션 개발을 위한 의존성. 기본적으로 톰캣이 내장되어 있어 jar 형식으로 실행이 가능하다.
-
spring-boot-starter-test : JUnit,Hupiter,Mockito 등의 테스트용 라이브러리를 포함.
-
spring-boot-starter-jdbc : HikariCP 커넥션 풀을 활용한 JDBC 긴응을 제공.
-
spring-boot-starter-security : 스프링 시큐리티(인증, 인가 등) 기능을 제공.
-
spring-boot-starter-data-jpa : 하이버네이트를 활용한 spring data JPA를 제공.
-
spring-boot-starter-cache : 스프링 프레임워크의 캐시 기능을 지원.
🌟개발 환경 구성
- Windows 11 64bits
- 인텔리제이 Ultimate
- JDK 11(1.8 버전 이상)
- 스프링 부트 2.5.6 ~ 2.5.8
- MySQL DB
- Maven
🌟스프링 부트 - 애플리케이션 개발
✅프로젝트 생성
[File] → [Project...] → [Spring Initializr]
- Name : 프로젝트명 설정
- Location : 프로젝트 생성 위치 설정
- Language : JVM 상에서 동작하는 언어 선택.
- Type : 빌드 툴.
- Group : 고유한 식별자 정보인
그룹 설정.
- Artifact : 세부 프로젝트를 식별하는 정보.
- Pacakge name : Group과 Artifact 입력 시, 자동 입력.
- Java : 자바 버전 설정.
- Packaging : 애플리케이션을 쉽게 배포하고 동작하게 할 파일들의 패키징 옵션.
Jar 와 War
모두 자바 언어의 툴에서 사용하는 아카이브 파일. 애플리케이션의 배포와 동작을 위해 사용되는데, 두 형식의 차이점과 특징을 알아두면 좋다.
- JAR(Java Archive)
- .jar 확장자 파일에는 Class와 같은 Java 리소스와 속성 파일, 라이브러리 등이 포함되어 있다.
- 쉽게 자바 애플리케이션이 동작할 수 있도록 자바 프로젝트를 압축한 파일로 생각하면 된다.
- 실제 JAR 파일은 플랫폼에서 귀속되는 점만 제외하면 ZIP파일과 동일한 구조이다.
- JRE만 가지고도 실행이 가능하다.
- WAR(Web Application Archive)
- .war 확장자 파일은 servlet/jsp 컨테이너에 배치할 수 있는 웹 애플리케이션 압축 파일 포맷이다.
- Servlet Context 관련 파일들로 패키징 되어 있다.
- WAR는 웹 응용 프로그램을 위한 포맷이기 때문에 웹 관련 자원만 포함하고 있으며, 이를 사용하면 웹 애플리케이션을 쉽게 배포 및 테스트가 가능하다.
- 사전 정의된 구조를 사용하며, WAR 파일 실행을 위해서는 Tomcat, Weblogic, Websphere 등의 웹 서버 또는 WAS가 필요하다.
- WAR 파일도 Java의 JAR 옵션을 이용해 생성하는 JAR 파일의 일종으로, 웹 애플리케이션 전체를 패키징하기 위한 JAR 파일로 생각하면 된다.
✅pom.xml
- 메이븐의 기능을 사용하기 위해 작성하는 파일.
메이븐의 생명주기
- 메이븐의 기능은 생명주기 순서에 따라 관리되고 동작.
Default 생명주기
- validate : 프로젝트를 빌드하는데 필요한 모든 정보를 사용할 수 있는지 검토.
- compile : 프로젝트의 소스코드를 컴파일.
- test : 단위 테스트 프레임워크를 사용해 테스트 실행.
- package : 컴파일한 코드를 가져와서 JAR 등의 형식으로 패키징 수행.
- verify : 패키지가 유효하며 일정 기준을 충족하는지 확인.
- install : 프로젝트를 사용하는데 필요한 패키지를 로컬 저장소에 설치.
- deploy : 프로젝트를 통합 또는 릴리스 환경에서 다른 곳에 공유하기 위해 원격 저장소에 패키지를 복사.
Clean 생명주기
- clean : 이전 빌드가 생성한 모든 파일 제거.
Site 생명주기
- site : 메이븐의 설정 파일 정보를 기반으로 프로젝트의 문서 사이트 생성.
- site-deploy : 생성된 사이트 문서를 웹 서버에 배포.
🌟API를 작성하는 다양한 방법
-
@RestController()
-
@RequestMapping() : Controller 클래스 수준에서 공통으로 사용될 URL 설정.
-
스프링 4.3 버전 이후 @RequestMapping(value,method) 대신에 사용하는 어노테이션
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
✅GET API
@PathVariable 활용하여 URL 자체에 값을 요청하는 방식
- 만약, @GetMapping 어노테이션에 지정한 변수명과 메서드 매개변수 일므을 동일하게 설정하기 어려운 경우, @PathVariable 뒤에 괄호를 통해 @GetMapping 어노테이션에 사용된 변수명을 지정한다.
@GetMapping(value="/variable/{variable}")
public String getVariable(@PathVariable("variable") String var){
return var;
}
@RequestParam 어노테이션을 활용하여 쿼리 형식으로 값을 전달
- 쿼리 스트링에 키 값을 기준으로 메서드의 매개변수명을 매핑하여 가져온다.
- 일반적으로 값을 기입하지 않은 경우도 있기 때문에, 매개변수의 항목이 일정하지 않게 되므로 Map 객체로 받는것이 효율적이다.
@GetMapping(value="/request")
public String getRequestParam(@RequestParam Map<String,String> param){
StringBuilder sb = new StringBuilder();
param.setEntry().forEach(map -> {
sb.append(map.getKey() + " : " + map.getValue() + "\n");
});
return sb.toString();
}
URL 과 URI
- URL : 우리가 흔히 말하는 웹 주소를 의미.리소스가 어디에 있는지 알려주기 위한 경로.
- URI : 특정 리소스를 식별할 수 있는 식별자를 의미.
- 웹에서는 URL을 통해 리소스가 어느 서버에 위치해 있는지 알 수 있으며, 그 서버에 접근해서 리소스에 접근하기 위해서는 대부분 URI가 필요하다.
DTO 객체를 활용한 GET 메서드 구현
- DTO란?
Data Transfer Object의 약자로, 다른 레이어 간의 데이터 교환에 활용.
@GetMapping(value="/request")
public String getRequestParam(@RequestParam MemberDto dto){
return dto.toString();
}
✅POST API
- 웹 애플리케이션을 통해 데이터 베이스 등의 저장소에 리소스를 저장할 때 사용되는 API.
- 저장하고자 하는 리소스나 값을 HTTP 바디 안에 담아서 서버에 전달.
@RequestBody를 활용하여 POST 메서드 구현
- POST 요청에서는 리소스를 담기 위해 HTTP Body 안에 값을 넣어 전송.
- 일반적으로 JSON 형식으로 전송.
- @RequestBody는 HTTP의 Body 내용을 해당 어노테이션이 지정된 객체에 매핑해준다.
✅PUT API
- 웹 애플리케이션 서버를 통해 데이터베이스와 같은 저장소에 존재하는 리소스 값을 업데이트 하는데 사용.
- POST API와 거의 동일하며, HTTP Body를 활용해야 한다.
@ResponseEntity를 활용
- HttpEntity라는 내장 객체가 있는데, 이는 헤더와 바디로 구성된 HTTP 요청과 응답을 구성하는 역할을 한다.
- 일반적으로, @ResponseEntity를 사용하여 HttpEntity로 부터 HttpHeaders와 Body를 가지고 자체적으로 HttpStatus를 구현한다.
Ex)
@PutMapping("/member3")
public ResponseEntity<MemberDto> postMemberDto(@RequestBody MemberDto dto){
return ResponseEntity.status(HttpStatus.ACCEPTED).body(dto);
}
/**
응답 결과
202 응답 코드 발생.
*/
✅DELETE API
- 웹 애플리케이션 서버를 거쳐 데이터베이스 등의 저장소에 있는 리소스를 삭제할 때 사용.
- 클라이언트로부터 리소스를 식별할 수 있는 값을 받아 데이터베이스나 캐시에 있는 리소스를 조회하고 삭제하는 역할을 수행.
- GET 메서드와 같이 URI에 값을 넣어 요청을 받는 형식으로 구현.
🌟REST API 명세를 문서화 하는 방법 - Swagger
-
API를 개발하면 명세 관리가 필요하다.
-
명세 : 해당 API가 어떤 로직을 수행하는지 설명하고 이 로직을 수행하기 위해 어떤 값을 요청하며, 이에따른 응답값으로는 무엇을 받을 수 있는지를 정리한 자료를 의미한다.
-
즉, 협엽시에 협업자에게 API에 대한 로직을 추가해줌으로서 원활한 의사소통을 위해 필요하다.
-
API 개발 과정에서 명세 문서의 주기적인 업데이트가 필요하며, 이를 위해 사용하는 것이 'Swagger'이다.
✅Swagger 설정
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.springboot.api"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot Open API Test with Swagger")
.description("설명 부분")
.version("1.0.0")
.build();
}
}
✅Swagger 명세 추가
@ApiOperation(value="GET 메서드 예제", notes="@RequestParam을 활용한 GET Method")
@GetMapping("/request4")
public String getRequestParam4(
@ApiParam(value="이름",required = true) @RequestParam String name,
@ApiParam(value="이메일",required=true) @RequestParam String email,
@ApiParam(value="회사",required=true) @RequestParam String organization
){
return name + ", " + email + ", " + organization;
}
- @ApiOperation : 대상 API의 설명을 작성하기 위한 어노테이션.
- @ApiParam : 매개변수에 대한 설명 및 설정을 위한 어노테이션, 메서드 매개변수 뿐만 아니라 DTO 객체를 매개변수로 사용 시 DTO 클래스 내의 매개변수 정의도 가능하다.
trouble shooting
- 원인 : 구글링 결과, spring boot 2.7.14 버전과 Swagger 사이의 버전 오류로 인한 것이었다.
- 해결 방안
1. Spring boot 버전을 2.4.2로 낮춘다.
2. Swagger 설정한 Config 클래스에서 WebMvcConfigurationSupport를 구현 및 확장하는 방법이다.
→ Spring Boot가 제공하는 WebMVC 자동 설정을 사용하지 않기 때문에 일부 api 사용이 불가함.
3. springdoc-openapi-ui 적용(적용 방법 설명 링크 참고)
- 1번 해결방안으로 해결함.