💡 웹이란, 우리 모두를 위한 정보 공유의 장.
섹션2 : 웹이 뭐길래
인터넷 안에서 웹 공간을 찾아가려면!
HTTP (Hyper Text Transfer Protocol)
- 받는 사람, 인사, 말, 끝인사, 보내는 사람 → 형식을 맞추어서!
- 예시) https://www.naver.com
- https의 s는 secure.
섹션3: 백엔드 개발자는 API를 만듭니다.
API란
API (Application Programming Interface)
- 시스템과 유저 사이에서 일정한 ‘틀’을 제공하여 필요한 정보만 받을 수 있도록 하는 시스템.
REST API
REST API ( Representational State Transfer API)
- 백엔드 개발자가 만들어야 할 것.
- REST API가 생겨나게 된 배경은
- 고전적인 API는 화면을 포함한 모든 데이터를 틀에 맞지 않게 작성하여 전달. → 성능이 느리다.
- 틀과 규칙을 맞추고, 필요한 데이터만 전달하도록 진화. → REST API의 정의. 가볍고 빠르다.
- REST’ful’ ? : 규칙을 잘 지킨~ 이라는 느낌.
URL
웹에서 요청을 하는 방법
= API를 사용하는 방법
= API를 호출하는 방법
- 데이터를 가져오려면 JAVA로 메서드를 호출해야하는데, 이걸 어떻게 하는가?
- URL을 호출함으로서 사용한다.
REST API에 맞는 HTTP
HTTP 틀에 잘 맞추려면
- URL : 이 API의 이 기능을 호출하고 싶어!
- 목적 : 조회, 등록, 수정 etc..
- 데이터 : body에 담아서.
그 외에 여러가지가 있지만 기본은 위 세가지.
섹션4. Hello Spring
스프링 프레임워크란?
- 개발자 지향적인 기술
- 웹을 만들기 위해 필요한 모든 것이 있는 프레임워크.
라이브러리 vs 프레임워크
- 라이브러리 : 도서관.
- 쉽게 풀이 : 내가 필요한 걸 직접 찾아서 하나하나 찾아 쓴다.
- ‘소프트웨어를 개발할 때 컴퓨터 프로그램이 사용하는 비휘발성 자원의 모음’ 이라는 뜻.
- 프레임워크 : 틀 안에서 다 해결됨.
- 쉽게 풀이 : 이 안에 있는 것 중에서 골라서 쓴다.
- ‘일정한 틀과 규약을 가지고 일하다’ 라는 뜻.
- 모든 기능을 이 안에서 해결하기 때문에 인수인계가 쉬우며, 팀 단위 개발을 할 때도 중구난방이 되지 않을 수 있다.
스프링 프레임워크 안에 이렇게 많이 들어있다고?
- Spring framework로 모든 작업을 할 수 있지만, 최근 추세가 frontend는 별개의 프레임워크(ex. React) 로 구현을 하기 때문에 Spring은 Rest API를 만드는 프레임워크로 자리를 잡게 됨.
- Spring 안에는..
- 데이터베이스 접근
- web쪽 기능
- AOP
- Test기능
- Core 기능
- 백엔드 개발에 화면은 필수가 아니다.
스프링 부트란?
스프링을 직접 다루기 위해서는 설정할 게 많다. 설정을 쉽게 하기 위해 사용하는 것이 Spring Boot.
스프링 부트는..
- 웹 서버 + 웹 어플리케이션 서버가 포함되어있음.
- 개발자가 로직에 더 집중할 수 있도록 해준다.
섹션5. SpringBoot
💡 실습 환경IDE는 IntelliJ로 진행한다. Community버전은 무료이며, jetbrain toolbox로 설치하는 것이 권장된다. (업데이트 때문에)
Project는 Gradle-Groovy, Language는 Java, Boot 버전은 2.7, Java 1.8, Packaging은 Jar, Dependencies는 Spring Web 으로 사용한다.
start.spring.io 설명 및 프로젝트 다운로드
- spring initializr에서 기반을 미리 다 만들어줘서, 빠르게 개발을 시작할 수 있다.
- 빌드 도구
- Ant → Maven → Gradle
- Gradle이 좀 더 빠르고, 간결.
- Gradle에도 사용하는 언어에 따라 두 가지로 나뉘는데
- Groovy : 주로 많이 사용. Gradle만을 위해 사용하는 언어로 쉽게 사용 가능.
- Kotline
- Ant → Maven → Gradle
- 언어 선택
- Java
- Kotline
- Groovy
- Spring Boot
- 여러가지 버전이 있지만, 번호만 적혀있는 Stable 버전을 사용하는 것을 권장.
- jdk 버전 8, 11 사용할 경우 2.x 사용 → 지원기간 종료로 지원 X
- jdk 17 이상일 경우 3.x 사용
- 여러가지 버전이 있지만, 번호만 적혀있는 Stable 버전을 사용하는 것을 권장.
- Project Metadata
- 프로젝트명, 패키지명, JDK버전 등 내용 작성.
- Artifact : 프로젝트명
- Packaging
- Jar : 웹서버, WAS까지 한 번에 압축
- War : 웹 제외하고 압축
- 프로젝트명, 패키지명, JDK버전 등 내용 작성.
- Dependencies
- 사용을 하는 것들.
- REST API를 만들기 위해서는 Spring Web Dependency는 필수.
- 나중에 추가도 가능.
프로젝트 구조 살펴보기
💡 IntelliJ에서 Project open 시에는 폴더 내의 build.gradle 파일을 열어야 한다.
💡 처음 Open할 때는 이것저것 모두 받아오기 때문에 느리다. 좌측 하단의 Build에서 Build Successful 문구를 확인하자.
- src
- 실질적인 로직을 짜는 곳은 src > main > java
- 소스 코드 외의 것들 src > resources
- TDD : Test Driven Development
- 테스트를 기반으로 구현하는 개발방법.
- src > test 폴더 제공을 하고 있음.
- build.gradle
- gradle이 빌드를 할 때 사용하는 파일.
- groovy로 작성되어있음.
- gradlew.bat
- 이 프로그램을 패키징할 때 사용함.
- window는 bat, mac은 다른걸 사용.
- External Libraries
- Gradle이 다운받은 라이브러리들 모음.
IoC, DI
스프링의 주요 개념(Core)
- IoC
- DI
- Container
- Spring Bean
IOC
: 제어의 역전 (Inversion of Contorl)
- inverse : 정반대로 뒤집힌다. (갖고있다 → 가지고있지 않다) control : 제어 “프로그램의 흐름”
- = 프로그램의 흐름을 제어하는 주체가 정반대로 뒤집힌다. = 객체의 흐름을 제어하는 주체가 정반대로 뒤집힌다. (객체의 생성, 사용, …라이프사이클)
- 원래 객체생성은 개발자가 코드로 직접 생성하여 사용하였으나, 이를 spring이 대신해주는 것을 의미한다.
DI
: 의존성 주입 (Dependency Injection)
- 의존한다 = 사용한다.
- 객체를 사용한다. = 객체의 메소드, 필드를 사용한다. → 객체의 생성부터 해야한다(IoC).
- 내가 직접 객체 생성을 해서 쓰는게 아니라 주입을 당해서 사용한다. IoC가 생성한 객체를 사용하도록 주입해달라고 요청.
Container
: 담아두는 공간, 박스
- 스프링이 객체를 생성해서 관리를 해야하는데, 이 객체를 담아두는 게 Container.
- IoC를 위한 컨테이너, DI에 사용하는 컨테이너 등으로 표현하기도 하지만, 최근에는 DI컨테이너라고 한다.
Spring Bean
- 스프링(이 컨테이너에 담아놓고 관리하는) 객체
스프링 MVC: Controller – Service – Repository
Spring MVC
- Model :
- 데이터 처리(연산), 로직
- 데이터를 가지고 연산을 하려면, 데이터베이스와 소통 필요
- (계층, 클래스) Service / Repository
- // View : 화면
- Controller :
- Model – View 중간 매개체(기존)
- Model – 사용자 중간 매개체(최근)
💡 REST API 환경을 구성한다고 했을 때, Spring에서 화면을 구현하는 경우는 드물기 때문에 View가 잘 사용되지 않는다. 그래서 위에서 View는 다루지 않고, Controller에서도 view가 아닌 사용자(Client)로 변경됨.
프로젝트 구동 시켜보기
- 가장 처음 확인해야 하는 것은 main method가 정상적으로 기동하는지 이다.
- 상단의 start버튼 클릭하여 기동 테스트를 하고, http://localhost:8080으로 접속 테스트 진행
- 기동 로그 : 정상 기동됨을 확인.
오후 1:26:16: Executing ':com.example.demo.DemoApplication.main()'...
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :com.example.demo.DemoApplication.main()
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.17)
2024-08-21 13:26:19.507 INFO 16432 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication using Java 1.8.0_202 on P94101681-003 with PID 16432 (D:\demo\build\classes\java\main started by jsm5125 in D:\demo)
2024-08-21 13:26:19.511 INFO 16432 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default"
2024-08-21 13:26:20.533 INFO 16432 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2024-08-21 13:26:20.545 INFO 16432 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-08-21 13:26:20.545 INFO 16432 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.82]
2024-08-21 13:26:20.717 INFO 16432 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-08-21 13:26:20.717 INFO 16432 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1147 ms
2024-08-21 13:26:21.093 INFO 16432 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2024-08-21 13:26:21.104 INFO 16432 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.938 seconds (JVM running for 2.609)
브라우저 결과 : 아직 아무것도 안했기 때문에 안나오는게 맞음.
Controller, Service, Repository 클래스만 만들어보기
- new > Java Class로 클래스 생성
자바 어노테이션
- 어노테이션을 기재함으로써, 의도하지 않은 실수를 방지할 수 있다.
- 그 외에도 여러가지 기능들이 있기 때문에 Spring에서 주요한 역할을 한다.
- 아래 예제는 Override 환경에서 오탈자가 발생했을 때 @Override annotaion이 해당 내용을 확인해주는 내용이다.
패키지 구조, 이름 생각해보기 + Controller부터 만들기
구현 예제 : 상품 등록, 조회 API 프로젝트
- 화면 없이, Spring을 이용한 Backend API.
DDD : Domain Driven Development (도메인 단위로)
- 상품 등록, 상품 조회 라는 기능에서 공통된 “상품”이라는 도메인을 사용
- new > package로 도메인명으로 패키지 생성
유지보수를 위해, 모듈화를 진행 (product의 controller, order의 controller 등)
- Refactor > Rename 하여 classfile의 이름을 변경
//controller
package com.example.demo.product;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
//Controller annotation 설정
//ResponseBody는 REST API 의 틀에 맞게 "body"에 넣어 보내줘야함. 이 어노테이션이 REST API로 인식하게 해주어 정상적으로 데이터가 표출된다.
@Controller
@ResponseBody
public class ProductController {
// "사용자(화면)" 요청을 던지면 그걸 받아서
// 요청에 맞는 메소드를 실행시킵니다.
// 그 안에서 그에 맞는 로직을 수행할 수 있도록 서비스한테 시킴.
//handler = 요청에 따른 메소드 호출.
//상품 조회
//()안의 요청이 들어오고 method가 일치한다면 이 메서드를 실행하도록 한다.
//value 내부 값이 http://localhost:8080인 경우 생략 가능.
@RequestMapping(value="", method= RequestMethod.GET)
public String findProduct(){
return "Notebook";
}
}
너에게 요청하는 목적, HTTP method
- 조회 : GET
- 등록(생성) : POST
- 수정 : 전체 – PUT 부분 – PATCH
- 삭제 : DELETE
Service 추가해보기 (Service – Repository 틀 만들기)
컨트롤러는 요청을 받아 서비스한테 일을 시키고
서비스는 일을 처리해서 결과를 반환하도록 변경.
//ProductController
package com.example.demo.product;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody
public class ProductController{
@RequestMapping(value = "", method = RequestMethod.GET)
public String findProduct(){
ProductService productService = new ProductService();
return productService.findProduct();
}
}
//Product Service
package com.example.demo.product;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
public String findProduct(){
return "Notebook!";
}
}
섹션6. 스프링 코어
스프링 IoC & 스프링 빈 등록 방법 2가지 & DI
1 . 우리가 직접 객체를 생성하는 대신, 스프링이 객체를 생성 등 관리하라고 요청
- = 스프링 빈으로 등록해줘.
- 등록 방법
- @Component
- @Configuration + @Bean
💡 *Service 어노테이션에는 Component가 이미 등록되어있다 (Cntl+ 서비스 어노테이션 클릭으로 확인 가능)
- 스프링에게 컨테이너에 서비스 빈을 달라고 요청. (DI)
- = 등록된 빈을 사용하게 주입해줘
- 등록방법
- Controller에 Service Class의 필드를 생성하고 @Autowired 어노테이션을 추가.
package com.example.demo.product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody
public class ProductController{
@Autowired
private ProductService productService;
@RequestMapping(value = "", method = RequestMethod.GET)
public String findProduct(){
//ProductService productService = new ProductService();
return productService.findProduct();
}
}
@Component를 달아두면 생기는 일
- Spring이 Spring Bean으로 만들어서 써야함을 인식하는 태그
- Service뿐만 아니라 Controller에도 들어가있음.
- SpringBootApplication 어노테이션을 확인해보면 컴포넌트를 찾아주는 역할을 수행함을 확인할 수 있음.
Repository는 Map으로
서비스는 연산,로직 담당.
Repository가 데이터를 꺼내오는 역할.
- @Repository 어노테이션 작성.
💡 DB는 현재 연결하기 번잡스러움으로 Map을 통해 간략히 만들어만 두고, Return은 String으로 처리한다.
//Service
package com.example.demo.product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public String findProduct(){
return productRepository.findProduct();
}
}
//Repository
package com.example.demo.product;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.Map;
@Repository
public class ProductRepository {
private Map<Integer, String> db = new HashMap<>();
private int id = 1;
public String findProduct(){
return "NoteBook";
}
}
DI 3가지 방법 – 추가적으로 알아보기 필요.
- 필드로 주입 받음
- 필드 위에 @Autowired
- 테스트하기에 어려움이 있음.
- Setter로 주입 받음
- 최근에는 잘 사용되지 않음.
- setter메서드 위에 @Autowired.
- 사용 안하는 이유 : public으로 열려있어 누구나 접근이 가능하기 때문에 사용하지 않음.
- 생성자로 주입 받음
- 생성자 위에 @Autowired.
- 테스트하기에 좋으므로 권장됨.
//ProductService 생성자로 주입받는 코드
package com.example.demo.product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
private ProductRepository productRepository;
@Autowired
ProductService(ProductRepository productRepository){
this.productRepository = productRepository;
}
public String findProduct(){
return productRepository.findProduct();
}
}
섹션7. 상품 등록해보기
“Notebook” 등록하기.
- Repository에 save 메서드 생성하여 db에 데이터 넣기.
@Repository
public class ProductRepository {
private Map<Integer, String> db = new HashMap<>();
private int id = 1;
public String findProduct(){
return db.get(1);
}
public void save() {
db.put(id++,"NoteBook");
}
}
- Service에 saveProduct 메서드 생성하여 ProductRepository.save() 호출 \
@Service
public class ProductService {
private ProductRepository productRepository;
@Autowired
ProductService(ProductRepository productRepository){
this.productRepository = productRepository;
}
public String findProduct(){
return productRepository.findProduct();
}
public void saveProduct(){
productRepository.save();
}
}
- Controller에서 setProductService 메서드 생성하여 ProductService.saveProduct()호출
@Controller
@ResponseBody
public class ProductController{
@Autowired
private ProductService productService;
@RequestMapping(value = "", method = RequestMethod.GET)
public String findProduct(){
return productService.findProduct();
}
@RequestMapping(value = "", method = RequestMethod.POST)
public void setProductService(){
productService.saveProduct();
}
REST API URL 규칙
localhost:8080
메서드가 get, post로 다르므로 product_get 등을 사용하지 않아도 된다.
- 상품 조회 ( method=GET )
- localhost:8080/products → 보통 현업에서는 복수형.
- 상품 등록 ( method=POST )
테스트 방법
테스트 수행 방법
- 간단한 테스트를 수행하기 위해서는 로그를 남기는데, System.out.println() 은 간단하게 사용하긴 좋지만 권장되진 않는 방법.
- 어.. IntelliJ에서 Sysout하면 안되네 어떻게하지?
- → 어휴.. return 아래에다 하니까 안되지!
Hello Postman
post 테스트를 위해 postman을 설치.
- desktop 버전을 권장. (온라인 버전은 안되는 기능이 좀 많음)
- 사용 방식은 method와 url을 입력하여 테스팅.
- Status code가 200이면 성공.
- post 시도 후 get 시도하였을 때 정상적으로 데이터가 “Notebook” 으로 찍히는 것을 확인.
섹션 9. 원하는 상품을 가져오기
요청을 받을 때 데이터도 같이 받는 방법
- HttpServletRequest
- @RequestParam
- http://localhost:8080/products? → requestparam(쿼리스트링)
- name=~~~~
- 개인정보는 입력받지 않게! URL에 개인정보 돌아다니는건 좀..
- RequestParam을 사용하면, url에서 꼭 name=“” 으로 하지 않고 name=~~ (따옴표 없이) 해도 알아서 지정한 타입(현재는 String)으로 받는다.
- http://localhost:8080/products? → requestparam(쿼리스트링)
- @RequestBody
- @ModelAttribute
- @PathVariable
- code
- RequestParam을 이용하여 Controller → Service → Repository로 데이터를 이동하고 내부 로직을 수정하여 가장 최근에 입력한 내용을 가져오도록 수정.
- Repository에서, 강의 그대로 진행하면 db의 첫번째 들어간 데이터만 반환하게 되므로, 아래와 같이 로직을 수정함. (이후 과정에서 재수정함)
//Controller
@Controller
@ResponseBody
public class ProductController{
@Autowired
private ProductService productService;
@RequestMapping(value = "/products", method = RequestMethod.GET)
public String findProduct(){
return productService.findProduct();
}
@RequestMapping(value = "/products", method = RequestMethod.POST)
public void setProductService(@RequestParam(value="name") String productName){
//http://localhost:8080/products?name=~~ -> productName
//받아온 데이터를 서비스에 전달
productService.saveProduct(productName);
}
}
//Service
@Service
public class ProductService {
private ProductRepository productRepository;
@Autowired
ProductService(ProductRepository productRepository){
this.productRepository = productRepository;
}
public String findProduct(){
return productRepository.findProduct();
}
public void saveProduct(String productName){
productRepository.save(productName);
}
}
//Repository
@Repository
public class ProductRepository {
private Map<Integer, String> db = new HashMap<>();
private int id = 0;
public String findProduct(){
return db.get(id);
}
public void save(String productName) {
db.put(++id,productName);
}
}
테스트 방식
- postman의 POST를 사용하여 macbook을 등록
- postman의 GET을 사용하여 macbook을 가져오기
@PathVariable로 조회하고싶은 상품 id를 직접 받아보기
- 언제 무엇을 사용하는가?
- 입력을 받는 값을 사용 할 때 = @RequestParam
- 정해져 있는 시스템 값의 조회를 하고싶다면 = @PathVariable
- url
- code
- PathVariable을 사용하여 Controller → Service → Repository를 거쳐 데이터를 정상적으로 조회할 수 있도록 작성한다.
- @RequestMapping에서 받을 때부터 url에 {id}를 넣어주어야 정상적으로 인식하여 들어온다.
//Controller
@Controller
@ResponseBody
public class ProductController{
@Autowired
private ProductService productService;
@RequestMapping(value = "/products/{id}", method = RequestMethod.GET)
public String findProduct(@PathVariable("id") int id){
System.out.println(id);
return productService.findProduct(id);
}
@RequestMapping(value = "/products", method = RequestMethod.POST)
public void setProductService(@RequestParam(value="name") String productName){
//http://localhost:8080/products?name=~~ -> productName
//받아온 데이터를 서비스에 전달
productService.saveProduct(productName);
}
}
//Service
@Service
public class ProductService {
private ProductRepository productRepository;
@Autowired
ProductService(ProductRepository productRepository){
this.productRepository = productRepository;
}
public String findProduct(int id){
return productRepository.findProduct(id);
}
public void saveProduct(String productName){
productRepository.save(productName);
}
}
//Reposirtory
@Repository
public class ProductRepository {
private Map<Integer, String> db = new HashMap<>();
private int id = 1;
public String findProduct(int idx){
return db.get(idx);
}
public void save(String productName) {
db.put(id++,productName);
}
}
섹션 10. 상품에 데이터를 더 넣기
상품 객체 만들어서 @RequestBody로 받아보기
- 객체(class)를 만들어 세트로 움직이기.
- 각 properties가 private이기 때문에, 다른 클래스의 메서드에서 가져와 사용할 수 없음. 이 때 getter, setter를 사용함.
- 생성 방법은 클래스 내부에서 마우스 우클릭 → generate → getter, setter
- 각 properties가 private이기 때문에, 다른 클래스의 메서드에서 가져와 사용할 수 없음. 이 때 getter, setter를 사용함.
public class Product {
private String name;
private int price;
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
- @RequestBody
- http://localhost:8080/products
- body에 넣어 전송된 데이터를 받아오기.
//controller
@Controller
@ResponseBody
public class ProductController{
@Autowired
private ProductService productService;
@RequestMapping(value = "/products/{id}", method = RequestMethod.GET)
public String findProduct(@PathVariable("id") int id){
System.out.println(id);
return productService.findProduct(id);
}
@RequestMapping(value = "/products", method = RequestMethod.POST)
public void setProductService(@RequestBody Product product){
productService.saveProduct(productName);
}
}
Json
: Java Script Object Notation.(자바 스크립트 객체 형태)
key-value 형태로 기재됨.
var product = {
name: "handcream",
price: 15000
}
product.name
product.price
형식으로 사용.
💡 @RequestBody에서 알아서 매핑해줌. 자바스크립트에서 건너오는 객체를 이름만 맞다면 필드값을 하나하나 맞춰서 데이터를 담아줌. → Message Converter로 인해서 이 기능이 가능. 추가적인 정보가 필요하면 찾아보기.
postman으로 테스트해보기
- RequestBody로 받으려면 postman에서 Body > raw에서 Json 형식으로 데이터를 보내줘야함
{
"name":"hihi",
"price":150000,
"description":"hi im hihi"
}
Repository 고도화하기
- 조회 시에 해당 데이터들을 모두 가져오게 하기 위해서, return type을 Product로 변경.
//Controller
@Controller
@ResponseBody
public class ProductController{
@Autowired
private ProductService productService;
@RequestMapping(value = "/products/{id}", method = RequestMethod.GET)
public Product findProduct(@PathVariable("id") int id){
System.out.println(id);
//json형태로 반환됨.
return productService.findProduct(id);
}
@RequestMapping(value = "/products", method = RequestMethod.POST)
public void setProductService(@RequestBody Product product){
productService.saveProduct(product);
}
}
//Service
@Service
public class ProductService {
private ProductRepository productRepository;
@Autowired
ProductService(ProductRepository productRepository){
this.productRepository = productRepository;
}
public Product findProduct(int id){
return productRepository.findProduct(id);
}
public void saveProduct(Product productName){
productRepository.save(productName);
}
}
//Repository
@Repository
public class ProductRepository {
private Map<Integer, Product> db = new HashMap<>();
private int id = 1;
public Product findProduct(int idx){
return db.get(idx);
}
public void save(Product productName) {
db.put(id++, productName);
}
}
- Controller에서 Return까지 Product로 하면, 브라우저에서는 JSON 형식으로 받게 된다.
섹션 11. 앞으로..
- 상품 수정, 삭제
- @Configuration+ @Bean 조합으로 스프링 빈 등록 해보기.
- Entity vs DTO → DTO를 사용하는 이유
- DB연결 (JPA)
- AOP
후기
사실 Java 와 Spring 모두 배웠었지만.. 그 때 당시엔 전혀 이해가 안됐었는데, 이 강의를 듣고 가닥이 잡히는 느낌이다.
이래서 돈 주고 비싼 강의를 듣는거구나 싶다. 이번에 이렇게 시작하게됐으니 완전히 전문적인 백엔드 까진 아니더라도 스타트업 초기 사업모델 만들 수 있을 정도의 백엔드 실력(어떻게든 돌아가는)을 갖추는 걸 목표로 노력해보자!
우선 현재 위 예제를 모두 이해하며 안 보고 처음부터 끝까지 만들어보는 걸 다섯 번 해봤고, 마지막으로 한 번 더 복습 후 다음 강의로 넘어가려한다.
그나저나.. 노션으로 정리한 내용 워드프레스 붙여넣는거 굉장히 불편한데 무슨 다른 방법이 없으려나ㅋ큐ㅠㅠ
출처 : Udemy- 옆집 개발자와 같이 진짜 이해하며 만들어보는 첫 Spring Boot 프로젝트