JPA(Java Persistence API)

Java 객체와 DB 엔티티(테이블) 자체를 그대로 매핑해서 처리할 수 있는 접근 방식을 채택한 새로운 기술표준

JPA의 접근 방식은 ORM(Object-Relational Mapping) 기술을 의미한다. 즉, 객체와 데이터베이스 간의 매핑 기술을 의미, Java 개발자가 좀 더 객체지향 관점에서 개발할 수 있게 하고, 개발을 용이하게 해주어서 DB와 Java간의 불일치를 해소해 준다.

MyBatis와 다르게 SQL 문의 작성이 불필요하며 ORM 내부적으로 java 메소드에 적합한 SQL 문이 자동으로 생성이 되어 실행되게 된다. Java 개발자는 클래스만 만들어서 사용하고, ORM 프레임워크가 자동으로 관련된 SQL을 만들어 준다고 한다.

그래서 찾아봤는데
자동으로 SQL을 만들어 준다고 했으니 설정 값을 어떻게 해야하나..?

spring:
  jpa:
    hibernate:
      ddl-auto: update  # or create

 

update 또는 create 옵션을 사용하면 JPA가 엔티티 기반으로 테이블을 자동으로 생성해준다고 한다. => DBeaver에서 수동으로 테이블을 만들 필요없음!

그동안에는 직접 테이블을 생성하고 연결했는데 이렇게 되면 테스트 데이터도 프로젝트 실행 시 자동으로 데이터 삽입도 가능하게 된다.

근데 주의해야할 점은 복잡한 쿼리를 만들어야 하는데 여러 테이블을 Join해서 데이터 결과를 가져와야 하는 경우에, JPA로는 복잡한 쿼리를 만드는 데는 용이하지 않음

뭐.. 일단 JPA로 사용하다가, 복잡해질때는 MyBatis를 같이 사용해보자 가능하다고 함!

사실 어떻게 쓰이는지 배우려고 적용하는거니 거기에 의미를 두자

 

 


@Entity
@Table(name = "member")  // 테이블명 지정
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 기본키 자동 생성
    private Long id;

    @Column(nullable = false, unique = true, length = 50)
    private String loginId;

 

이렇게 해서 JPA 사용하고 있고,

잘들어갔나 DBeaver에서 SELECT * FROM member; 해서 확인해봤는데

 

잘 매핑되는 것은 확인되었지만, 카멜 표기법으로 작성한 속성이 자동으로 login_id 처럼 변환되는 것을 확인할 수 있다. 혹시 나중에 에러가 발생할 수 있으니 이 점을 잘 기억해두고, 만약 'DB 속성값이 일치하지 않는다'는 에러가 발생하면 1순위로 확인해 보자

테스트 데이터 자동 삽입

@Component
public class DataInitializer implements CommandLineRunner {

    @Autowired
    private MemberRepository memberRepository;

    @Override
    public void run(String... args) throws Exception {
        if (memberRepository.count() == 0) {  // 기존 데이터가 없을 때만 실행
            memberRepository.save(Member.builder()
                    .loginId("user01")
                    .name("김민준")
                    .email("minjun01@example.com")
                    .password("password123")
                    .authLevel(1)  // 일반 사용자
                    .build());

 

확인 완료!!

HHH90000025: PostgreSQLDialect does not need to be specified explicitly using 'hibernate.dialect'

 

application.yml에서 hibernate 설정을 제거해서 해결
Hibernate 6.x 이상에서는 PostgreSQL이 자동으로 감지되므로 설정이 불필요하다.

 

spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering.

 

open-in-view 설정이 기본적으로 true로 되어있어서, View 렌더링 중에도 데이터베이스 쿼리가 실행될 수 있음 / yml에서 비활성화하면 View 렌더링 중 발생할 수 있는 LazyInitializationException 와 같은 문제를 방지할 수 있다.

LazyInitializationException은 데이터베이스에서 가져온 객체를 나중에 필요한 부분만 로드하는 Lazy Loading (지연 로딩) 기능을 사용할 때, Spring이 DB 연결을 이미 끊어버린 상태에서 추가 데이터를 가져오려 할때 발생하는 에러

🚩진행순서

  1. 로그인 요청
    › 사용자가 React에서 로그인 정보를 입력하여 Spring Boot로 전송
    › Spring Security가 요청을 가로채고 입력받은 사용자 정보를 AuthenticationManager로 전달.
    › 인증 성공 시, 사용자 정보를 기반으로 JWT를 생성하여 React에 반환
    › 생성된 JWT는 HTTP-only 쿠키에 저장하도록 서버에서 설정
  2. JWT 저장 및 요청
    › React는 JWT를 직접 다루지 않고, 브라우저가 HTTP-only 쿠키에 저장된 JWT를 자동으로 관리
    › 이후 모든 API 요청 시, JWT가 쿠키를 통해 자동으로 서버로 전달됨
  3. Spring Security와 JWT 검증
    › Spring Security는 들어온 요청의 쿠키에서 JWT를 추출
    › 필터(JwtFilter)를 통해 토큰의 유효성을 검증
    › JWT가 유효하다면, 사용자 정보를 SecurityContext에 저장하여 인증된 상태로 처리
  4. 보호된 리소스 접근
    › 인증된 사용자는 Spring Security가 보호하는 URL에 접근 가능
    › Spring Security는 사용자 권한에 따라 접근을 허용하거나 차단
  5. 로그아웃 처리
    › 사용자가 React에서 로그아웃 요청 시, JWT를 삭제하여 인증 상태를 초기화
    › 필요 시 서버로 로그아웃 요청을 보내 세션을 무효화하거나 토큰 블랙리스트를 사용

 

JWT를 저장할 때 sessionStorage? localStorage? 쿠키?

JWT는 모바일이나 웹의 사용자 인증을 위해 사용하는 암호화된 토큰
JWT 정보를 request에 담아 사용자의 정보 조회, 수정 등의 작업을 수행할 수 있다.

이전 프로젝트에서는 보안 문제는 아예 생각 조차 못했는데... 이번에는 좀 더 깊이 생각해서 코드를 짜보고 싶다.

XSS(Crose Site Scripting), CSRF(Cross Site Request Forgery)
XSS는 악의적인 사용자가 악성 스크립트 삽입해서 사용자 브라우저에서 실행되도록 공격 기법
CSRF는 정상적인 request를 가로채 사용자의 의지와 무관하게 백엔드 서버에 변조된 request를 보내 악의적인 동작을 수행하는 공격 기법

쿠키에 저장하는 걸로, sessionStorage는 탭을 닫으면 정보가 사라져서 만드려는 사이트에 적합하지 않고, localStorage보다 쿠키가 나중에 확장한느 것까지 생각하면 적합하다고 판단 HTTP-only 쿠키는 javaScript로 접근할 수 없어 XSS 공격에 안전하며, 요청 시 쿠키가 자동으로 서버에 전달되므로, 클라이언트 코드가 간결해지고, 쿠키를 통해 세션과 비슷한 경험을 제공하되, 서버 상태를 저장하지 않아 확장성이 높음!


 

으아.. 처음보는 부분이 많아서 오래걸리다ㅠ
면접도 준비하느라 시간이 너무 부족하네ㅠ 이거.. 천천히 가도 되는건가.. 미쳐버리겠네

그래도 시간이 걸려도 꼼꼼하게 해야지..

node.js 설치

프로젝트 생성

React.js

cd src/main
yarn create react-app frontend		# frontend 디렉토리에 React 프로젝트 생성 및 필요한 의존성 설치
cd frontend   
yarn install
yarn start		# React 개발 서버 시작

node_modules 대신 Yarn Berry를 도입하는 이유

전에 프로젝트 진행했을때도 node_modules 파일이 너무 많아서 github에 올릴때나 다운받을때도 속도가 느린걸 경험해봤다.
(npm에서 구성하는 node_modules는 큰 디스크 공간을 차지한다.)

그래서 이번에는 yarn으로!

Yarn Berry는 프로그램 개발에 필요한 도구를 더 빠르고 효율적으로 관리하기 위한 패키지 관리 도구
기존 node_modules 방식은 파일이 많아 속도가 느리고 공간을 많이 차지했지만, Yarn Berry는 도구를 압축된 .zip파일로 저장해 설치 속도를 높이고 중복을 줄이며 디스크 공간을 절약한다. 또한 Zero-Install 기능으로 추가 설치 없이 바로 실행할 수 있고, Plug’n’Plan(PnP) 기술로 의존성을 깔끔하게 관리해 충돌 문제를 방지한다.

Spring Boot 와 React 연동

스프링 부트와 리액트가 통신할 수 있도록 설정

frontend/package.json에 proxy 설정

"proxy": "http://localhost:8080",

Axios 설치

react에서 REST API 호출을 위해 Axios를 설치

yarn add axios

 


 

폴더 구조도 진짜.. 어떻게 하면 좋을까

이전 프로젝트에서는 그냥 기능구현에만 집중하느라.. 그냥 배운대로 진행했었는데, 모델 훈련 시킬 때도.. 부족했고, 가독성이 너무 안좋았다.

어떻게 하면 다른 사람들이 봤을때도 쉽게 알아볼 수 있을까.. 서치해보니 백엔드와 프론트엔드 폴더를 따로 만들어서 각각 띄우는 방법..!

 

요렇게

 

 

CORS는 브라우저가 다른 도메인의 리소스에 접근하는 것을 제어하는 보안 메커니즘이다.

WebConfig로 CORS 설정하는 이유

WebConfig 클래스는 Spring의 WebMvcConfigurer를 사용하여 모든 API 엔드포인트(/api/**)에 대해 특정 origin에서의 요청을 허용할 수 있도록 설정

WebConfig를 사용하는 상황 => React는 localhost : 3000, Spring Boot는 localhost : 8080 브라우저가 서로 다른 origin 간의 요청을 차단하므로, CORS 설정이 필요하다.

REST API를 외부에서 호출해야 하는 경우 → 외부 서비스나 클라이언트가 API를 호출하려면 CORS 정책을 설정해야한다.

WebConfig 설정이 필요한 경우

  • React와 Spring Boot가 다른 포트에서 실행되는 경우
  • API를 외부에서 호출하도록 허용하려는 경우

프로젝트 기획

회사를 찾아보면서 Node.js, React 가 많이 보임.. 간단한 주제를 잡고 이 전에 좀 체계적으로 못했다면 작은 프로젝트로 기획, 설계, 개발, 테스트, 배포까지 좀 더 체계적으로 단기간에 진행해보자

목표는

  • 사람들이 간단히 이벤트를 등록하고 관리할 수 있는 웹 애플리케이션
  • 이벤트 이름, 날짜, 장소를 입력하고 등록된 이벤트를 목록으로 확인/삭제

프로젝트 설계

초기 기술 스택

배포환경 : 로컬(개발), AWS

 


 

 

일단 간단하게 이벤트 CRUD 할 수 있는거 만들고 확장하는 식으로 이거 만들어 두면 다른 프로젝트에도 넣을 수도(?) 있으니깐

  1. 이벤트 등록 -> 이름, 날짜, 장소 입력 및 저장 / 이벤트 조회 -> 등록된 이벤트 목록 조회 / 이벤트 삭제
  2. 이벤트 우선순위 저장
  • 단순히 등록하는 것을 넘어 각 이벤트에 우선순위를 설정
  • 오늘 할 일과 미래의 이벤트를 한 화면에 표시
  • 우선순위 높은 이벤트 강조

페이지 들어가면 로그인 창을 딱 보여주자, 로그인하면 바로 윗 내용으로
알림 및 카운트다운 -> 각 이벤트에 대해 사용자 지정 알림 설정 / 남은 시간 표시

확장

공유 이벤트 관리 -> 이건 게시글 만든 뒤 확장하고, 생성한 이벤트 링크 공유/ 친구나 팀원과 실시간으로 협업하여 이벤트 추가 / 삭제 -> 간단한 소셜 피드 ( 각 이벤트에 댓글 기능 추가)

 


 

캘린더...? 처럼 할껀가 중요한 이벤트는 색상이 진하고, 덜 중요한 이벤트는 옅은 색
버튼 클릭 시 애니메이션 효과 추가 ( 이벤트 추가 시 작은 성공 메시지 표시 )
반응형 웹으로 제작

간단한 대시보드 : 오늘, 이번주, 이번달, 일정 요약
개인화 설정 : 이벤트 색상 지정, 알림 방식 선택

+ Recent posts