GOORM-DEEP DIVE 백엔드 3회차 회고 DAY12

Cori1304·2025년 3월 13일
0

GOORM-DEEPDIVE

목록 보기
11/19

글을 쓰게된 배경

부트캠프에서 처음으로 java수업을 받고 있기에 기록하는게 좋다고 생각했고, 수업이 있는 날이면 매일 글을 쓰려고 합니다. 쵀대한 몰랐거나 필요하다고 생각되는 내용 위주로 기록할 예정입니다. (제가 게을러서 이러한 시도를 성공한 적이 없기에 이번 부트캠프 목표 중 1가지입니다. 할 수 있도록 화이팅!!)



DAO, DTO,

🟢 DAO(Data Access Object)는 데이터베이스에 직접 접근하여 CRUD(Create, Read, Update, Delete) 작업을 수행하는 객체로 SQL 쿼리 또는 ORM을 사용하여 데이터 조회 및 조작에 사용된다.
🟢 DTO (Data Transfer Object)는 계층 간(예: Controller ↔ Service ↔ Repository) 데이터를 전달하기 위한 객체로 불필요한 데이터를 제외하고 필요한 데이터만 전달하여 성능을 최적화하는 역할을 한다.

DAO 예제 코드

// ------- DAO 인터페이스 정의
public interface UserDao {
    User getUserById(int id);
    List<User> getAllUsers();
    void saveUser(User user);
    void updateUser(User user);
    void deleteUser(int id);
}

// -------- JDBC를 이용한 DAO 구현
public class UserDaoImpl implements UserDao {
    private Connection connection;

    public UserDaoImpl(Connection connection) {
        this.connection = connection;
    }

    @Override
    public User getUserById(int id) {
        String sql = "SELECT * FROM users WHERE id = ?";
        try (PreparedStatement stmt = connection.prepareStatement(sql)) {
            stmt.setInt(1, id);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()) {
                return new User(rs.getInt("id"), rs.getString("name"), rs.getString("email"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void saveUser(User user) {
        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
        try (PreparedStatement stmt = connection.prepareStatement(sql)) {
            stmt.setString(1, user.getName());
            stmt.setString(2, user.getEmail());
            stmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // updateUser, deleteUser도 같은 방식으로 구현 가능
}

DTO 예제 코드

// -------- DTO 정의
public class UserDTO {
    private int id;
    private String name;
    private String email;

    public UserDTO(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    // Getter만 제공하여 불변 객체로 유지
    public int getId() { return id; }
    public String getName() { return name; }
    public String getEmail() { return email; }
}

// ------ Entity 클래스와 변환 (DTO ↔ Entity)
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String name;
    private String email;
    private String password; // DTO에는 포함되지 않음

    public User() {}  // JPA 기본 생성자 필요

    public User(String name, String email, String password) {
        this.name = name;
        this.email = email;
        this.password = password;
    }

    // 엔티티를 DTO로 변환하는 메서드
    public UserDTO toDTO() {
        return new UserDTO(this.id, this.name, this.email);
    }
}

Repository는 DAO보다 더 추상적인 계층을 제공하여 도메인 로직과 데이터 액세스를 연결하는 역할을 한다.

비교 항목DAO (Data Access Object)Repository
역할SQL을 직접 다루며 데이터 액세스를 처리도메인 로직과 데이터 저장소를 연결
구현 방식SQL 또는 ORM을 사용하여 직접 구현Spring Data JPA 등으로 인터페이스 기반 자동 구현
SQL 관리직접 작성해야 함자동 생성 가능 (필요시 @Query로 작성)
유지보수성SQL 변경이 필요하면 직접 수정해야 함추상화된 인터페이스라 유지보수 용이

@Bean

@Bean은 Spring에서 객체(Bean)를 수동으로 생성하고 관리할 때 사용하는 애노테이션으로 보통 @Configuration 클래스 내부에서 정의되며, 해당 메서드가 반환하는 객체를 Spring 컨테이너가 관리하는 Bean으로 등록해서 사용한다.

@Configuration
public class ContextConfiguration {

    /* @Bean 어노테이션은 해당 메소드의 반환 값을 스프링 컨테이너에 빈으로 등록한다는 의미이다.
     * 이름을 별도로 지정하지 않으면 메소드 이름을 bean의 id로 자동 인식한다.
     * */
    @Bean(name="member")
    public MemberDTO getMember() {

        return new MemberDTO(1, "user01", "pass01", "홍길동");
    }
}

// ------ 
 public static void main(String[] args) {

        /* AnnotationConfigApplicationContext클래스를 사용하여 ApplicationContext를 생성한다.
         * 생성자에 @Configuration 어노테이션이 달린 설정 클래스의 메타 정보를 전달한다. */
        ApplicationContext context
                = new AnnotationConfigApplicationContext(ContextConfiguration.class);

        MemberDTO member = context.getBean("member", MemberDTO.class);

        System.out.println(member);
    }

AOP

AOP는 핵심 비즈니스 로직과 부가적인 기능(공통 관심사, Cross-Cutting Concern)을 분리하여 관리하는 프로그래밍 기법이다. 즉, 로깅, 트랜잭션 관리, 보안 검사 같은 공통 기능을 한 곳에서 관리하고, 여러 클래스에 적용할 수 있도록 도와주는 개념이다.

✅ @Before("execution(* 패키지명.클래스명.메서드(..))") → 특정 메서드 실행 전에 로깅 수행!

간단 예제

@Aspect // AOP 클래스 선언
@Component // 스프링 빈 등록
public class LoggingAspect {

    @Before("execution(* com.example.service.*.*(..))") // 특정 패키지의 모든 메서드 실행 전 적용
    public void beforeMethod() {
        System.out.println("[LOG] 메서드 실행 전 수행됩니다.");
    }
}

심화 예제

@Aspect
@Component
public class LoggingAspect {

    @Pointcut("execution(* com.ohgiraffers.section01.aop.*Service.*(..))")
    public void logPointcut() {}

    @Before("LoggingAspect.logPointcut()")
    public void logBefore(JoinPoint joinPoint) {

        System.out.println("Before joinPoint.getTarget() : " + joinPoint.getTarget());

        System.out.println("Before joinPoint.getSignature() : " + joinPoint.getSignature());

        if(joinPoint.getArgs().length > 0) {
            System.out.println("Before joinPoint.getArg()[0] : " + joinPoint.getArgs()[0]);
        }
    }

    @After("logPointcut()")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("After joinPoint.getSignature() : " + joinPoint.getSignature());
    }

    @AfterReturning(pointcut = "logPointcut()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("After Returning result : " + result);
    }

    @AfterThrowing(pointcut = "logPointcut()", throwing = "exception")
    public void logAfterThrowing(Throwable exception) {
        System.out.println("After Throwing exception : " + exception);
    }

    @Around("logPointcut()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {

        System.out.println("Around Before : " + joinPoint.getSignature().getName());

        /* 원본 조인포인트를 실행한다. */
        Object result = joinPoint.proceed();
        System.out.println("Around After : " + joinPoint.getSignature().getName());

        return result;
    }
}


배운점

  1. @Bean을 통해서 개발자가 아닌 spring이 객체를 관리하는 것은 효율적이고 복잡성을 낮출 수 있어서 도움이 될거라고 생각한다.
  2. AOP라는 개념은 처음이라서 현재도 너무 낮설지만 공통되는 부분을 손쉬게 관리할 수 있기에 좋다고 생각한다.
profile
개발 공부 기록

0개의 댓글

관련 채용 정보