SQL Injection
입력 데이터가 SQL의 구조를 바꾸는 취약점
ex) email과 pwd 값을 다음과 같이 입력하는 경우, SQL 쿼리가 의도한 대로 실행되지 않고 공격자가 원하는 방식으로 쿼리가 실행
String sql = "select * from member where email='" + m.getEmail() + "' and pwd='" + m.getPwd() + "'";
- 공격 예시
{
"email" : "' or ''='",
"pwd" : "' or ''='"
}
- 실행되는 SQL 쿼리
select * from member where email='' or ''='' and pwd='' or ''=''
➡️ 로그인 시스템에서 실제로 로그인 검증을 하지 않고 모든 사용자가 로그인되는 결과 !!
❌ Statement
- SQL 쿼리를 문자열로 직접 결합하기 때문에 SQL 인젝션 공격에 취약
String sql = "SELECT * FROM users WHERE email = '" + email + "' AND password = '" + password + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
✅ PreparedStatement
- 매개변수화된 쿼리를 사용하기 때문에 SQL 인젝션 공격을 예방할 수 있음
- 쿼리가 먼저 컴파일되고, 값은 나중에 바인딩되므로 쿼리의 구조가 변경되지 않음
String sql = "SELECT * FROM users WHERE email = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, email);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
Connection pool
로그레벨(log level)
커넥션 풀에서 로그 레벨은 커넥션 풀의 동작에 대한 정보를 기록하는 로그의 상세도를 설정하는 방식
- 로그 레벨은 커넥션 풀 내에서 발생하는 이벤트들(예: 커넥션 획득, 커넥션 반환, 커넥션 시간 초과 등)에 대해 어떤 정도로 자세히 기록할지 결정
🔥 커넥션 풀
DB와 연결된 커넥션 객체들을 미리 생성하여, 여러 애플리케이션이 필요할 때마다 재사용할 수 있도록 관리하는 시스템
매번 새로운 DB 커넥션을 만드는 것보다 미리 커넥션을 풀에 저장해두고 필요한 때에 빌려 쓰는 방식이 성능과 자원 관리에 유리
✔ 왜 커넥션 풀을 사용할까?
- 성능 향상: DB 연결을 반복적으로 생성/닫는 데 걸리는 시간이 줄어듦
- 자원 관리: 커넥션 수를 미리 설정하여 자원의 낭비를 줄임
- 동시 처리 성능 개선: 여러 쓰레드가 동시에 DB와 연결을 요청할 때 대기시간을 줄여줌
🔧 커넥션 풀의 동작
- 애플리케이션에서 DB 연결 요청.
- 커넥션 풀에서 사용 가능한 커넥션을 반환.
- 작업을 마친 후 커넥션을 풀에 반환.
- 커넥션이 만료되거나 유휴 상태로 있으면 닫을 수 있음.
☕️ HikariCP
Java에서 가장 빠르고 효율적인 커넥션 풀 라이브러리
- Spring Boot에서 기본 커넥션 풀로 사용됨
- 속도와 성능을 최우선으로 고려하여 설계된 커넥션 풀
🛋️ MyBatis
Java의 ORM(Object Relational Mapping) 프레임워크로, SQL을 작성을 편하게 만들어 줌
- 다른 ORM 프로임워크와 달리, SQL을 개발자가 직접 작성하고 이를 XML 파일에 매핑하여 사용하는 특징을 가짐
🔄 어떻게 함께 사용되나?
- MyBatis는 SQL을 직접 작성하여 데이터베이스와 상호작용
- HikariCP는 데이터베이스 연결을 관리하는 커넥션 풀을 제공하여, MyBatis가 DB에 빠르게 접근할 수 있도록 도와줌
- MyBatis는 SQL을 실행할 때, HikariCP에서 관리하는 커넥션 풀을 통해 효율적으로 DB 커넥션을 할당받고, 작업을 마친 후 커넥션을 풀에 반환
🛍️ 쇼핑몰 실습에 MyBatis 적용해보기
1️⃣ application.properties 설정
// ... 생략
logging.level.com.shop.cafe=debug // 로그 레벨을 설정
mybatis.type-aliases-package=com.shop.cafe.dto // MyBatis가 DTO 클래스들의 별칭을 자동으로 등록할 패키지를 지정
mybatis.mapper-locations=mapper/*.xml // MyBatis가 SQL 쿼리가 정의된 매퍼 XML 파일을 찾을 위치를 지정
2️⃣ Mapper XML 파일: SQL 쿼리 매핑을 위한 XML 파일을 작성
- src/main/resources/mapper/product.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shop.cafe.dao.ProductDao">
<select id="getAllProducts" resultType="Product" >
select * from product
</select>
</mapper>
- src/main/resources/mapper/member.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shop.cafe.dao.MemberDao">
<select id="login" resultType="Member" parameterType="Member" >
select * from member where email=#{email} and pwd=#{pwd}
</select>
<insert id="insertMember" parameterType="Member" >
insert into member(email, pwd, nickname) values(#{email}, #{pwd}, #{nickname})
</insert>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?> | XML 파일의 버전과 문자 인코딩을 지정 |
<!DOCTYPE mapper ...> | MyBatis Mapper XML 파일에서 사용할 DTD(문서 유형 정의)를 선언 |
<mapper namespace="com.shop.cafe.dao.MemberDao"> | Mapper의 namespace를 정의합니다. 이 XML 파일이 com.shop.cafe.dao.MemberDao 클래스와 연관이 있음을 나타냄 |
<select id="login" resultType="Member" parameterType="Member"> | <select> 태그는 SQL SELECT 쿼리를 정의 |
id="login" | SQL 쿼리를 호출할 메서드 이름을 지정, MemberDao 클래스에서 login 메서드를 호출하면 이 SQL이 실행 |
resultType="Member" | 쿼리 결과가 매핑될 Java 객체 타입을 지정, 여기서는 Member 객체로 매핑 |
parameterType="Member" | 쿼리의 파라미터 타입을 Member 객체로 지정, 여기서는 login 메서드에서 전달된 Member 객체의 email과 pwd 값이 SQL에 전달 |
3️⃣ Mapper 인터페이스: XML 파일에서 정의한 SQL을 호출하는 인터페이스를 작성
- com.shop.cafe.dao/ProductDao
package com.shop.cafe.dao;
import java.util.*;
import org.apache.ibatis.annotations.Mapper;
import com.shop.cafe.dto.Product;
@Mapper
public interface ProductDao {
public List<Product> getAllProducts() throws Exception;
}
- com.shop.cafe.dao/MemberDao
package com.shop.cafe.dao;
import org.apache.ibatis.annotations.Mapper;
import com.shop.cafe.dto.Member;
@Mapper
public interface MemberDao {
public Member login(Member m) throws Exception;
public void insertMember(Member m) throws Exception;
}
728x90
반응형
'LG 유플러스 유레카 SW > Spring' 카테고리의 다른 글
[#33] RESTful 방식 + Swagger 사용 (0) | 2025.03.14 |
---|---|
[#31] 토큰 인증 방식 (0) | 2025.03.11 |
[#30] XSS/Tabnabbing 공격 (0) | 2025.03.10 |
[#28] 쇼핑몰 연동 실습 - 다중 서버 세션 문제 해결 + 사용자 인증 (1) | 2025.03.06 |
[#27] 쇼핑몰 연동 실습 - 회원가입/로그인 (1) | 2025.03.05 |