목록2025/06 (30)
che01 님의 블로그
오늘 학습한 내용『이것은 컴퓨터과학이다』를 읽으며 컴퓨터가 어떻게 동작하는지 전체적인 흐름을 파악했다. 개별 부품의 역할보다는 정보가 어떻게 흘러가고 처리되는지에 집중해서 정리해보았다.컴퓨터는 추상화의 산물컴퓨터는 여러 계층으로 이루어진 복잡한 구조다. 우리가 작성하는 코드 한 줄이 실제로 실행되기까지는 다음과 같은 과정을 거친다:고급 언어 코드 → 컴파일러 변환 → 기계어 → CPU 명령어 실행 → 전기 신호각 단계마다 복잡한 처리 과정이 숨어있지만, 상위 계층에서는 하위 계층의 복잡함을 신경 쓰지 않아도 된다. 이것이 바로 추상화의 힘이다.정보 처리의 전체적인 흐름컴퓨터에서 정보가 처리되는 과정을 단계별로 정리하면:입력: 사용자가 키보드나 마우스로 명령을 입력변환: 프로그래밍 언어로 작성된 코드가 컴..
DTO 프로젝션이란?데이터베이스에서 필요한 필드만 선택해서 조회하고, 그 결과를 DTO 객체에 바로 매핑하여 반환하는 방법이다. 엔티티 전체를 조회하는 대신 원하는 데이터만 가져와 성능을 최적화할 수 있다.사용하는 이유성능 최적화불필요한 필드를 제외하고 필요한 데이터만 조회네트워크 트래픽 감소메모리 사용량 절약응답 최적화API 응답에 필요한 정보만 포함클라이언트 처리 속도 개선민감한 정보 노출 방지코드 가독성복잡한 조인 결과를 명확한 DTO로 표현비즈니스 로직과 데이터 구조 분리QueryDSL에서 DTO 프로젝션 방법1. Projections.fields() - 필드 이름 기반 매핑List results = queryFactory .select(Projections.fields( Tod..
결론QueryDSL에서 leftJoin()을 사용할 때 항상 fetchJoin()이 필요한 것은 아니다. DTO 프로젝션으로 조회하는 경우에는 N+1 문제가 발생하지 않는다.상황별 N+1 문제 발생 여부1. 엔티티 직접 조회 - N+1 발생함List todos = queryFactory .selectFrom(todo) .leftJoin(todo.managers, manager) // fetchJoin 없음 .fetch();// 연관 객체 접근 시 N+1 발생for (Todo t : todos) { t.getManagers().size(); // 각 Todo마다 추가 쿼리 실행}2. DTO 프로젝션 조회 - N+1 발생하지 않음List result = queryFactory ..
Spring에서 페이징을 처리하는 방법은 크게 두 가지가 있다. 각각의 특징과 사용법을 정리해보자.1. 전통적인 방식 - @RequestParam 직접 받기컨트롤러에서 page와 size 파라미터를 직접 받아서 처리하는 방식이다.특징컨트롤러에서 page, size를 직접 파라미터로 받음defaultValue를 통해 기본값 지정 가능Pageable 객체를 직접 생성해서 서비스에 전달코드 예시@GetMapping("/todos")public ResponseEntity> getTodos( @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size) { Pageable pageable = PageR..
트랜잭션 롤백 정책트랜잭션에서 어떤 예외가 발생했을 때 롤백을 진행할지 결정하는 정책입니다.예외 종류 복습체크예외(Exception): 컴파일 시점에 처리해야 하는 예외언체크예외(RuntimeException): 런타임에 발생하는 예외기본 롤백 정책스프링에서는 기본적으로 RuntimeException이 발생했을 때만 rollback을 진행합니다. 체크예외는 기본적으로 rollback하지 않습니다.롤백 정책 설정rollbackFor특정 예외를 rollback 정책에 추가할 때 사용체크예외도 rollback 대상으로 만들 수 있음noRollbackFor특정 예외를 rollback 정책에서 제거할 때 사용RuntimeException이어도 rollback하지 않도록 설정 가능@Transactional(roll..
MyBatis나 JPA 기본 쿼리로 복잡한 검색 조건 만들기가 너무 어려웠다문자열로 쿼리 작성하다가 오타가 나면 실행해봐야 알 수 있어서 불편했는데, QueryDSL은 컴파일 시점에 오류를 잡아준다동적 쿼리 작성이 훨씬 편리하다처음 설정하면서 겪은 시행착오들build.gradle에 의존성 추가implementation 'com.querydsl:querydsl-jpa:5.0.0'annotationProcessor 'com.querydsl:querydsl-apt:5.0.0'Q클래스 생성을 위한 설정 (필수)def querydslDir = "$buildDir/generated/querydsl"sourceSets { main.java.srcDirs += [querydslDir]}configurations ..
Self-invocation problem은 스프링에서 같은 클래스 내부의 메서드를 호출할 때 발생하는 문제다. AOP나 프록시가 적용된 메서드를 같은 클래스 안에서 직접 호출하면, 프록시를 거치지 않아서 의도한 기능이 동작하지 않는다.왜 발생하나?스프링은 객체를 프록시로 감싸서 AOP 기능을 제공한다. 하지만 같은 클래스 내부에서 메서드를 호출할 때는 this.method()로 호출하게 되는데, 이때 this는 프록시 객체가 아닌 실제 객체를 가리킨다. 그래서 프록시를 거치지 않아 AOP가 동작하지 않는다.실제 예제문제가 되는 코드@Servicepublic class UserService { @Transactional public void updateUser(Long userId) {..
기본 개념Statement는 SQL 문자열을 직접 작성해서 DB에 전송하는 방식이다. 매번 새로운 SQL 문자열을 조합해서 실행한다.PreparedStatement는 SQL 템플릿을 미리 준비하고, 나중에 값만 바인딩하는 방식이다. ? 플레이스홀더를 사용해 값을 동적으로 할당한다.보안성Statement의 SQL Injection 취약점String userInput = "admin' OR '1'='1' --";String sql = "SELECT * FROM users WHERE username = '" + userInput + "'";Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(sql);// 실제 실행되는 SQL:// ..
문제 상황JWT 기반 인증 시스템에서 인증 제외 URL에 대한 처리 로직이 JWT 필터와 Spring Security 설정에 중복으로 구현되어 있었고, 이로 인해 토큰이 필요 없는 요청에서 예상치 못한 예외가 발생하는 문제가 있었습니다.주요 증상인증이 필요 없는 API에 요청 시 "토큰이 필요하다"는 예외 발생AuthenticationEntryPoint로 도달하지 못하고 JWT 필터에서 예외 처리됨JWT에도 인증제외 URL 로직을 구현 했었음원인 분석문제의 핵심은 책임 분리의 실패였습니다.잘못된 예외 처리 시점: JWT 필터에서 토큰 검증 실패 시 바로 예외를 발생시켜 Spring Security의 정상적인 인증 플로우를 방해Spring Security 아키텍처 이해 부족: 인증 실패는 Authent..
JPA Auditing 핵심 정리1. 기본 기능: 생성/수정 날짜 자동 기록@CreatedDate : 엔티티가 생성될 때 자동으로 현재 시각을 기록@LastModifiedDate : 엔티티가 수정될 때 자동으로 현재 시각을 기록이 기능들을 사용하려면 다음 3가지가 필요엔티티(또는 부모클래스)에 @EntityListeners(AuditingEntityListener.class) 붙임스프링 부트 메인 클래스나 설정 클래스에 @EnableJpaAuditing 붙여서 기능 활성화날짜 필드는 LocalDateTime 타입 등으로 선언이게 어떻게 가능한가?@EnableJpaAuditing → 기능 활성화Spring Boot가 실행될 때, 이 어노테이션을 통해 JPA Auditing 기능을 켭니다.이걸 켜면 Spri..