★요구사항 분석과 기초 설계의 중요성
- 코드가 정말 길어지고 나니, 처음에 설계를 잘못했을 때 너무너무 큰 대가를 치르게 되었다.
- 맨 처음에 요구사항을 정확히 분석하고 완전한 설계를 해두어야 추후 문제가 없다.
백엔드 프로젝트의 준비물
- 자바, 스프링, JPA, 서버 사이드 템플릿(Thymeleaf), DB
백엔드 프로젝트의 구성
- resources : 프론트엔드 + 애플리케이션 설정 파일
- Java : 백엔드 전반
엔티티( Entity) & 빈(Bean)
- 1. 엔티티(Entity)
- 정의: 엔티티는 주로 데이터베이스 테이블에 매핑되는 객체입니다. 데이터베이스에서 특정 테이블과 일대일 매핑을 하여, 해당 테이블의 데이터를 객체로 다룰 수 있게 해줍니다.
- 용도: 엔티티는 주로 **JPA(Java Persistence API)**와 함께 사용되며, 데이터베이스의 데이터를 객체지향적으로 처리하는 역할을 합니다.
- 예를 들어, @Entity 어노테이션을 사용하여 JPA 엔티티 클래스를 정의하면, 이 클래스는 데이터베이스 테이블과 연관됩니다.
- 엔티티 클래스는 객체 상태와 데이터베이스 상태 간의 매핑을 담당합니다. 즉, 객체의 필드 값이 데이터베이스의 열(column)과 매핑됩니다.
- 특징:
- 데이터베이스와 연결되어 있으며, 데이터의 저장, 조회, 수정, 삭제 등의 작업을 할 수 있습니다.
- 일반적으로 @Entity 어노테이션으로 클래스가 엔티티로 선언됩니다.
- 엔티티는 보통 영속성 관리의 대상이 되어 JPA나 Hibernate가 객체의 생명 주기를 관리합니다.
- 정의: **빈(Bean)**은 Spring에서 사용되는 객체로, Spring IoC(제어의 역전) 컨테이너에 의해 관리되는 객체입니다. Spring에서는 Bean을 관리하고 생성하는 방식으로 객체 간의 의존성을 관리합니다.
- 용도: 빈은 애플리케이션의 구성 요소로, 객체의 생성, 의존성 주입(DI), 생명주기 관리 등을 Spring 컨테이너가 담당합니다.
- Spring 컨테이너에 의해 관리되므로, 애플리케이션에서 필요한 객체를 명시적으로 생성하거나 관리할 필요 없이 Spring이 자동으로 빈을 관리하고 주입합니다.
- 빈은 애플리케이션의 비즈니스 로직을 담당하는 서비스나 컴포넌트 클래스일 수 있습니다.
- 특징:
- 빈은 @Component, @Service, @Repository, @Controller 등의 어노테이션을 사용하여 선언할 수 있습니다.
- Spring IoC 컨테이너는 이러한 빈들을 자동으로 관리하고, 의존성 주입을 통해 필요한 곳에 제공해 줍니다.
영속성
영속성의 개념
영속성은 객체 지향 프로그래밍(OOP)에서 메모리 상의 객체가 영구 저장소(주로 데이터베이스)에 저장되는 과정과 관련이 있습니다. 즉, 프로그램의 실행이 종료되더라도 데이터가 계속해서 유지될 수 있게 하는 것을 의미합니다.
JPA에서의 영속성
**JPA(Java Persistence API)**에서 영속성은 객체가 데이터베이스 테이블과 매핑되어 데이터베이스에 저장되거나, 수정되고, 삭제되는 과정을 관리하는 기능입니다. JPA는 자바 애플리케이션에서 데이터베이스와의 상호작용을 객체 지향적으로 처리할 수 있게 해주는 API입니다.
JPA 영속성의 주요 개념
JPA에서는 **엔티티 객체(Entity Object)**를 사용하여 데이터를 저장하고, 이 엔티티 객체들이 **영속성 컨텍스트(Persistence Context)**라는 환경 내에서 관리됩니다. 영속성 컨텍스트는 영속성 상태를 관리하는 메모리 내의 저장소로, JPA가 객체와 관계형 데이터베이스 간의 매핑을 관리합니다.
JPA를 사용한 이유
- 객체 중심 설계를 지원해 코드의 생산성과 유지보수성을 높임.
- SQL 대신 메서드 호출로 데이터베이스 작업을 처리하여 간결한 코드 작성 가능.
- 영속성 컨텍스트를 통해 1차 캐시, 지연 로딩 등 최적화된 데이터 관리 제공.
- JPQL로 객체 중심의 쿼리 작성 가능.
- 다양한 데이터베이스와 독립적인 표준 API로 확장성과 호환성 보장.
- 자동화된 데이터베이스 매핑으로 개발 시간 단축.
- 변경 감지 및 트랜잭션 관리 기능으로 안정적인 데이터 처리가능.
JPA가 어노테이션인 이유
테스트 환경 생성
- 단순한 코드의 경우 그냥 수정할 수 있지만, 복잡한 코드가 될 수록 수정에 신중해야한다. 그래서 test코드를 작성하여 컴파일 해보면서 문제가 없는지, 버그는 없는지, 제대로 동작하는지 테스트 하는 것이 중요하다.
- 문론 테스트 코드도 유지보수를 해야하기 때문에 의미있는 테스트 케이스를 작성해야한다.
- 서버에 올리는 코드는 에러가 없어야한다. 즉, 이 과정은 정말 중요한 과정이다.
@Query와 Querydsl
- JPA에서 SQL 쿼리를 작성하는 2가지 대표적인 방법이다.
- 쿼리는 데이터베이스에서 원하는 데이터를 조회하거나 조작하기 위한 명령어를 말합니다.
1. @Query
@Query는 JPA 리포지토리에서 제공하는 어노테이션을 사용하여 JPQL(Java Persistence Query Language) 또는 네이티브 SQL 쿼리를 작성할 수 있게 해줍니다.
장점
- 간단하고 직관적: SQL이나 JPQL을 직접 작성하기 때문에, 쿼리가 간단하고 직관적입니다. SQL에 익숙한 개발자라면 바로 사용할 수 있습니다.
- 구현이 쉬움: 쿼리를 메소드에 어노테이션으로 추가할 수 있어서 코드 작성이 간단하고 빠릅니다.
- 복잡한 쿼리도 가능: JPQL이나 네이티브 SQL로 복잡한 쿼리를 작성할 수 있기 때문에, SQL에 대한 제어가 가능합니다.
- 쿼리 작성 시 강력한 최적화 가능: SQL을 직접 작성할 수 있어 데이터베이스에 최적화된 쿼리를 작성할 수 있습니다.
단점
- 쿼리 재사용이 어려움: 쿼리를 여러 곳에서 사용할 경우, 쿼리가 중복될 수 있어 유지보수가 어렵습니다.
- 쿼리 복잡도 증가: 복잡한 동적 쿼리를 작성할 때, 여러 조건을 동적으로 처리하는 것이 번거로울 수 있습니다.
- 타입 안정성 부족: 문자열로 쿼리를 작성하기 때문에 컴파일 타임에 쿼리가 잘못 작성되었는지 확인할 수 없습니다. 즉, 쿼리 문법이나 컬럼명이 잘못된 경우 런타임에 오류가 발생할 수 있습니다.
- 컴파일 시점에서 에러가 안나온다.
2. Querydsl
Querydsl은 자바 코드로 SQL 쿼리를 작성할 수 있게 해주는 라이브러리입니다. 타입 안전성을 제공하며, 쿼리를 빌더 방식으로 동적으로 생성할 수 있습니다.
장점
- 타입 안전성: 컴파일 타임에 쿼리를 검증할 수 있어, 잘못된 필드명이나 잘못된 쿼리 문법에 대해 오류를 미리 확인할 수 있습니다.
- 동적 쿼리 작성 용이: 여러 조건을 기반으로 동적으로 쿼리를 생성할 수 있어 복잡한 쿼리를 유연하게 작성할 수 있습니다.
- 쿼리 재사용 용이: Querydsl을 사용하면 쿼리를 객체 지향적으로 작성할 수 있어, 코드 재사용과 유지보수가 용이합니다.
- 자동 완성 지원: IDE에서 자동 완성 기능을 제공하므로, 쿼리 작성 시 실수를 줄일 수 있습니다.
단점
- 설정과 초기 학습 곡선: Querydsl을 프로젝트에 통합하는 데 다소 시간이 걸리며, 초기 설정이 복잡할 수 있습니다.
- 추가 의존성: Querydsl을 사용하려면 추가 라이브러리나 빌드 설정이 필요하므로 프로젝트에 의존성이 늘어날 수 있습니다.
- 가독성 저하: 자바 코드로 SQL을 작성하기 때문에, 단순한 쿼리에서는 오히려 가독성이 떨어질 수 있습니다. 복잡한 쿼리를 작성할 때 코드가 길어질 수 있습니다.
결론
- @Query는 단순하고 빠른 개발을 위해 좋습니다. 작은 프로젝트나 복잡하지 않은 쿼리에서는 매우 유용하며, 기존 SQL 문법에 익숙한 개발자에게 적합합니다.
- Querydsl은 동적이고 복잡한 쿼리를 작성할 때 유리합니다. 타입 안전성과 재사용성을 제공하므로, 대규모 프로젝트나 복잡한 비즈니스 로직을 구현할 때 더 효과적입니다.
Thymeleaf를 사용한 이유
+ Thymeleaf는 Java 기반의 서버 사이드 템플릿 엔진으로, 주로 Spring Framework와 함께 사용됩니다. HTML, XML, JavaScript, CSS 등의 파일을 동적으로 렌더링 (데이터를 가공)할 수 있는 템플릿 시스템입니다.
= 컨트롤러에서 데이터 처리 -> 타임리프가 템플릿화 -> 스프링이 데이터 전송
1. 자연스러운 템플릿(Natural Templates):
- 타임리프: HTML 파일을 템플릿 엔진 없이 열어도 유효한 HTML로 보이고, 동적 데이터가 서버에서 렌더링됩니다. 디자이너와 개발자가 협업하기 용이합니다.
- 다른 엔진 (예: Freemarker, Velocity): HTML 구조와 템플릿 문법이 혼합되어 있기 때문에, 템플릿 파일을 직접 브라우저에서 열면 정상적인 HTML로 보이지 않습니다. 또한, HTML 파일을 비전문가와 협업하기 어려울 수 있습니다.
2. 강력한 표현식 언어:
- 타임리프: 조건문, 반복문, 텍스트 출력 등 다양한 표현식 기능을 제공하며, HTML 내에서 쉽게 사용할 수 있습니다. 특히, 속성 값을 처리할 때 유연하고 직관적입니다.
- 다른 엔진: 다른 템플릿 엔진들도 조건문, 반복문 등을 제공하지만, 타임리프처럼 HTML 속성 내에서 직접 사용할 수 있는 방식은 아닙니다. 예를 들어, Freemarker는 <#if>나 <#list>와 같은 태그를 사용해야 하며, Velocity는 $!{}와 같은 특수 문법을 사용합니다. 타임리프는 이러한 문법을 덜 사용하고, HTML 내에서 자연스럽게 사용할 수 있습니다.
3. Spring과의 통합성:
- 타임리프: Spring과 매우 잘 통합되며, Spring Boot에서 기본적으로 지원됩니다. Spring의 다양한 기능(모델 객체, 메시지 처리, 국제화 등)과 자연스럽게 결합할 수 있습니다.
- 다른 엔진: Freemarker와 Velocity도 Spring과 통합할 수 있지만, 타임리프만큼 자연스럽고 쉽지는 않습니다. 특히 Spring Boot와의 통합에 있어 타임리프는 기본 지원이므로 설정이 간단합니다.
4. 확장 가능성:
- 타임리프: 커스텀 디얼리티브나 프로세서를 만들어 확장이 가능하며, 새로운 태그나 속성을 쉽게 추가할 수 있습니다.
- 다른 엔진: Freemarker와 Velocity는 확장성도 있지만, 타임리프는 확장이 용이하고, 사용자가 직접 커스텀 태그를 추가할 때 좀 더 직관적이고 깔끔한 방식으로 구현할 수 있습니다.
5. 강력한 디버깅 기능:
- 타임리프: 템플릿 렌더링 시 오류 메시지를 상세히 제공하여 디버깅을 용이하게 합니다. 오류를 명확하게 알려줘서 개발자가 쉽게 문제를 찾을 수 있습니다.
- 다른 엔진: Freemarker나 Velocity는 디버깅 기능이 있지만, 타임리프처럼 직관적이고 명확한 오류 메시지를 제공하는 데는 부족할 수 있습니다.
6. 모듈화된 레이아웃 지원:
- 타임리프: 레이아웃을 모듈화할 수 있는 기능(th:replace, th:include)을 제공하여 코드 중복을 줄이고 유지보수성을 높입니다.
- 다른 엔진: Freemarker와 Velocity도 레이아웃을 모듈화할 수 있는 기능을 제공하지만, 타임리프의 th:replace, th:include 같은 방식은 더 직관적이고, HTML 속성으로 처리할 수 있어 코드 작성이 용이합니다.
7. 보안:
- 타임리프: 기본적으로 HTML 이스케이프 기능이 제공되어 XSS(교차 사이트 스크립팅)와 같은 보안 문제를 예방할 수 있습니다.
- 다른 엔진: Freemarker와 Velocity도 보안 기능을 제공하지만, 기본적으로 HTML 이스케이프 처리가 되지 않는 경우가 많습니다. 보안을 강화하려면 개발자가 별도로 처리해야 할 수 있습니다.
DTO 클래스
- Data Transfer Object의 약자로, 엔티티 객체를 그대로 사용하지 않고 데이터를 포장하여 원하는 값만 전달하기 위해 필요한 데이터 전송 담당 클래스
- View Layer와 DB Layer의 분리를 위해서, 엔티티 객체의 변경을 막기 위해서, 데이터베이스 설계 외부 노출을 방지하기 위해 등 보안과 효율적인 면을 위해서 사용하게 된다.
부트스트랩
- HTML, CSS, JavaScript로 구성된 오픈 소스 프론트엔드 프레임워크로, 웹 페이지나 웹 애플리케이션을 보다 빠르고 효율적으로 개발할 수 있도록 돕는 도구
- 타인이 만든 웹 디자인을 공유할 수 있는 페이지
- 백엔드는 프론트를 하는 경우도 많지만 일단은 웹 디자이너 역활은 못하기에... 이걸로 대체했다..
스프링 시큐리티
- 단순히 로그인 보안에 사용했다.
- 다만 여러 기능이 있는 만큼, 더 갈고 닦을 필요가 있어보인다.
- 내용은 단순히 검문 시스템 정도로 이해하면 편한 것 같다.
- 요청이 들어오면 요청에 대한 검사와 처리를 수행하는 메서드로 구성된다.
- 관리자와 비 관리자의 보안 관리는 다르게 들어가는데, 가장 큰 이유는 여기서 데이터 정보를 어디까지 허용할지 지정하기 때문
매핑
- 클라 - 서버 - DB는 서로 데이터를 보내거나 불러올때 계속 매핑을 해야한다.
- 간단히 서로 언어가 다르니 번역해야한다는 것, [ 사과 - 애플 - 링고 ] 이런식으로 언어가 다르다 보니 서로 번역하는 작업이 필요한데 이게 매핑이다.
- 매핑은 처음에는 언제 사용해야 하나 라는 생각이 들었는데, 그냥 클라, 서버, db 각각 내부에서 사용하는 변수, 상수가 아니면 싹다 매핑을 해야한다. = 서로 뭘 주고 받으면 매핑해야한다...
AJAX 요청에서 401 Unauthorized 상태 코드를 반환하는 이유
일반적으로 AJAX 요청은 페이지 리로드 없이 서버와 비동기적으로 데이터를 주고받기 위해 사용되기 때문(웹 페이지 일부만 업데이트해서 리로드 없어도 가능함)입니다. 즉, 브라우저가 페이지를 새로고침하지 않고도 서버와 데이터를 주고받을 수 있는 방식입니다. 이때, 인증되지 않은 상태일 경우 어떻게 처리할지에 대한 특별한 요구사항이 있을 수 있습니다.
이유:
- 페이지 리디렉션이 불가능하기 때문에:
- 일반적인 HTTP 요청에서는 인증이 필요할 경우, 사용자를 로그인 페이지로 리디렉션할 수 있습니다.
- 하지만 AJAX 요청은 페이지 리로드를 하지 않고 데이터를 주고받는 방식이기 때문에, 리디렉션을 처리할 수 없습니다.
- 만약 HTTP 401 Unauthorized 상태 코드 대신 로그인 페이지로 리디렉션하면, AJAX 요청을 보낸 클라이언트는 리디렉션을 처리하지 못하고, 예상하지 못한 동작이 발생할 수 있습니다. 예를 들어, 클라이언트는 로그인 페이지로 리디렉션된 후, 이를 다시 처리하기 위해 페이지를 새로고침해야 할 수 있습니다.
- AJAX 응답의 형식:
- AJAX 요청은 비동기적으로 서버와 통신하므로, 클라이언트는 서버로부터 데이터를 받아와서 페이지 내에서 처리합니다.
- 서버에서 401 Unauthorized 상태 코드를 반환하면, 클라이언트 측에서 이를 처리하고, 사용자에게 적절한 오류 메시지를 표시하는 등 후속 작업을 할 수 있습니다.
- 리디렉션을 대신하여, 클라이언트는 이 상태 코드를 처리하여 사용자를 로그인 페이지로 유도할 수 있습니다. 예를 들어, alert()으로 "로그인 필요" 메시지를 띄우거나, 로그인 페이지로 리디렉션하는 방식으로 처리할 수 있습니다.
+ 리디렉션(Redirection)은 웹에서 사용자가 특정 요청을 했을 때, 서버가 다른 URL로 사용자를 자동으로 보내는 방법을 의미합니다.
연관 관계 매핑 종류
- 매핑이 당연히 1:1이라 생각할 수 있지만, 아래처럼 일대다의 형태를 띄기도 한다. 이럴경우 리스트로 받아온다.
- 이 연관 관계 매핑을 잘 생각하고 매핑해야한다. 정보 이상하게 불러오면 처리고 뭐고 다 망해간다.
1. 단방향 관계 (Unidirectional)
- 한 엔티티에서 다른 엔티티를 참조하는 형태입니다.
- 다른 방향으로의 접근은 불가능하고, 하나의 엔티티에서만 연관된 엔티티에 접근할 수 있습니다.
2. 양방향 관계 (Bidirectional)
- 두 엔티티가 서로를 참조하는 형태입니다.
- 두 방향으로의 접근이 가능하며, 이를 설정하기 위해 mappedBy를 사용하여 연관 관계를 설정합니다.
연관 관계 매핑 종류
1. One-to-One (1:1 관계)
- 한 엔티티가 다른 엔티티와 1:1 관계를 맺는 경우입니다.
- 예시: 한 사람은 하나의 여권만 가질 수 있다.
2. One-to-Many (1:N 관계)
- 한 엔티티가 여러 엔티티를 참조하는 경우입니다.
- 예시: 하나의 게시글에는 여러 댓글이 있을 수 있다.
3. Many-to-One (N:1 관계)
- 여러 엔티티가 한 엔티티를 참조하는 경우입니다.
- 예시: 여러 댓글은 하나의 게시글에 속한다.
4. Many-to-Many (N:M 관계)
- 여러 엔티티가 서로 다대다 관계를 가지는 경우입니다.
- 예시: 여러 학생은 여러 과목을 수강할 수 있다.
영속성 전이
- 엔티티의 상태를 변경할 때 해당 엔티티와 연관된 엔티티의 상태 변화를 전파시키는 옵션을 말한다.
- 이때 부모는 One에 해당하고 자식은 Many에 해당한다.
- 예시로 Order엔티티 삭제 - 연관된 다른 엔티티 삭제 / Order엔티티를 저장할때 포함된 다른 엔티티도 저장되는 경우
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
고아 객체의 삭제
부모 엔티티와 연관 관계가 끊어진 자식 엔티티를 말하는 것으로, 영속성 전이 기능과 같이 사용하면 부모 엔티티를 통해서 자식의 생명주기를 관리할 수 있다.
- 다만 고아 객체는 위의 영속성 전이와 같이 다른 곳에 영향을 줄 수 있다는 점에서 삭제에 유의해야한다.
- 고아 객체가 하나의 참조만 하고 있다면 삭제가 가능하지만, 그게 아니라면 어떤 변수가 발생할지 모르기에 삭제가 불가능 하다.
- 예시 : orphanRemoval = true라고 하면 만약 주문 항목(부모) 삭제시, 항목들도 데이터 베이스에서 삭제된다.
지연 로딩
일반적으로 로딩을 시전하면 DB 특정 항목의 모든 데이터를 불러온다. 이러한 대참사를 막기 위해 있는 것이 지연 로딩 방식이다. 지연 로딩은 데이터를 실제로 필요할 때까지 로딩을 지연시키는 방식이다. 즉 관련된 엔티티나 컬렉션이 실제로 사용되기 전까지는 DB에서 불러오지 않는다는 것.
Auditing을 이용한 엔티티 공통 속성 공통화
Auditing = Spring Data Jpa에서 제공하는 엔티티가 저장 or 수정될 때 자동으로 등록일,수정일,등록자,수정자를 입력해주는 기능을 말한다. 실제 영어 뜻도 '감시하다'의 의미를 가지고 있다.
- 문론 위의 정보 중 필요한 정보만 자동 저장할 수 있게 만들 수 있다.
애플리케이션 실행 상태에서 테이블 수정
일반적으로 소스를 작성하면서 애프릴케이션을 재실행하면 테이블을 삭제하고 다시 만들기 때문에 코드를 실행한 이후에 저장된 데이터는 삭제된다. 이 과정을 해결하기 위해 application.prperties의 dll-auto 속성을 validate로 변경하면 애플리케이션 실행 시점에 테이블을 삭제한 후 재생성하지 않으면 엔티티와 테이블이 매핑이 정상적으로 되어 있다.
= 디버깅 중에 테이블 내용을 수정할 수 있다.
Hibernate의 ddl-auto 속성
hibernate.hbm2ddl.auto는 Spring Data JPA에서 데이터베이스 테이블을 자동으로 관리하는 방법을 지정하는 설정입니다. 애플리케이션을 실행할 때, 이 설정에 따라 데이터베이스의 테이블이 어떻게 처리될지 결정됩니다.
여기서 validate, update, create, create-drop 값들이 중요한데, 각각 어떤 동작을 하는지에 대해 간단히 설명해볼게요.
문제의 핵심:
- 테이블 삭제 후 재생성:
- 기본적으로 **create**나 **create-drop**을 설정하면, 애플리케이션이 시작될 때 데이터베이스의 테이블이 삭제되고 새로 생성됩니다. 이때 기존에 저장된 데이터는 모두 삭제됩니다.
- validate로 설정하면?:
- hibernate.hbm2ddl.auto=validate로 설정하면, 애플리케이션이 시작될 때 기존 테이블을 삭제하거나 새로 만들지 않습니다.
- 대신, 데이터베이스의 테이블 구조가 애플리케이션의 엔티티 클래스와 잘 매핑되어 있는지 확인합니다. 만약 테이블 구조가 엔티티 클래스와 일치하지 않으면 애플리케이션이 예외를 발생시키며 실행되지 않습니다.
- 즉, 엔티티와 데이터베이스 테이블이 잘 매핑되어 있다면 테이블은 변경되지 않고, 데이터도 유지됩니다.
spring.jpa.hibernate.ddl-auto= create
-----------------------------------------
spring.jpa.hibernate.ddl-auto= validate
화면이 너무 복잡하고 얽힌 데이터가 많으면
Vue.js 프레임워크를 사용해보자
- 데이터가 변하면 해당 데이터를 보여주는 영역에 뷰도 자동으로 바뀌고, 데이터가 변하는 걸 감시하고 있다가 이벤트를 발생하기 쉽다.
- Vue.js는 반응형(Reactivity) 시스템을 제공합니다. 이 시스템 덕분에 데이터가 변경되면 해당 데이터를 사용하는 UI(뷰)가 자동으로 업데이트됩니다.
- 를 들어, 사용자가 데이터를 수정하거나 서버에서 데이터를 받아오면 Vue.js는 이 데이터를 감시하고 있다가, 데이터가 변경될 때마다 관련된 UI 요소를 자동으로 갱신합니다.
- 이는 상태 관리와 UI 갱신을 자동으로 해주기 때문에, 개발자는 UI를 직접 수정할 필요 없이 데이터만 수정하면 화면이 자동으로 반영됩니다.
- 그러니까 변형의 자동 인지와, 관련된 UI를 자동으로 업데이트 해준다는 것
네트워크 생명주기 모델
1. 네트워크 생명주기 (요청-응답 흐름)
위 코드가 작동하는 전체 네트워크 생명주기는 아래와 같이 설명됩니다.
① 요청 (Request)
- 클라이언트(브라우저 또는 JavaScript)는 서버로 요청을 보냅니다.
- URL: /order (POST 요청)
- 데이터: JSON ({ "itemId": 1, "count": 2 })
- 방식: AJAX를 통해 비동기적으로 전달.
② 처리 (Processing)
- 컨트롤러 (OrderController)
- @PostMapping("/order") 메서드가 요청을 받습니다.
- @RequestBody를 통해 JSON 데이터를 Java 객체(OrderDto)로 매핑.
- 유효성 검사 결과(BindingResult)를 확인하고, 서비스 계층 호출.
- 서비스 (OrderService)
- 비즈니스 로직을 처리하며, 데이터베이스 접근 및 주문 처리.
- 처리 결과로 주문 ID를 반환.
③ 응답 (Response)
- 컨트롤러가 처리 결과를 JSON 형태로 반환:
- ResponseEntity<Long>로 반환된 주문 ID를 JSON으로 변환.
- 클라이언트는 AJAX의 성공 콜백 함수에서 이를 처리.
④ 클라이언트 반응
- 클라이언트는 서버에서 받은 JSON 데이터를 활용하여 화면 업데이트:
- 주문 완료 메시지 표시.
- 주문 ID와 관련된 정보를 화면에 출력.
2. 요청-응답 간 상호작용 요약
- 클라이언트 → 서버:
AJAX로 JSON 데이터를 서버에 전달 (@RequestBody). - 서버 → 클라이언트:
처리 결과를 JSON 형태로 반환 (@ResponseBody).
3. AJAX 사용의 장점
- 페이지 새로고침 없이 실시간 업데이트 가능.
- 사용자 경험(UX)을 크게 개선.
- 요청-응답 간 데이터 크기를 줄여 효율성 증가.
4. 코드 흐름에 AJAX가 통합되는 구조
- 프론트엔드에서 주문 요청 시 AJAX를 호출.
- 백엔드 컨트롤러와 서비스 계층이 데이터 처리.
- 응답 데이터를 클라이언트가 받아 사용자 인터페이스(UI) 업데이트.
+ json = 클라이언트, 서버 통신시 사용되는 경량형 데이터 형식 (map 구조)
+ AJAX = 클라이언트 ,서버 통신시 비동기 통신을 가능하게 해주는 웹 기술 (프로토콜 아님)
프론트와의 통신
- 맵핑은 기본적으로 서버에서 진행한 다음 db나 클라에게 보낸다.
- $(".custom-file-input"):
- 의미: 이 코드는 jQuery를 사용하여 클래스 이름이 custom-file-input인 HTML 요소들을 선택하는 코드입니다.
- $(".custom-file-input")는 HTML 문서 내에서 클래스가 custom-file-input인 모든 요소를 찾아 조작하거나 스타일을 적용할 수 있게 합니다.
- 예를 들어, 파일 선택 버튼을 커스터마이즈할 때 자주 사용됩니다.
- $("#searchBtn"):
- 의미: 이 코드는 jQuery를 사용하여 아이디가 searchBtn인 HTML 요소를 선택하는 코드입니다.
- $("#searchBtn")는 id="searchBtn"인 요소를 선택하여 해당 요소를 조작할 수 있습니다. 일반적으로 버튼 클릭 이벤트를 다룰 때 사용됩니다.
- 예를 들어, 검색 버튼을 클릭했을 때 검색 기능을 활성화하는 용도로 사용될 수 있습니다.
- th:href="@{/css/layout1.css}":
- 의미: 이 코드는 Thymeleaf 템플릿 엔진을 사용하여 HTML 링크 태그의 href 속성을 동적으로 설정하는 코드입니다.
- th:href는 Thymeleaf의 특수 속성으로, 페이지가 렌더링될 때 href 속성을 해당 URL로 변환합니다. @{}는 해당 URL을 프로젝트의 루트 경로를 기준으로 계산해줍니다.
- 예를 들어, @{/css/layout1.css}는 /css/layout1.css라는 경로로 CSS 파일을 참조하는 링크를 만듭니다. 이 경로는 애플리케이션의 컨텍스트 경로를 자동으로 고려하여 적절하게 해석됩니다.
- th:
- 의미: th는 Thymeleaf 템플릿 엔진에서 사용하는 네임스페이스의 접두어입니다. Thymeleaf는 HTML을 렌더링할 때 동적 데이터를 삽입하거나 처리할 수 있게 해주는 서버 사이드 템플릿 엔진입니다.
- th 접두어는 Thymeleaf 특수 속성을 나타내며, 예를 들어 th:href, th:text, th:src와 같은 속성을 사용할 수 있습니다. 이는 HTML 속성에 동적 값을 삽입하거나 변환할 때 사용됩니다.
- th:text="${message}": message 변수에 담긴 값을 텍스트로 삽입합니다.
- th:src="@{${imagePath}}": imagePath 변수를 경로로 변환하여 이미지 소스를 설정합니다.
+추가사항+
1. 트랜잭션 관리 (Transaction Management)
- 트랜잭션은 데이터베이스에서 일련의 작업들이 일관성 있게 처리되도록 보장하는 메커니즘입니다. 예를 들어, 여러 데이터베이스 작업이 하나의 큰 작업을 구성할 때, 작업 중 하나가 실패하면 전체 작업이 롤백되어야 합니다.
- Spring에서는 @Transactional 어노테이션을 사용하여 트랜잭션을 관리할 수 있습니다. 트랜잭션이 적용되면 메서드 실행이 끝나기 전에 모든 DB 작업이 성공적으로 처리되거나 롤백됩니다.
- 트랜잭션 전파, 격리 수준, 예외 처리 등도 고려해야 할 중요한 부분입니다.
2. 캐시 (Cache)
- 캐싱은 애플리케이션 성능을 최적화하는 중요한 기법입니다. 자주 조회되는 데이터를 메모리에 저장해두고, 데이터베이스 접근을 최소화하는 방법입니다.
- Spring에서는 @Cacheable, @CacheEvict 등의 어노테이션을 활용해 쉽게 캐시를 적용할 수 있습니다.
- Redis나 Ehcache와 같은 외부 캐시 시스템을 연동하여 성능을 크게 향상시킬 수 있습니다.
3. API 설계 (RESTful API)
- RESTful API는 HTTP를 통해 자원을 CRUD(Create, Read, Update, Delete) 방식으로 처리하는 API 설계 방법론입니다.
- RESTful API 설계 시 **HTTP 메서드(GET, POST, PUT, DELETE 등)**의 사용법과 상태 코드(예: 200 OK, 404 Not Found 등)를 정확하게 이해하고 활용하는 것이 중요합니다.
- Spring에서는 @RestController를 사용하여 REST API를 쉽게 구현할 수 있습니다.
4. 로깅 (Logging)
- 로깅은 애플리케이션의 상태를 기록하고, 오류나 문제 발생 시 이를 추적하는 데 중요한 역할을 합니다.
- SLF4J와 Logback을 사용하여 로그를 관리하고, 로그의 레벨을 적절히 설정하여 개발, 테스트, 프로덕션 환경에서 로그를 효과적으로 사용할 수 있습니다.
- 로그 추적을 통해 성능 병목이나 오류를 빠르게 파악할 수 있습니다.
5. 보안 (Security)
- Spring Security를 사용하여 로그인, 인증, 권한 관리 등 다양한 보안 기능을 구현할 수 있습니다.
- CSRF, XSS, 세션 관리 등과 같은 웹 애플리케이션 보안 문제를 고려해야 합니다.
- 인증과 권한 처리를 통해 사용자가 수행할 수 있는 작업을 제한하고, 민감한 정보에 대한 접근을 제어합니다.
6. 배포와 CI/CD (Continuous Integration / Continuous Deployment)
- 애플리케이션을 CI/CD 파이프라인을 통해 자동으로 빌드하고 배포하는 시스템을 구축하면, 배포 시 오류를 최소화하고 효율성을 높일 수 있습니다.
- Jenkins, GitHub Actions, GitLab CI 등을 사용하여 자동화된 빌드 및 배포 프로세스를 설정할 수 있습니다.
7. 단위 테스트(Unit Testing)
- JUnit과 Mockito를 사용하여 단위 테스트를 작성하면, 코드 변경이 기존 기능에 영향을 미치지 않는지 확인할 수 있습니다.
- 테스트 주도 개발(TDD, Test-Driven Development)을 통해 코드 품질을 높이고, 버그를 사전에 예방할 수 있습니다.
8. API 문서화 (API Documentation)
- Swagger와 같은 도구를 사용하여 API 문서를 자동으로 생성할 수 있습니다.
- Springfox 또는 Springdoc OpenAPI를 활용하여 API 문서화가 용이하며, 팀원들과의 협업 시 API 사용법을 명확하게 전달할 수 있습니다.
9. 비동기 처리 (Asynchronous Processing)
- 비동기 작업 처리는 시간 소모적인 작업을 별도의 쓰레드에서 처리하여 애플리케이션의 응답성을 높이는 데 유용합니다.
- Spring에서는 @Async 어노테이션을 사용하여 비동기 메서드를 처리할 수 있습니다.
10. 로그인 및 세션 관리 (Session Management)
- 세션 관리는 사용자가 로그인 상태를 유지하도록 하는 기능입니다. JWT (JSON Web Token)와 같은 토큰 기반 인증 시스템을 활용하여 분산 환경에서도 세션을 관리할 수 있습니다.
- 세션 스토리지와 쿠키를 잘 활용하여 사용자의 인증 상태를 안전하게 관리하는 방법을 이해해야 합니다.
'Project > Spring' 카테고리의 다른 글
Spring Querydsl 과제 회고 (1) | 2025.01.27 |
---|---|
[Spring] IOC & DI (0) | 2025.01.23 |
스프링 NEWSFEED 협업 프로젝트 (1) | 2024.12.27 |
일정표를 만들어 보자! 업데이트! (2) | 2024.12.19 |
일정표를 만들어 보자! (2) | 2024.12.09 |