반응형

JPA(Java Persistence API)란?

JPA(Java Persistence API)는 자바 애플리케이션에서 관계형 데이터베이스를 쉽게 다룰 수 있도록 도와주는 ORM(Object Relational Mapping) 기술입니다. 개발자가 SQL을 직접 작성하지 않고도 객체를 통해 데이터베이스를 조작할 수 있도록 해줍니다. Hibernate, EclipseLink와 같은 구현체가 있으며, Spring Boot에서는 주로 Hibernate를 기본 JPA 구현체로 사용합니다.


@Entity 클래스: 데이터베이스 테이블과 1:1 매핑되는 클래스

@Entity는 JPA에서 엔티티 클래스를 선언할 때 사용하는 어노테이션으로, 해당 클래스가 데이터베이스의 테이블과 매핑됨을 나타냅니다.

예제:

import jakarta.persistence.*;

@Entity
@Table(name = "users") // 테이블 명 지정 가능
public class User {
    @Id // 기본 키 설정
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 자동 증가
    private Long id;

    @Column(nullable = false, length = 100)
    private String name;

    @Column(unique = true)
    private String email;
}

위 코드에서 @Entity를 통해 User 클래스가 users 테이블과 매핑됩니다. @Id는 기본 키, @Column은 필드에 대한 제약 조건을 설정하는 데 사용됩니다.


application.yml: 데이터 소스 및 JPA 설정

Spring Boot에서 데이터베이스 연결 및 JPA 설정을 위해 application.yml 파일을 사용합니다.

예제:

spring:
	datasource:
		url: jdbc:mysql://localhost:3306/mydb
		username: root
		password: secret
		driver-class-name: com.mysql.cj.jdbc.Driver
	jpa:
        hibernate:
	        ddl-auto: update # 애플리케이션 실행 시 테이블 자동 업데이트
        show-sql: true # 실행되는 SQL 출력
        properties:
    	    hibernate:
        		format_sql: true # SQL을 보기 좋게 포맷

위 설정은 MySQL 데이터베이스에 연결하고, Hibernate를 통해 JPA를 설정하는 방법을 보여줍니다.


레포지토리 인터페이스: JpaRepository를 상속받은 인터페이스

JPA에서 데이터베이스 조작을 쉽게 하기 위해 JpaRepository를 활용할 수 있습니다.

예제:

import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {
	Optional<User> findByEmail(String email); // 이메일로 사용자 검색
}

이렇게 JpaRepository<User, Long>을 상속받으면 기본적인 CRUD 메서드(findAll, save, delete 등)를 자동으로 제공받을 수 있습니다.


JPA 일대다 관계 설정

JPA에서 엔티티 간의 관계를 설정할 때 @OneToMany를 사용하여 일대다 관계를 정의할 수 있습니다.

예제:

@Entity
public class Team {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToMany(mappedBy = "team", cascade = CascadeType.ALL)
    private List<User> users = new ArrayList<>();
}

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToOne
    @JoinColumn(name = "team_id") // 외래 키 설정
    private Team team;
}

위 코드에서 Team 엔티티는 여러 User 엔티티를 가질 수 있으며, User 엔티티는 하나의 Team에 속합니다.


JPA 문법 종류

JPA에서는 다양한 문법을 지원하며, 주로 사용되는 기능들은 다음과 같습니다.

1. JPQL (Java Persistence Query Language)

JPQL은 SQL과 유사하지만, 엔티티 객체를 대상으로 쿼리를 작성하는 방법입니다.

@Query("SELECT u FROM User u WHERE u.name = :name")
List<User> findByName(@Param("name") String name);

2. Native Query (SQL 직접 사용)

JPA에서도 SQL을 직접 실행할 수 있습니다.

@Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)
User findByEmailNative(String email);

3. EntityManager 사용

JPA의 핵심 객체인 EntityManager를 활용하여 데이터베이스 조작이 가능합니다.

@PersistenceContext
private EntityManager entityManager;

public User findUser(Long id) {
	return entityManager.find(User.class, id);
}

마무리

JPA는 객체와 데이터베이스 간의 매핑을 쉽게 할 수 있도록 도와주는 강력한 기술입니다. @Entity 클래스를 활용하여 테이블을 정의하고, application.yml에서 설정을 관리하며, JpaRepository를 통해 데이터를 쉽게 조작할 수 있습니다. 또한, 일대다 관계 설정과 다양한 JPA 문법을 활용하여 보다 효율적인 데이터 처리를 할 수 있습니다.

JPA를 잘 활용하면 SQL 작성 부담을 줄이고 유지보수성을 높일 수 있으므로, 프로젝트에서 적극적으로 활용해보세요!

 

반응형
반응형

SQL Injection: 개념과 방어 방법

SQL Injection은 사용자가 입력한 데이터를 통해 데이터베이스에 비정상적인 SQL 쿼리를 주입하는 보안 취약점 공격입니다. 이를 통해 공격자는 데이터베이스의 민감한 데이터를 조회, 수정, 삭제하거나 시스템에 대한 제어권을 얻을 수 있습니다.

이 글에서는 SQL Injection의 개념과 바이패스 방법, 그리고 이를 방어하는 다양한 기법을 자바 예제와 함께 설명하겠습니다.


SQL Injection이란?

SQL Injection은 주로 다음과 같은 방식으로 발생합니다:

  • 입력값을 SQL 쿼리 문자열에 그대로 삽입하여 실행.
  • 쿼리의 논리를 변조하여 의도하지 않은 결과를 유도.

예시: 취약한 코드

String query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "';";

공격자가 usernameadmin' --를 입력하면 쿼리는 다음과 같이 변조됩니다:

SELECT * FROM users WHERE username = 'admin' -- ' AND password = '';

--는 SQL에서 주석 처리를 의미하므로 비밀번호 조건이 무시됩니다.


SQL Injection 바이패스 방법

SQL Injection 바이패스는 데이터베이스의 입력 검증과 로직을 우회하여 공격하는 기법입니다.

바이패스 방법 예시:

  1. 논리 우회:
    • 입력값에 논리 연산자(OR 1=1)를 삽입하여 조건을 항상 참으로 만듦.
    • 예: username=admin' OR 1=1 --
  2. 유효성 검사 우회:
    • 특수문자, 인코딩 기법을 활용하여 필터링 로직을 우회.
    • 예: admin' OR '1'='1 (문자열 비교 이용).
  3. 스키마 정보 노출:
    • UNION 쿼리를 사용하여 추가적인 데이터베이스 정보를 조회.
    • 예: admin' UNION SELECT null, username, password FROM users --

SQL Injection 방어 방법

SQL Injection을 방지하기 위해 다음 기법을 사용할 수 있습니다.

1. 입력값 검증

입력값을 철저히 검증하여 예상치 못한 입력을 필터링합니다.

예제:

String username = request.getParameter("username");
String sanitizedUsername = username.replaceAll("[^a-zA-Z0-9]", "");

2. SQL 로직 검증

SQL 쿼리 작성 시 논리적 오류가 발생하지 않도록 구조를 점검합니다.

예제:

if (username.contains("'") || password.contains("'")) {
	throw new IllegalArgumentException("Invalid characters in input");
}

3. Prepared Statement 사용

Prepared Statement는 파라미터화된 쿼리를 사용하여 SQL Injection 공격을 원천적으로 차단합니다.

Statement와의 차이점:

  • Statement: 쿼리와 데이터를 결합하여 실행.
  • Prepared Statement: 쿼리와 데이터를 분리하여 처리.

취약한 Statement 예제:

Statement stmt = connection.createStatement();
String query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "';";
ResultSet rs = stmt.executeQuery(query);

안전한 Prepared Statement 예제:

String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();

4. ORM (Object-Relational Mapping) 사용

JPA, Hibernate 같은 ORM 프레임워크를 사용하여 SQL 쿼리를 직접 작성하지 않고 객체 지향적으로 데이터베이스와 상호작용.

예제:

@Entity
public class User {
    @Id
    private Long id;
    private String username;
    private String password;
}

public User findByUsernameAndPassword(String username, String password) {
    return entityManager.createQuery(
    "SELECT u FROM User u WHERE u.username = :username AND u.password = :password", User.class)
    .setParameter("username", username)
    .setParameter("password", password)
    .getSingleResult();
}

마무리: SQL Injection 방어의 중요성

SQL Injection은 잘못된 입력값 처리를 통해 발생하는 심각한 보안 취약점입니다. 이를 방지하려면 입력값 검증, 로직 점검, 그리고 Prepared Statement와 같은 안전한 프로그래밍 기법을 활용해야 합니다. 보안을 염두에 두고 코드를 작성하는 습관을 들여 안전한 애플리케이션을 개발하세요!

 

반응형

'개발 부트캠프 > 백엔드' 카테고리의 다른 글

[Java] JSON  (0) 2025.01.16
[Java] HTTP 요청 처리하기  (0) 2025.01.16
[Java] 서블릿(Servlet)  (0) 2025.01.08
[Java] 계층형 아키텍처 패턴 (Layered Architecture Pattern)  (0) 2025.01.07
[Java] MVC 패턴  (1) 2025.01.07

+ Recent posts