[TIL][03.07] 메모리 캐싱, SQL 인젝션, MyBatis, ConnetionPool

2025. 3. 10. 03:59· [LG 유플러스] 유레카/Today I Learned
목차
  1. 메모리 캐싱을 활용한 불필요한 DB 조회 방지
  2. 기존 방식
  3. 변경된 방식
  4. SQL 인젝션
  5. SQL 인젝션 방어
  6. MyBatis
  7. Connection Pool
  8. 과제 (미니 프로젝트 도메인 생각하기)

초기 프론트 화면에서 정적인 정보를 제공하는 경우, 해당 정보를 프론트엔드에 직접 포함시키는 것이 효율적

넷플릭스처럼 사용자 맞춤 정보를 제공해야 하는 경우, DB에서 데이터를 가져와야 하므로 상대적으로 성능이 저하될 수 있음

메모리 캐싱을 활용한 불필요한 DB 조회 방지

기존 방식

새로고침 시마다 DB에서 데이터를 조회

package com.shop.cafe.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.shop.cafe.dto.Product;
import com.shop.cafe.service.ProductService;

@RestController
public class ProductController {
	
	@Autowired
	ProductService productService;
	
	@GetMapping("getAllProducts")
	public List<Product> getAllProducts() {
		try {
			return productService.getAllProducts();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
}
  • getAllProducts()가 새로고침 할 때마다 호출됨
  • 매번 productService.getAllProducts()를 실행하여 DB에서 데이터를 가져옴
  • 사용자가 페이지를 새로고침할 때마다 성능 부담이 증가함

변경된 방식

첫 호출 후 데이터를 저장하여 재사용

package com.shop.cafe.controller;

import java.util.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.shop.cafe.dto.Product;
import com.shop.cafe.service.ProductService;

@RestController
public class ProductController {
	
	@Autowired
	ProductService productService;
	
	Map<String, Object> storage = new HashMap();
	
	@GetMapping("getAllProducts")
	public List<Product> getAllProducts() {
		try {
			Object o = storage.get("firstPageProducts");
			if(o==null) {
				List<Product> list = productService.getAllProducts();
				storage.put("firstPageProducts", list);
				return list;
			}
			return (List<Product>)o;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
}
  • storage라는 **메모리 캐시(Map)**를 활용하여 데이터를 저장
  • 첫 번째 요청에서는 productService.getAllProducts()를 호출하고, 결과를 storage에 저장
  • 이후 요청에서는 storage에서 데이터를 가져와 DB 호출 없이 반환
  • 새로고침해도 DB를 다시 조회하지 않음 → 성능 향상
  • storage는 애플리케이션이 꺼지면 초기화
  • 새로운 데이터가 추가되거나 변경될 경우, 이를 갱신하는 로직 필요

SQL 인젝션

사용자가 입력한 데이터를 통해 SQL 쿼리의 구조를 조작하여 의도하지 않은 데이터 조회, 변경, 삭제 등을 수행할 수 있는 보안 취약점

ResultSet rs = stmt.executeQuery("SELECT * FROM member WHERE email = '"+ m.getEmail() +"' AND pwd = '" + m.getPwd() + "'");

위 코드처럼 문자열 연결 방식으로 SQL 쿼리를 만들면, 입력값에 따라 SQL 구조가 변경될 수 있음

{
    "email" : "' or ''='",
    "pwd" : "' or ''='"
}

예제 입력

SELECT * FROM member WHERE email='' OR ''='' AND pwd='' OR ''='';

실행되는 SQL : WHERE 조건이 항상 TRUE가 되어 모든 멤버 정보가 반환됨 → 보안 취약

SQL 인젝션 방어

PreparedStatement 사용

  • SQL 구조를 고정하고 데이터만 전달하여 SQL 인젝션 방어
  • function(email, pwd)처럼 실행됨
  • function안의 내용은 컴파일되어있기 때문에 구조가 변경되지 않음. 데이터만 전달함
  • 성능, 사용성, 보안 증가

MyBatis

  • Apache iBatis에서 발전하여 만들어진 SQL 매핑 프레임워크
  • SQL을 XML 또는 애노테이션으로 작성하여 직접 관리 가능
  • JDBC보다 편리한 SQL 작성 및 실행 지원
  • Connection Pool 제공으로 성능 최적화
@Mapper
public interface ProductDao {	
	public List<Product> getAllProducts() throws Exception;
}
  • @Mapper를 사용하여 MyBatis가 자동으로 생성
  • getAllProducts()는 SQL 매핑과 연결됨
<mapper namespace="com.shop.cafe.dao.ProductDao">
  <select id="getAllProducts" resultType="Product">
    select * from product limit 6
  </select>
</mapper>
  • namespace="com.shop.cafe.dao.ProductDao"
    → DAO 인터페이스와 연결
  • id="getAllProducts"
    → ProductDao.getAllProducts() 메서드와 매핑
  • resultType="Product"
    → 조회 결과를 Product 객체 리스트로 변환

Connection Pool

  • 데이터베이스(DB) 연결을 미리 생성하고 재사용하는 기법
  • 새로운 DB 연결(Connection)을 매번 생성하는 대신, 미리 생성된 연결을 풀(Pool)에 보관하고 필요할 때 가져다 사용
  • 클래스를 직접 생성하면 요청마다 새 연결이 필요 → 비효율적
  • 일정 개수의 DB 연결을 미리 생성하여 재사용
  • 요청이 들어오면 풀에서 연결을 할당
  • 요청이 끝나면 풀에 반환하여 대기
  • 성능 향상 및 자원 낭비 방지

과제 (미니 프로젝트 도메인 생각하기)

도메인 : 패션 플랫폼(ex. 무신사, w컨셉)

주요 엔티티 : Member, Brand, Product, Cart, Order, Payment

'[LG 유플러스] 유레카 > Today I Learned' 카테고리의 다른 글

[TIL][03.11] 세션 & 토큰 로그인, 토큰 수명 관리  (0) 2025.03.12
[TIL][03.10] XSS, 외래키, tabnabbing, 토큰, 로그인  (0) 2025.03.11
[TIL][03.06] @CrossOrigin, WebMvcConfigurer, 쿠키, 세션 스토리지, 로컬 스토리지, fetch, axios, jwt  (0) 2025.03.07
[TIL][03.05] secu.properties, MVC, 자원 자동 해제, 의존성 주입, Http Session  (0) 2025.03.06
[TIL][03.04] SQL, DISTINCT, WHERE, JOIN, MVC, Annotation, fetch, async/await  (0) 2025.03.05
  1. 메모리 캐싱을 활용한 불필요한 DB 조회 방지
  2. 기존 방식
  3. 변경된 방식
  4. SQL 인젝션
  5. SQL 인젝션 방어
  6. MyBatis
  7. Connection Pool
  8. 과제 (미니 프로젝트 도메인 생각하기)
'[LG 유플러스] 유레카/Today I Learned' 카테고리의 다른 글
  • [TIL][03.11] 세션 & 토큰 로그인, 토큰 수명 관리
  • [TIL][03.10] XSS, 외래키, tabnabbing, 토큰, 로그인
  • [TIL][03.06] @CrossOrigin, WebMvcConfigurer, 쿠키, 세션 스토리지, 로컬 스토리지, fetch, axios, jwt
  • [TIL][03.05] secu.properties, MVC, 자원 자동 해제, 의존성 주입, Http Session
leeemingyu
leeemingyu
leeemingyu
ye
leeemingyu

블로그 메뉴

  • GitHub
  • Instagram
    전체
    오늘
    어제
    • 전체보기 (68)
      • GDSC (4)
        • 실시간 채팅 구현 (4)
      • [LG 유플러스] 유레카 (63)
        • Today I Learned (37)
        • 코딩테스트 (22)
        • 프로젝트 (4)

    공지사항

    인기 글

    최근 댓글

    최근 글

    hELLO · Designed By 정상우.v4.2.2
    leeemingyu
    [TIL][03.07] 메모리 캐싱, SQL 인젝션, MyBatis, ConnetionPool
    상단으로

    티스토리툴바

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.