728x90
1. 이번주 궁금증들
(1) Spring 환경에서 HTTP 요청과 응답을 JSON 형식으로 주고받는 방법은 무엇인가?
- 일단, JSON(Javascript Object Notation)이란 무엇일까?
- 어떤 언어에서든 해석 가능한 데이터 교환 형식. 그렇기에 대부분의 프로그래밍 언어에서 쉽게 생성하고 파싱할 수 있는 형식이다.
- 간단하고 가벼운 데이터 형식으로 텍스트 기반의 직관적인 데이터 표현 방식
- 요청(Request) : 클라이언트에서 서버로 JSON 형식의 요청을 보내는 경우, 이를 객체로 변환하기 위해 @RequestBody 사용
- 응답(Response) : @RestController를 사용한다면 controller 내 모든 메서드가 응답을 JSON 형식으로 자동 변환
@RestController
public class UserController {
// JSON 형식의 요청을 받아들이기 위해 @RequestBody 사용
@PostMapping
public User createUser(@RequestBody User user) {
// 여기서 user 객체는 JSON 요청에서 변환된 객체
// 로직 수행 후, 응답으로 JSON 형식의 user 객체를 반환
return user;
}
}
(2) URL 경로 변수 값을 메서드 파라미터로 받는 방법?
- @PathVariable은 URL 경로 변수 값을 메소드의 파라미터로 매핑하는데 사용된다
- ex) 삭제할 id를 경로 변수로 받는 경우
(3) ResponseEntity 활용
- ResponseEntity : HTTP 응답을 보다 세부적으로 구성할 수 있도록 도와주는 클래스. 이를 통해 응답 본문, HTTP 상태 코드, 그리고 응답 헤더를 모두 제어 가능하다.
- 응답 본문 (Body) : 반환할 데이터를 설정 가능하다.
- HTTP 상태 코드 (Status Code) : HTTP 응답의 상태 코드를 설정 가능. 상태 코드는 클라이언트에게 요청이 성공했는지, 실패했는지, 또는 다른 상태인지 알려준다.
- 응답 헤더 (Headers) : 필요에 따라 추가적인 메타데이터를 응답 헤더에 포함시킬 수 있다.
@RestController
public class UserController {
// JSON 형식의 요청을 받아들이기 위해 @RequestBody 사용
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
// 추가적인 로직 수행 예: 데이터베이스에 저장, 유효성 검사 등
// 응답 헤더 설정
HttpHeaders headers = new HttpHeaders();
headers.add("Custom-Header", "CustomHeaderValue");
// 응답 본문과 상태 코드 설정
return new ResponseEntity<>(user, headers, HttpStatus.CREATED);
}
// JSON 형식의 응답을 자동으로 변환하기 위해 @GetMapping 사용
@GetMapping("/{name}")
public ResponseEntity<User> getUser(@PathVariable String name) {
// 간단한 응답 예시
User user = new User(name, 25);
// 응답 헤더 설정
HttpHeaders headers = new HttpHeaders();
headers.add("Custom-Header", "CustomHeaderValue");
// 응답 본문과 상태 코드 설정
return new ResponseEntity<>(user, headers, HttpStatus.OK);
}
}
(4) @RestController vs @Controller
- @RestController
- 주 목적 : JSON이나 XML로 데이터를 반환. 주로 API를 만들 때 사용
- 사실상 @Controller와 @ResponseBody를 합친 것
- @Controller
- 주목적 : 웹 페이지를 반환. 주로 웹 애플리케이션에서 사용
(5) 렌더링(Rendering)이란?
- 데이터를 사용자에게 시각적으로 표시 가능한 형태로 변환하는 과정
- 주로 두 가지 형태로 나뉜다 -> CSR, SSR
(6) 서버 사이드 렌더링 (Servcer-Side Rendering) vs 클라이언트 사이드 렌더링 (Client-Side Rendering)
- SSR
- 사용자 요청에 맞게 html 페이지를 서버에서 생성하고 이를 브라우저로 전송하는 방식
- 장점
- 초기 페이지 로딩 속도가 빠르다. (서버에서 미리 생성된 HTML을 사용자 요청에 맞게 살짝 변형하여 바로 보내주기에)
- SEO 성능이 향상된다. (검색 엔진 크롤러는 JS를 실행하지 않고 HTML을 분석하는데 SSR을 사용하면 HTML 구조만 파악하기에 쉽게 크롤링 가능하다)
- 단점
- 서버 부하 증가 (사용자 요청이 많을 경우 서버에서 생성해야 하는 HTML 페이지 작업량이 많기에 서버에 부하가 많이 걸릴 수 있음)
- 페이지 전환 속도 (매번 전체 페이지를 서버에 요청하여 다시 로드하기에 페이지 전환 속도가 CSR에 비해 느리다)
- 과정
- 클라이언트 요청 : 사용자가 브라우저에게 URL을 클릭하면, 브라우저가 서버에 HTTP 요청을 보낸다.
- 서버 처리 : 서버는 요청을 받아 필요한 데이터를 DB에서 가져오고, 이를 바탕으로 HTML 페이지를 생성한다.
- HTML 전송 : 생성된 HTML 페이지를 브라우저로 전송한다.
- 브라우저 렌더링 : 브라우저는 서버에서 받은 HTML 페이지를 렌더링 하여 사용자에게 보여준다.
- CSR
- 초기 HTML 페이지를 서버에서 최소한으로 전송하고, JS를 통해 클라이언트 측에서 동적으로 콘텐츠를 렌더링 하는 방식
- 장점
- 빠른 페이지 전환으로 사용자 경험 향상
- 서버 부하가 적다.
- 단점
- 초기 페이지를 띄우는 과정에서 여러 작업이 수행되기에 초기 로딩 속도가 느리다.
- SEO 성능 낮음 (검색 엔진 크롤러가 JS를 제대로 실행하지 못하는 경우가 많기에)
- 과정
- 클라이언트가 서버에게 페이지 요청
- 서버가 기본적인 HTML 페이지와 JS 파일을 전송
- 브라우저가 JS를 실행해 필요한 데이터를 API로 가져옴
- 브라우저는 가져온 데이터를 기반으로 DOM을 조작하여 콘텐츠를 렌더링함
- SEO (Search Engine Optimizaition)이란?
- 검색 엔진 결과 페이지에서의 가시성과 순위를 높이기 위한 최적화 과정
- DOM (Document Object Model)이란?
- HTML과 같은 웹페이지 문서를 브라우저가 이해하고 조작할 수 있는 객체 기반의 문서 구조
- JS를 통해 동적으로 조작 가능
- 조작을 통해 웹 페이지 내용을 동적으로 변경하여 새로운 요소 추가 가능
(7) 객체 지향 생활 체조 원칙
- Though Works Antology 책에서는 객체 지향 프로그래밍을 잘하기 위한 9가지 원칙을 제시한다.
- 한 메서드에 오직 한 단계의 들여쓰기만 한다.
- 복잡한 논리를 단순화하고 메서드를 작은 단위로 쪼개어 가독성을 높인다.
// 안 좋은 예
public void processOrders(List<Order> orders) {
for (Order order : orders) {
if (order.isValid()) {
process(order);
}
}
}
// 좋은 예
public void processOrders(List<Order> orders) {
for (Order order : orders) {
processIfValid(order);
}
}
private void processIfValid(Order order) {
if (order.isValid()) {
process(order);
}
}
2. else 예약어를 사용하지 않는다.
3. 모든 원시 값과 문자열을 포장한다. (객체로 포장)
4. 한 줄에 점을 하나만 찍는다.
- 메서드 체이닝을 줄이고 객체의 역할과 책임을 명확히 한다.
5. 줄여 쓰지 않는다. (축약 금지)
6. 모든 엔티티를 최대한 작게 유지한다.
7. 3개 이상의 인스턴스 변수를 가진 클래스를 사용하지 않는다.
- 클래스가 너무 많은 책임을 가지지 않도록 인스턴스 변수의 수를 제한한다.
// 안 좋은 예
public class Order {
private String productName;
private int quantity;
private String customerName;
private String address;
private Date orderDate;
}
// 좋은 예
public class Order {
private Product product;
private Customer customer;
private OrderDetails orderDetails;
}
public class Product {
private String name;
private int quantity;
}
public class Customer {
private String name;
private String address;
}
public class OrderDetails {
private Date orderDate;
}
8. 일급 컬렉션을 사용한다.
- 일급 컬렉션 : 단일 컬렉션을 감싸는 클래스
- 컬렉션과 관련된 로직을 캡슐화하여 외부에서 컬렉션을 직접 조작하지 못하게 한다.
// 안 좋은 예
public class Order {
private List<Product> products;
public Order() {
this.products = new ArrayList<>();
}
public List<Product> getProducts() {
return products;
}
public void addProduct(Product product) {
products.add(product);
}
public void removeProduct(Product product) {
products.remove(product);
}
}
// 좋은 예
public class Products {
private final List<Product> products;
public Products() {
this.products = new ArrayList<>();
}
public void add(Product product) {
products.add(product);
}
public void remove(Product product) {
products.remove(product);
}
public List<Product> getList() {
return Collections.unmodifiableList(products);
}
// 추가 로직을 여기에 포함 (예: 특정 조건에 맞는 제품 필터링)
}
9. getter / setter / property를 사용하지 않는다.
(8) 라이브러리 vs 프레임워크
- 구분 기준 : 실행 흐름과 제어의 흐름
- 라이브러리를 사용하는 애플리케이션 코드는 애플리케이션이 흐름을 사용자가 직접 제어한다. 작동 중에 기능이 필요할 때만 능동적으로 사용한다. 또한 실행 흐름이 없다.
- 프레임워크는 개발자가 만든 클래스에 대한 제어 권환을 넘겨받아서 주도적으로 애플리케이션의 흐름을 제어한다. 개발자가 만든 클래스의 오브젝트를 생성하고 실행하는 일은 프레임워크에 의해 진행된다. 또한 실행 흐름이 있고 이 실행 흐름은 무한 루프를 돈다.
(9) 메이븐 vs 그레이들
- 메이븐
- XML 형식으로 종속성을 관리
- 엄격하고 때로는 독단적인 접근 방식이 프로젝트와 개발 환경을 일관되게 만든다.
- 그레이들
- 스크립트 길이와 가독성 측면에서 우수하다.
- 그레이들 데몬 등을 활용하면 빌드 속도가 메이븐보다 빠르다.
(10) @Override란?
- 메서드에 적용되며 해당 메서드가 상위 클래스나 인터페이스에서 선언된 메서드를 재정의하고 있음을 나타낸다.
- 사용 이점
- 코드의 가독성
- 컴파일 검사 : 재정의된 메서드가 인터페이스의 메서드와 일치하지 않으면 컴파일러가 오류를 발생시킨다.
(11) @Entity 붙이고 안 붙이고의 차이?
- JPA에서 사용되는 어노테이션으로 해당 클래스가 JPA 엔티티임을 나타냄
- 사용 이점
- JPA가 해당 클래스를 DB 테이블에 매핑함
- JPA가 관리하고 DB 연산을 할 수 있음
(12) RowMapper 사용 이유?
- RowMapper : rowNum에 대한 행의 query문 결과값을 객체에 매핑
- 각 행의 DB 쿼리 결과값을 객체로 변환하는 역할을 한다. 이때, 쿼리의 결과값을 ResultSet으로 반환된다.
- 여러 곳에서 동일한 매핑 로직을 사용할 때 재사용 가능하다.
(13) schema.sql 설계 후 설정 과정
- schema.sql에 테이블 설계
- Spring Boot 애플리케이션 시작
- application.yml 설정에 따라 DB 연결
- Spring Boot가 schema.sql 파일의 SQL 스크립트를 실행하여 DB 초기화
(14) Exception 발생 시 handler 동작 과정
- ex) 다음과 같이 ProductNotFoundException이 발생하였을 때 어떤 과정이 이루어지는가?
@GetMapping("/edit/{id}")
public String showEditForm(@PathVariable("id") Long id, Model model) {
Product product = productService.getProductById(id);
if (product == null) {
throw new ProductNotFoundException(id);
}
model.addAttribute("product", product);
return "edit_product";
}
- 컨트롤러에서 ProductNotFoundException 발생
- Spring MVC는 해당 예외를 처리할 수 있는 @ControllerAdvice가 붙은 클래스의 @ExceptionHandelr 탐색
- (선택) exception을 처리하는 메서드에서 Custom Exception 클래스 요청
- 응답 반환
(13) 보통 Exception 처리는 어느 계층에서 이루어지는가?
- 보통 예외 처리는 service 계층에서 처리하는 것이 일반적이다. service 계층은 비즈니스 로직을 담당하므로, 예외 처리를 통해 비즈니스 규칙을 적용하고 데이터 무결성을 검증하기 때문이다. 또한 동일한 서비스 메서드를 여러 컨트롤러에서 재사용할 수 있고, 이로 인해 중복된 예외 처리 코드가 줄어든다.
(14) data.sql 활용
- 기본 데이터 삽입 : 애플리케이션 시작 시 기본 데이터를 삽입하여 초기 상태 설정 가능
- DB 스키마 일부 수정 : 기존 테이블에 대한 추가적인 수정 작업 수행 가능
- DB 검사 : 애플리케이션 시작 시 특정 데이터가 존재하는지 검사와 같은 기능들을 수행
2. 계절학기 대면수업 내용
- 나의 질문 : 개인 프로젝트나 과제를 하는 경우 요구되는 기능 구현을 완료하면 더 이상 refactoring 하지 않는 듯합니다. 왜냐하면 목표를 이루었다고 생각하니깐! 그러나 저보다 잘하는 개발자의 경우 하드 코딩한 것들을 훨씬 완벽한 로직으로 구사할 수 있을 거 같습니다. 따라서 기능 구현 이후 리팩토링은 어느 정도 선까지 해주는 것이 좋을까요?
- 교수님 : 토이프로젝트의 경우 기능 구현까지만 하고 넘어가도 무방하다. 그러나 애정 가는 프로젝트 한 개를 계속 틈만 나면 리팩토링하는 것이 훨씬 낫다. (2.0까지 한 개발자의 글이 떠오르는 교수님의 답변!)
- 나의 질문 : 회고하는 방식 중에서 최고는?
- 교수님 : 주니어 개발자들끼리 일주일에 한 번씩 만나서 일주일동안 어느 부분에서 막혔는데 해결했고, 어떤 것을 실수했는지 서로 태클 절대 걸지 말고 그냥 터놓고 말하기. 개인 블로그에 일주일 한 번 정도 자신이 배운 것들, 실수한 것들 등등을 기록하기.
- 또한 Naver D2, 우아한 형제들 기술블로그와 같은 회사 기술 블로그들을 추천해 주셨다.
- 우리가 사용하는 도구에 대해 정확히 인지하고 쓰임을 의심해 볼 필요가 있다.
- ex) 이번에 파이썬을 활용한 프로젝트를 하는데 Django 안 쓰고 FastAPI를 쓰기로 함. 왜...?? 둘의 장단점??
- 교수님께서 말씀하시는 도구들 : 언어버전, 번들링 및 빌드팩, IDE (단축키 등), Git GUI 도구
3. 이번주차 과제 수행과정
- 1단계 : 상품 API 기능 요구사항
- 2단계 : 관리자 화면 기능 요구사항
- 3단계 : 데이터베이스 적용 기능 요구사항
- README.md에 구현할 기능들 정리
- 상품 Model 정의 - Product (Jdbc 사용하기에 @Entity 안 붙여도 무방)
- 컨트롤러 구현
- 요청에 따라 웹페이지 띄우기
- 대략적인 웹페이지 구조 및 ui 구현
- 요청에 따라 CRUD 수행 후 redirect를 통해 웹페이지 띄우기 -> Model을 메서드 파라미터로 받아 상품(Product)을 addAttribute 메서드를 통해 웹 페이지에 집어넣기
- 요청에 따라 웹페이지 띄우기
- 서비스 구현
- 유효성 검사하기
- Exception handelr 및 에러 페이지 구현
- 레포지토리 구현
- JdbcTemplate 활용
- RowMapper 활용
- schema.sql, data.sql, application.yml 설정
- 통합 테스트 구현
- CRUD 테스트
- exception 테스트
- 구현 결과
4. 추가적인 내용들
- 1.0 프로젝트를 많이 만든 개발자보다 피드백을 반영하여 2.0까지 만들어본 개발자를 더 선호한다.
- 자바 도서 추천
- effective java (조슈아 블로크)
- Moder Java in Action
'Backend > Spring' 카테고리의 다른 글
[세차새차] 양방향 매핑 지양과 순환 참조의 위험성 - 회원 관리 기능 개발 (2) | 2024.08.31 |
---|---|
[Kakao Tech Campus Step2] 2주차 회고 (0) | 2024.07.07 |
[Spring Core] 초록 스터디 Step3 회고 (0) | 2024.05.03 |
[Spring MVC] 초록 스터디 Step2 회고 (1) | 2024.04.22 |
[Spring MVC] 초록 스터디 Step1 회고 (1) | 2024.04.14 |