Code.presso Java 웹 개발 트랙 체험단 활동 3주차 두번째 코스로 수강한 강의는 Spring Boot를 활용한 웹 개발 에 관한 내용이다.
지난 포스팅에 이어 이번에서는 본격적으로 Spring Boot 컨트롤러와 REST API, Spring Bean의 기초 개념과 의존성 주입에 대해 다뤄보도록 하겠다😊
강의 제목은 "Spring Boot 웹 개발 입문"으로, 자세한 정보는 👇🏻아래👇🏻 링크를 통해 확인할 수 있다.
✋🏻 포스팅 내 사용된 사진 파일들의 저작권은 모두 코드프레소에 있으며, 강의자료 공유 및 업로드는 불가능합니다.
건축을 할 때 설계도를 그려서 건물이 어떻게 지어질지 구상하는 것처럼, 소프트웨어도 실제 코드 개발 전에 최종 소프트웨어가 되어야 할 모습을 설계한다.
SW 아키텍처란, SW의 구조를 정의한 것으로 SW를 구성하는 주요 요소들과 요소들의 관계를 정의한 것이다.
패턴이란 특정 상황의 문제를 해결하기 위한 일반화된 솔루션으로, 우리의 목표인 웹 서비스 개발 또한 패턴을 가지고 있는데 이것이 바로 계층형 아키텍처 패턴이다!
웹 서비스 개발에 주로 사용되는 패턴으로, 서로 다른 역할을 하는 3~4개의 계층으로 구분된다.
이 계층 간에 호출을 하고 데이터를 주고받으며 협력하여 전체 웹 서비스를 구성한다.
이는 각각 @Controller
@Service
@Repository
라는 용어와 매핑되는데 자세한 역할과 내용은 앞으로 차근차근 정리해보자!
계층형 아키텍처 패턴 중 presentation layer에 대해 조금 더 자세히 알아보자!
Spring Controller를 구현하기 위해서는 3개의 기본 Annotation이 사용된다.
📌 Annotation
Annotation은 자바 소스코드에 추가적인 정보를 제공하는 방법이다.
@
으로 시작하며 클래스, 메소드, 멤버변수, 파라미터 등에 부착 가능하다.
@Controller
➡️ Controller 역할을 하는 클래스를 지정하고 클래스 상단에 명시한다.
요청을 받아서 처리하고 응답을 한다는 부분에서는 @RestController
와 유사하지만,
@Controller
는 view(html파일 등)를 응답으로 가진다.
@RestController
➡️ Controller 역할을 하는 클래스를 지정하고 클래스 상단에 명시한다.
요청을 받아서 처리하고 응답을 한다는 부분에서는 @Controller
와 유사하지만,
@RestController
는 data(문자열, json, xml 등)를 응답으로 가진다.
@RequestMapping
➡️ 특정 Request를 처리하는 메소드를 지정하고 클래스 또는 메소드 상단에 명시한다.
바로 이전에 배운 @RequestMapping
어노테이션에 대해 조금 더 자세히 알아보자.
@RequestMapping
이 붙어있는 메소드는 클라이언트의 특정 요청이 왔을 때 Spring Framework에 의해 호출된다.
만약 @RequestMapping
이 붙어있는 메소드가 여러개 일 때는 어떤 메소드가 호출될까🤔❓
Spring Controller의 메소드들은 URI에 따라 호출이 결정된다.
➡️ 기본 도메인에 이어지는 /path
들에 의해 결정
➡️ RequestMapping Annotation에 URI Path 정보를 명시
📌 URI (Uniform Resource Identifier)
- URL과 유사한 개념(URL이 더 하위개념)
- 특정한 자원에 접근하기 위한 이름 또는 주소
- 웹 상의 모든 자원들은 URI를 가지고 있음(웹 페이지, 이미지, 영상 등)
브라우저에서 /hello
로 요청을 하면, 스프링 프레임워크가 이 path 정보를 확인하고, 알맞게 처리를 한다.
사진과 같이, Controller 클래스에 @RequestMapping
을 활용할 수도 있다.
이렇게 되면 특정 Controller 클래스 내부의 모든 메소드에 path를 적용하게 된다.
/user/paid
/user/enterprise
/user/administor
Interface란 두 개체 간의 정보를 공유하기 위한 방법이다.
비슷하게 API(Application Programming Interface) 는 컴퓨터(프로그램)간 정보를 공유하기 위한 방법이다.
그렇다면, HTTP API와 REST API의 차이점은 뭘까👀❓
1. HTTP API
HTTP API는 HTTP(S)를 활용하여 원격의 데이터를 공유하기 위한 API이다.
2. REST API
REST API는 REpresentational State Transfer의 약자로, 웹 상에서 효율적으로 데이터를 공유하기 위한 아키텍처 스타일이다.
실제로 다양한 조건이 만족되어야 하며, 실무에서 모든 조건을 만족하여 구현하기는 어렵다.
➡️ HTTP API와 REST API는 엄밀히 서로 다른 개념이지만, 실무에서 혼용되어 사용하고 있고 주로 REST API 명칭이 99.9% 정도로 사용된다!
@RestController
어노테이션은 REST API, HTTP API를 위한 클래스를 명시하는데 사용된다.
@RestController
클래스 내의 @RestMapping
이 붙은 개별 메소드들이 하나의
REST API, HTTP API라고 볼 수 있다.
➡️ HelloController
안에 @RestMapping
이 붙은 hello()
, bye()
각각을 REST API라고 보통 이야기한다.
우리가 지금까지는 추가적인 데이터 없이 그저 데이터의 요청만을 다뤘는데, 만약 다수의 사용자들이 서버의 요청을 할 경우에는 추가적인 정보가 필요하다.
이러한 추가정인 정보를 우리는 Request 파라미터라고 부른다!
클라이언트가 서버에 요청을 할 때, 추가적으로 전송하는 데이터이다.
2가지 유형의 Request 파라미터가 있다.
Spring Framework는 Request 파라미터를 메소드, 즉 @RequestMapping
어노테이션이 붙은 메소드의 파라미터에 저장한다.
?
뒤에 key1=value1&key2=value2&...
형태로 작성한다.@RequestParam
어노테이션을 사용한다.name
요소는 Query String의 key와 연결된다.예를 들어 http://localhost:8080/post?category=it&id=10
이라는 정보를 요청하면,
➡️ You requested it-10 post
라는 결과가 나오게 된다.
@RequestParam
의 요소들을 살펴보자.
name
: query string의 key, key와 변수명이 같다면 생략 가능required
: 필수 여부defaultValue
: 데이터가 들어오지 않았을 때 자동으로 세팅되는 값@RequestMapping
의 value URI에 {}
를 사용해 Path Param임을 표시한다.@PathVariable
어노테이션을 사용하며, 선택적 데이터인 경우에는 Path Param을 잘 사용하지 않는다.예를 들어 http://localhost:8080/user/admin/id/100
이라는 정보를 요청하면,
➡️ You requested admin-100 user
라는 결과가 나오게 된다.
그렇다면 어떤 경우에 무엇을 써야할까?
일반적인 추천 사항으로는
특정 자원을 요청하는 경우네는 Path Param을, 정렬이나 추가 필터링을 위한 데이터는 Query String을 사용하는 것을 권장한다.
필수 데이터는 Path Param, 선택적 데이터는 Query String❗️
- Path Param이 포함 된 URI는 클라이언트가 영향을 받기 때문에 변경 비용이 높다.
- Query String은 상대적으로 편하게 확장이 가능하다.
무엇보다, 조직(회사/팀)마다 표준이 존재하기 때문에 그에 따라 적절하게 활용하는 것이 가장 중요하다!
클라이언트가 서버에게 요청을 하면, 서버는 요청에 대한 처리를 한 후 결과를 반환한다.
이때 응답 결과가 단순 문자열, 이미지, 영상, JSON 등 다양한 형태를 가질 수 있는데
이번 시간에는 JSON에 대해 알아보도록 하겠다!
JSON(JavaScript Object Notation) 응답 데이터는 웹 개발시 가장 일반적으로 사용하는 응답 데이터 포맷이다.
데이터를 교환하는데 많이 사용되며, 기존의 방법(XML보다 가볍고 상대적으로 사람이 읽고 이해하기가 쉽다.
JSON 객체가 가장 기본 단위로, "key":value
데이터를 포함한다.
{}
)를 사용한다.""
)로 묶는다."key":value
는 쉼표(,
)로 구분한다.또한 JSON의 value에는 다양한 형태의 데이터타입이 올 수 있다.
HTTP👀❓
- HyperText(웹페이지)를 컴퓨터가 주고 받기 위한 규약
- IETF, W3C 등의 국제 표준 단체에서 HTTP에 대한 표준을 정하여 배포
- 모든 브라우저에서 웹 서버 등은 HTTP 표준에 따라 개발되고 통신함
HTTP Method란 HTTP 규약 중 하나로, 특정 자원에 대해 수행하는 행동의 종류를 명시한다.
HTTP Method를 사용하면 단일 URI로 다양한 행동을 정의할 수 있다!
GET
: 조회POST
: 생성PUT
: 수정DELETE
: 삭제이러한 HTTP Method는 데이터베이스의 동작과 위와 같이 매핑이 된다.
이를 CRUD 라고 한다.
HTTP Method를 사용하면 단일 URI로 다양한 행동을 정의할 수 있다.
HTTP Method는 @RequestMapping
어노테이션을 사용하여 구현할 수 있다.
method
옵션에 HTTP Method를 명시한다.
요청된 HTTP Method에 따라 해당 컨트롤러의 자바 메소드를 호출하게 된다.
스프링에는 위와 같이 HTTP Method를 위한 간소화된 어노테이션이 존재한다!
Request Data👀❓
- 클라이언트가 서버에 요청 시 전달하는 추가적인 데이터
- 우리가 알고 있는 2가지 방식의 데이터 전달 방식
- Query String
- Path Parameter
- 크기가 큰 데이터를 보내기 위해서는 다른 방식이 필요하다!!
Request Body는 Body 부분에 데이터를 보내는 방식이다.
일반적으로 데이터를 저장 및 수정할 때에는 POST
, PUT
메소드가 사용된다.
(+ GET
, DELETE
는 Query String, Path Param이 주로 사용)
Request Body에는 다양한 포맷의 데이터를 전송할 수 있는데 주로 JSON 데이터 형식이 사용된다.
클라이언트에서 위와 같은 JSON 데이터를 요청하면, 스프링에서는 자바 객체(PostDto
)가 저장시킨다.
Query String, Path Param과 같은 데이터 형식이 아닌 Request Body로 데이터가 들어오게 되면, @RequestBody
라는 어노테이션을 사용해주어야 한다!
API는 정보를 주고 받기 위한 방법/약속이다.
API를 사용하기 위해서는 사용 방법을 알아야 하는데, 이때 필요한 것이 API 문서이다.
자바의 sin
이라는 API의 문서이다.
이처럼 API 문서는 API를 사용하는 방법을 상세하게 명세한다.
REST API 문서란 프론트엔드에서 호출하기 위한 REST API의 정보가 명세된 문서이다.
보통 백엔드 개발자의 주도로 프론트엔드 개발자가 함께 설계를 하고,
프론트엔드 개발자는 약속된 REST API 문서에 의존하여 프론트엔드를 개발한다
중요한 점은, 프론트엔트 등 클라이언트에서 호출/활용하는 데 어려움이 없도록 상세하게 작성되어야 한다는 점이다!!
📌 REST API가 담고 있어야 하는 정보
REST API 문서가 잘 작성 될 수록 커뮤니케이션 비용이 줄어들기 때문에, REST API 문서는 잘 작성되어야 한다!!
Spring Service 계층이란, 시스템의 핵심 비즈니스 로직을 구현하는 계층으로, view의 종류와 database의 종류에 영향을 받지 않도록 설계해야 한다.
1. Service의 구현
@Service
어노테이션을 사용한다.마지막 항목을 자세히 봐보자.
이와 같이 하나의 클래스에 모든 내용을 구현하는 것이 아니라,
애플리케이션의 중요한 영역별로 클래스를 나누어서 Controller, Service 그리고 Repository 계층을 구현해야 한다.
객체지향 시스템에서는 다양한 객체들이 서로가 서로를 활용한다.
이처럼 하나의 모듈(클래스, 패키지 등)이 다른 모듈을 사용하는 것을 의존성이 있다라고 표현한다.
예를들어 PostController
에서 PostService
객체를 생성하고 있는데, 이러한 상황을 우리는 PostController
클래스가 PostService
클래스를 의존한다 라고 한다.
일반적으로 다른 객체의 기능을 활용하기 위해서는 멤버 변수에 new
로 객체를 생성하여 참조한다.
이런 경우에는 어떤 객체를 생성하여 사용할 것인지 코드 상에 명시가 된다.
➡️ 의존성이 compile-time에 생성 된다.
의존성 주입(DI-Dependency Injection) 이란 객체 생성을 외부에서 대신 수행해주는 것으로, 활용할 객체에 대한 의존성(참조)설정을 외부에서 대신 해준다.
이처럼 활용할 클래스(인터페이스) 타입의 멤버 변수만 선언한 뒤 생성자를 구현한다.
new
키워드로 객체를 생성하는 부분이 보이지 않는데 그렇다면 PostController
객체는 누가 생성하는 것일까?
➡️ 바로 Spring Framework가 한다!
Spring Framework는 애플리케이션이 실행되는 시점(Runtime)에 주요한 어노테이션들을 검색한 뒤, 특정 어노테이션이 붙어있으면 그에 대한 객체를 대신 생성을하고 관리를 해준다.
의존성에 대한, 참조에 대한 관리 또한 Spring Framework가 결정한다.
정리하자면,
@Controller
, @RestController
, @Service
등)@Configuration
의 @Bean
어노테이션이때 객체로 생성할 대상을 검색하는 과정을 컴포넌트 스캔(Component Scan)이라고 한다.
조건에 따라 객체들의 의존성을 관리한다.
Spring IoC 컨테이너란 Spring Framework에서 객체의 생성과 관리의 역할을 하는 컴포넌트이다.
그리고 Spring Bean란 사용자가 new
키워드를 통해 생성한 객체가 아닌, Spring IoC 컨테이너에 의해 생성되어 관리되는 Java 객체이다.
의존성 주입을 위한 단계를 알아보자.
Spring에 의해 객체가 생성되게끔 어노테이션을 설정한다.
사용할 객체를 멤버 변수와 생성자에 추가한다.
객체를 사용한다.
Java 클래스에 @Configuration
라는 어노테이션을 사용할 수도 있는데,
이렇게 하면 해당 클래스는 Spring Framework에 의해 설정 정보를 위한 클래스로 활용된다.
@Configuration
클래스 내에 @Bean
이라는 어노테이션을 사용한 메소드로 Bean을 생성할 수 있다.
이때 Bean으로 등록할 객체를 생성 후 리턴하는데 이 객체가 스프링 빈(=스프링에 의해 생성되고 관리되는 자바 객체)이 되게 된다.
이렇게 Spring Boot 컨트롤러와 REST API, Spring Bean의 기초 개념과 의존성 주입에 대해 학습해보았다!
코드프레소 홈페이지(https://www.codepresso.kr/)에는 오늘 포스팅한 Spring Boot를 활용한 웹 개발 관련 강의뿐만 아니라 다양한 강의들이 개설되어 있으니 모두 한번 씩 살펴보고 수강해보면 좋을 것 같다😃