cd restapi
npm install
npm run dev
// 결과
> restapi@0.0.0 dev
> vite
VITE v6.3.5 ready in 848 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
시작 화면
// vite.config.js 파일
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default {
server: {
// 접속할 주소
proxy:{
"/api" :'http://localhost:8080'
}
}
}
BCrypt는 패스워드를 안전하게 암호화하기 위해 널리 사용되는 해시 함수 알고리즘입니다. org.mindrot.jbcrypt.BCrypt는 이 알고리즘을 자바에서 쉽게 사용할 수 있도록 제공하는 라이브러리로, 비밀번호를 해시하여 저장하고, 사용자가 로그인할 때 입력한 비밀번호가 기존 해시와 일치하는지 안전하게 비교할 수 있도록 hashpw()와 checkpw() 메서드를 제공합니다. 이 방식은 단방향 암호화로 복호화가 불가능하고, salt을 자동으로 적용하여 동일한 비밀번호라도 해시값이 달라지기 때문에 무차별 대입 공격(Brute-force)과 레인보우 테이블 공격에 강한 보안성을 갖습니다.
타임리프(Thymeleaf)는 자바 기반 웹 애플리케이션에서 사용되는 현대적인 서버 사이드 템플릿 엔진으로, HTML, XML, JavaScript, CSS 등 다양한 마크업 언어와 자연스럽게 통합됩니다. 특히 HTML 파일을 그대로 브라우저에서 열어도 구조를 유지할 수 있어 디자이너와 개발자가 협업하기에 유리하며, ${변수}나 th:text, th:if 같은 속성 기반 문법을 통해 동적인 화면 구성이 가능하고, Spring MVC와도 강력하게 통합되어 컨트롤러에서 넘겨준 데이터를 직관적으로 표현할 수 있습니다.
CREATE TABLE member (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(100) NOT NULL,
name VARCHAR(50) NOT NULL
);
application.properties는 Spring Framework에서 애플리케이션의 설정 정보를 정의하는 파일로, 서버 포트, 데이터베이스 연결 정보, 로깅 수준, 경로 설정 등 다양한 환경설정을 key-value 형태로 작성할 수 있습니다. 이 파일은 src/main/resources 디렉토리에 위치하며, Spring Boot는 이 파일의 설정값을 자동으로 읽어와 애플리케이션 구동 시 적용합니다. 이를 통해 코드 변경 없이 운영환경에 맞는 설정을 쉽게 관리할 수 있습니다.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.member.mapper.MemberMapper">
<insert id="save" parameterType="MemberDTO">
INSERT INTO members (username, password, name)
VALUES (#{username}, #{password}, #{name})
</insert>
<select id="findByUsername" resultType="MemberDTO">
SELECT * FROM members WHERE username = #{username}
</select>
<update id="update" parameterType="MemberDTO">
UPDATE members SET password = #{password}, name = #{name}
WHERE id = #{id}
</update>
</mapper>
MemberDTO.java
@Data는 Lombok 라이브러리에서 제공하는 애노테이션으로, 자바 클래스에 자주 사용하는 보일러플레이트 코드(boilerplate code)를 자동으로 생성해주는 매우 유용한 기능입니다. @Data가 자동 생성하는 요소는 아래와 같습니다.
Getter 메서드 (모든 필드에 대해)
Setter 메서드 (모든 필드에 대해 final이 아닌 경우)
toString() 메서드
equals() 및 hashCode() 메서드
@RequiredArgsConstructor (final 필드나 @NonNull 필드를 매개변수로 받는 생성자)
package com.example.member.dto;
import lombok.Data;
@Data
public class MemberDTO {
private int id;
private String username;
private String password;
private String name;
}
MemberMapper.java
@Mapper는 MyBatis 프레임워크에서 사용되는 애노테이션으로, 인터페이스가 SQL 매퍼임을 명시하는 데 사용됩니다. 이 애노테이션을 통해 MyBatis는 해당 인터페이스를 구현체로 인식하고, XML 매퍼 파일이나 어노테이션 기반 SQL과 연결하여 자동으로 매핑을 처리할 수 있습니다.
SQL Mapper 인터페이스 지정 @Mapper가 붙은 인터페이스는 MyBatis가 자동으로 프록시 객체를 생성하여, 실제 SQL 실행 코드를 자동으로 주입합니다.
Spring과의 통합 Spring Boot와 함께 사용할 경우, @Mapper를 사용하면 Mapper 인터페이스가 자동으로빈(bean)으로 등록되어 DI(의존성 주입)에 사용할 수 있습니다.
자바에서 클래스를 만들면 new로 객체를 직접 생성하지만 Spring에서는 필요한 객체를 직접 만들지 않고, Spring이 대신 만들어서 관리해줍니다. 이처럼 Spring 컨테이너가 만들어서 관리하는 객체를 "빈(Bean)"이라고 부릅니다.
@Component
public class MemberService {
public void print() {
System.out.println("회원 서비스 실행");
}
}
의존성 주입(DI: Dependency Injection)
어떤 클래스가 다른 클래스를 사용할 때, 그 객체를 직접 만들지 않고 Spring에게 주세요! 라고 요청하는 방식입니다. 이렇게 다른 객체를 필요한 시점에 자동으로 넣어주는 것을 의존성 주입(DI)이라고 합니다.
@Repository
public class MemberRepository {
public void save() {
System.out.println("회원 저장됨!");
}
}
@Service
public class MemberService {
// Spring이 이 부분을 자동으로 채워줌 (의존성 주입)
@Autowired
private MemberRepository memberRepository;
public void join() {
memberRepository.save();
}
}
MemberController.java
package com.example.member.controller;
import com.example.member.dto.MemberDTO;
import com.example.member.service.MemberService;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
@RequiredArgsConstructor
public class MemberController {
private final MemberService service;
@GetMapping("/login")
public String loginPage() {
return "login";
}
@PostMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password,
HttpSession session,
Model model) {
if (service.login(username, password, session)) {
return "redirect:/home";
} else {
model.addAttribute("error", "로그인 실패");
return "login";
}
}
@GetMapping("/register")
public String registerPage() {
return "register";
}
@PostMapping("/register")
public String register(MemberDTO member) {
service.register(member);
return "redirect:/login";
}
@GetMapping("/home")
public String home(HttpSession session, Model model) {
MemberDTO user = (MemberDTO) session.getAttribute("loginUser");
if (user == null) return "redirect:/login";
model.addAttribute("user", user);
return "home";
}
@GetMapping("/update")
public String updatePage(HttpSession session, Model model) {
MemberDTO user = (MemberDTO) session.getAttribute("loginUser");
if (user == null) return "redirect:/login";
model.addAttribute("member", user);
return "update";
}
@PostMapping("/update")
public String update(MemberDTO member, HttpSession session) {
service.update(member);
session.setAttribute("loginUser", member);
return "redirect:/home";
}
@GetMapping("/logout")
public String logout(HttpSession session) {
service.logout(session);
return "redirect:/login";
}
}
클래스에 있는 final 필드나 @NonNull이 붙은 필드에 대해 생성자(constructor)를 자동으로 생성해주는 Lombok 애노테이션입니다. 즉, 필수 필드만을 매개변수로 받는 생성자를 만들어줍니다.
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service
public class MemberService {
private final MemberRepository memberRepository;
}
위 코드는 Lombok이 아래 생성자를 자동으로 만들어줍니다
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
package com.example.member.service;
import com.example.member.dto.MemberDTO;
import com.example.member.mapper.MemberMapper;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {
private final MemberMapper mapper;
@Override
public boolean login(String username, String password, HttpSession session) {
MemberDTO member = mapper.findByUsername(username);
if (member != null && StringUtils.hasText(password) && password.equals(member.getPassword())) {
session.setAttribute("loginUser", member);
return true;
}
return false;
}
@Override
public void register(MemberDTO member) {
mapper.save(member);
}
@Override
public void update(MemberDTO member) {
mapper.update(member);
}
@Override
public void logout(HttpSession session) {
session.invalidate();
}
}
스프링(Spring)은 자바 플랫폼을 위한 오픈소스 프레임워크로, 객체 지향 설계를 기반으로 의존성 주입(DI)과 관점 지향 프로그래밍(AOP) 같은 기능을 통해 개발자의 생산성과 유지보수성을 높여주는 반면, 설정이 복잡하고 XML 설정 파일이나 자바 설정 클래스가 많이 필요하다는 단점이 있습니다. 이에 비해 스프링부트(Spring Boot)는 스프링을 더욱 쉽게 사용할 수 있도록 만든 확장 프레임워크로, 자동 설정(Auto Configuration)과 내장 톰캣, 스타터 의존성 관리 등을 통해 개발자가 빠르게 애플리케이션을 구축할 수 있도록 도와줍니다.
1. IntelliJ에서 Spring 프로젝트 만들기 (Spring Boot 기준)
1. 프로젝트 생성
IntelliJ 실행 → New Project 클릭
왼쪽에서 Spring Initializr 선택
SDK는 설치된 Java 버전 선택 (예: 17)
Project Metadata 입력:
Group: com.example
Artifact: myapp ← 프로젝트 이름
Next 클릭 후 필요한 Dependency 선택
Spring Web (웹 개발)
Spring Boot DevTools (자동 재시작)
Lombok (선택사항)
2. 프로젝트 구조
myapp/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/myapp/
│ │ │ ├── MyappApplication.java <-- 🔸 시작 클래스
│ │ │ ├── controller/ <-- 🔹 요청을 받는 클래스
│ │ │ ├── service/ <-- 🔹 비즈니스 로직 처리
│ │ │ └── repository/ <-- 🔹 DB 접근 계층 (JPA 등)
│ │ └── resources/
│ │ ├── static/ <-- 🔹 정적 파일 (HTML, CSS, JS 등)
│ │ ├── templates/ <-- 🔹 Thymeleaf 등의 템플릿 파일
│ │ └── application.properties <-- 🔸 설정 파일
│
├── build.gradle OR pom.xml <-- 의존성 관리 파일 (Gradle or Maven)
└── ...
MyappApplication.java
애플리케이션의 시작점 (@SpringBootApplication)
controller/
사용자 요청을 처리하는 클래스 (예: /hello)
service/
실제 로직 처리 (예: 계산, 비즈니스 처리)
repository/
데이터베이스와의 연결 담당 (JPA, MyBatis 등 사용)
static/
HTML, CSS, JS 같은 정적 파일 위치
templates/
뷰 템플릿 파일 (Thymeleaf 등) 위치
application.properties / yml
포트번호, DB연결 등 설정 파일
build.gradle or pom.xml
필요한 라이브러리(의존성)를 정의하는 곳
2. Gradle
Gradle은 자바를 비롯한 여러 프로그래밍 언어 프로젝트의 빌드 자동화 도구로, 코드 컴파일, 테스트, 패키징, 의존성 관리 등을 손쉽게 처리해주는 도구입니다. 기존의 Maven보다 더 빠르고 유연하게 동작하며, Groovy 또는 Kotlin DSL 문법을 사용해 빌드 스크립트를 작성합니다. Gradle은 필요한 라이브러리를 자동으로 다운로드하고, 프로젝트를 실행 가능한 형태(jar, war 등)로 만들어주는 역할을 하며, 특히 Spring Boot와 함께 사용할 때 매우 강력하고 편리한 도구로 널리 사용됩니다.
1. 파일 구조
myapp/
├── build.gradle <-- 🔸 가장 핵심적인 빌드 스크립트 파일
├── settings.gradle <-- 프로젝트 이름 설정
├── gradle/
│ └── wrapper/ <-- Gradle 버전 관리 및 자동 설치용
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew <-- 유닉스용 Gradle 실행 스크립트
├── gradlew.bat <-- 윈도우용 Gradle 실행 스크립트
2. build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0' // 스프링 부트 플러그인
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.example' // 그룹 ID (패키지명처럼 사용)
version = '0.0.1-SNAPSHOT' // 버전
java {
sourceCompatibility = '17' // 자바 버전 설정
}
repositories {
mavenCentral() // 라이브러리 다운로드 위치
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web' // 웹 기능
testImplementation 'org.springframework.boot:spring-boot-starter-test' // 테스트 기능
}
3. Lombok
Lombok은 자바 개발에서 반복적으로 작성해야 하는 코드를 자동으로 생성해주는 코드 간소화 라이브러리입니다. 예를 들어, 클래스에서 자주 사용하는 getter, setter, toString, equals, hashCode, 생성자 등을 직접 작성하지 않아도 @Getter, @Setter, @ToString, @AllArgsConstructor, @NoArgsConstructor 같은 Lombok 어노테이션만 붙이면 컴파일 시점에 자동으로 생성해줍니다. 이로 인해 코드가 훨씬 깔끔해지고, 유지보수도 쉬워지며, 특히 DTO나 Entity 클래스 작성 시 매우 유용하게 사용됩니다. 단, IDE에서 Lombok 플러그인을 설치해야 정상 동작하며, 빌드 도구(Gradle/Maven)에도 의존성을 추가해야 합니다.
// src/main/java/com/example/demo/User.java
package com.example.demo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class User {
private String name;
private int age;
}
4. JUnit
JUnit은 자바에서 가장 널리 사용되는 단위 테스트 프레임워크로, 메서드 단위로 코드를 테스트하고 검증할 수 있도록 도와주는 도구입니다. 개발자는 @Test 어노테이션을 통해 특정 메서드의 동작을 검증하고, assertEquals, assertTrue 같은 다양한 검증 메서드를 사용해 기대한 결과와 실제 결과를 비교할 수 있습니다. JUnit은 코드의 신뢰성과 유지보수성을 높여주며, 특히 TDD(테스트 주도 개발)나 CI/CD 환경에서 자동화된 테스트를 실행하는 데 필수적인 도구로 활용됩니다. 최근에는 JUnit 5가 주로 사용되며, 이전 버전보다 더 유연하고 확장 가능한 구조를 가지고 있습니다.
myapp/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/demo/
│ │ │ └── User.java <-- 💡 실제 클래스
│ └── test/
│ └── java/
│ └── com/example/demo/
│ └── UserTest.java <-- ✅ 테스트 클래스
UserTest.java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class UserTest {
@Test
void testUserGetterSetter() {
User user = new User();
user.setName("김사과");
user.setAge(25);
assertEquals("김사과", user.getName());
assertEquals(25, user.getAge());
}
}
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '3.5.0'
id 'io.spring.dependency-management' version '1.1.7'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
compileOnly 'org.apache.tomcat.embed:tomcat-embed-jasper'
runtimeOnly 'org.apache.tomcat.embed:tomcat-embed-jasper'
implementation 'javax.servlet:jstl:1.2'
}
HomeController.java
@Controller
public class HomeController {
@GetMapping("/home")
public String home() {
return "home"; // /WEB-INF/views/home.jsp 로 포워딩
}
}
home.jsp
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head><title>Home</title></head>
<body>
<h1>Hello, JSP from Spring Boot!</h1>
</body>
</html>
2. Thymeleaf
기본적으로 Spring Boot는Thymeleaf, Mustache, Freemarker 같은 템플릿 엔진과REST API + 프론트엔드 분리 구조를 선호합니다. 타임리프(Thymeleaf)는 HTML을 기반으로 작동하는 자바 서버 사이드 템플릿 엔진으로, Spring Boot와 매우 잘 통합되어 주로 웹 페이지를 동적으로 생성할 때 사용됩니다. 타임리프는 HTML 파일을 그대로 브라우저에서 열어도 깨지지 않는 정상적인 HTML 문서 형태를 유지하면서, ${변수}와 같은 표현식이나 th:if, th:each 같은 속성으로 데이터를 출력하고 조건/반복 처리 등을 할 수 있도록 도와줍니다. JSP보다 설정이 간편하고 HTML 디자이너와 개발자가 협업하기 쉬우며, 템플릿 캐시, 레이아웃 구성, 국제화(i18n) 등도 쉽게 지원하여 실무에서 널리 사용되고 있습니다.