Spring boot 43

RestAPI 주소 설계 규칙

1. 소문자를 사용한다.대문자는 때로 문제를 일으키는 경우가 있기 때문에 URI를 작성할 때는 소문자를 선호한다.❌http://dev-cool.tistory.com/users/Post-Comments⭕http://cocoon1787.tistory.com/users/post-comments 2.언더바(_) 대신 하이픈(-)을 사용한다.가독성을 위해 긴 Path를 표현하는 단어는 하이픈(-)으로 구분하는 것이 좋다.프로그램의 글자 폰트에 따라 언더바 문자는 부분적으로 가려지거나 숨겨질수 있다.❌http://dev-cool.tistory.com/users/post_comments⭕http://dev-cool.tistory.com/users/post-comments 3. 마지막에 슬래시(/)를 포함하지 않는..

Spring boot 2025.08.05

CORS (Cross-Origin Resource Sharing)란?

CORS (Cross-Origin Resource Sharing)= "다른 도메인에서 우리 서버로 요청을 보낼 수 있게 허용하는 정책" Origin(출처)이란?Origin = Protocol + Domain + Port 왜 CORS 문제가 발생할까?시나리오: React 앱에서 우리 API 호출플러터 앱(localhost:3000)에서 아래 주소로 요청 실행fetch('http://localhost:8080/api/boards') .then(response => response.json()) .then(data => console.log(data)); 브라우저의 보안 정책Same-Origin Policy: 같은 출처끼리만 통신 허용다른 출처 요청 차단: 보안을 위해 기본적으로 거부CORS 에러 발생:..

Spring boot 2025.08.05

SSR 개념과 CSR 개념 이해하기

1. SSR과 CSR 개념 이해하기SSR (Server-Side Rendering) - 지금까지 만든 방식SSR은 서버에서 사용자에게 보여줄 페이지를 모두 구성하여 사용자에게 페이지를 보여주는 방식이다. 즉, 서버로부터 완전하게 만들어진 html파일을 받아와 페이지 전체를 렌더링 하는 방식이다. 서버에서 완성된 HTML을 만들어서 보내주는 방식브라우저 요청 → 서버가 HTML 완성 → 완성된 페이지 전송 → 브라우저 표시 SSR의 특징서버에서 모든 작업 처리: 데이터 조회, HTML 생성, 페이지 완성새로고침 발생: 페이지 이동할 때마다 전체 페이지 새로고침템플릿 엔진 사용: Mustache, Thymeleaf 등으로 HTML 생성진행한 프로젝트 예시:@GetMapping("/board/{id}")pub..

Spring boot 2025.08.04

JPA 연관관계 정리

JPA에서 DB의 JOIN이 필요한 상황에서 엔티티의 연관관계를 설정해 데이터를 조회할 때, 즉시 로딩과 지연 로딩의 차이와 지연 로딩에서 발생할 수 있는 N+1 문제, 그리고 이를 해결하기 위한 방법 정리 JPA에서 데이터베이스의 JOIN이 필요한 상황에서 엔티티 간 연관관계를 설정하여 데이터를 조회할 수 있습니다. 이때, 연관된 데이터를 가져오는 방식으로 **즉시 로딩(Eager Loading)**과 **지연 로딩(Lazy Loading)**을 설정할 수 있습니다.즉시 로딩 (Eager Loading)엔티티를 조회할 때 연관된 데이터도 즉시 함께 조회합니다.예: @ManyToOne(fetch = FetchType.EAGER) 설정.장점: 한 번의 쿼리로 필요한 모든 데이터를 가져옴.단점: 불필요한 ..

Spring boot 2025.08.04

스프링 부트- 익명 블로그 만들기 버전6 (사용자 프로필 이미지 업로드 기능)

1. 파일 업로드의 핵심 개념 MultipartFile: Spring에서 파일 업로드를 처리하는 핵심 인터페이스enctype="multipart/form-data": 파일 전송을 위한 필수 폼 속성정적 리소스 매핑: 업로드된 파일을 웹에서 접근 가능하게 하는 방법2. 보안 고려사항 파일 크기 제한 (5MB)파일 타입 검증 (이미지만 허용)고유한 파일명 생성으로 충돌 방지3. 데이터베이스 설계 파일 경로만 저장 (파일 자체는 파일 시스템에 저장)NULL 허용 필드로 선택적 기능 구현application.yml 설정 추가server: servlet: encoding: charset: utf-8 force: true port: 8080# 2칸 공백, 탭키 절대 사용 금지!# 로그 설..

Spring boot 2025.08.04

스프링 부트- 익명 블로그 만들기 버전6 (게시글 페이징 처리)

1. JPA 페이징처리페이징: 많은 데이터를 한 번에 보여주지 않고, 페이지 단위로 나눠서 보여주는 방법.필요한 이유는?데이터가 많으면 느려지니까, 한 페이지에 3~10개씩만 보여줘서 빠르게!사용자가 한눈에 보기 편함.게시글 100개가 있으면, 1페이지에 10개씩 보여주고, 1, 2, 3... 페이지로 나눔.페이징: 많은 데이터를 한 번에 보여주지 않고, 페이지 단위로 나눠서 보여주는 방법.필요한 이유는?데이터가 많으면 느려지니까, 한 페이지에 3~10개씩만 보여줘서 빠르게!사용자가 한눈에 보기 편함.게시글 100개가 있으면, 1페이지에 10개씩 보여주고, 1, 2, 3... 페이지로 나눔. 20 / 10 = 2 페이지10 / 10 = 1 페이지11 / 10 = (실제 값 1.1) → 2 페이지25 ..

Spring boot 2025.07.31

스프링 부트- 익명 블로그 만들기 버전6 (댓글 삭제)

detail.mustache - 권한 확인 및 자바스크립트 코드 추가{{#replyOwner}} 🗑{{/replyOwner}} ReplyController - 삭제 요청 기능 추가// 댓글 삭제 기능 요청@PostMapping("/reply/{id}/delete")public String delete(@PathVariable(name = "id") Long replyId, @RequestParam(name = "boardId") Long boardId, HttpSession session) { User sessionUser = (User) session.getAttribute(Define.SESSION_USER);..

Spring boot 2025.07.31

스프링 부트- 익명 블로그 만들기 버전6 (OSIV 와 댓글 목록 만들어 보기)

Open Session in View (OSIV) 란?HTTP 요청 시작부터 응답 완료까지 데이터베이스 세션(연결)을 유지하는 패턴입니다. HTTP 요청 시작 ↓데이터베이스 세션 열기 ↓Controller 실행 ↓Service 실행 (트랜잭션 시작/종료) ↓View 렌더링 (DB 세션 유지) ← 지연 로딩 가능! ↓데이터베이스 세션 닫기 ↓HTTP 응답 완료 OSIV가 없다면?// Service에서 트랜잭션 종료 시 DB 연결도 종료Board board = boardService.findByIdWithReplies(id, sessionUser);// 뷰 렌더링 중 지연 로딩 시{{#board.replies}} // LazyInitializationException 발생..

Spring boot 2025.07.31

스프링 부트- 익명 블로그 만들기 버전6 (댓글 저장과 양방향 맵핑 설정)

단방향 매핑이란?단방향 매핑은 한쪽 엔티티에서만 다른 엔티티를 참조하는 관계입니다. 현재 우리 프로젝트의 단방향 매핑 예시// Reply 엔티티 (댓글)public class Reply { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "board_id") private Board board; // 댓글 → 게시글 참조 (단방향) @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; // 댓글 → 사용자 참조 (단방향)}// Board 엔티티 (게시글)public class Board { @ManyToOne(..

Spring boot 2025.07.31

스프링 부트- 익명 블로그 만들기 버전6 (댓글 엔티티 설계 및 샘플 데이터)

Replypackage com.tenco.blog.reply;import com.tenco.blog.board.Board;import com.tenco.blog.user.User;import com.tenco.blog.utils.MyDateUtil;import jakarta.persistence.*;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;import org.hibernate.annotations.CreationTimestamp;import java.sql.Timestamp;@Data@NoArgsConstructor@Table(name = "reply_tb")@Entitypublic class Reply { @..

Spring boot 2025.07.30