코딩/자바

[Spring] 기초 6주차

yoney 2025. 1. 23. 15:08

✏️ Layered Architecture


컨트롤러의 책임이 너무 많아서 3가지 계층으로 나눈다.

 

구조

  • Presentation Layer
    • 사용자의 요청을 받고 응답하는 역할을 수행한다.
    • 화면을 응답하거나 데이터를 응답하는 API를 정의한다.
  • Business Layer(Service Layer)
    • 비지니스 로직을 수행한다.
    • 요청을 해석하여 Repository Layer에 전달한다.
    • 일반적으로 하나의 비지니스 로직은 하나의 트랜잭션으로 동작한다.
  • Data Access Layer(Repository Layer)
    • 데이터베이스와 연동되어 실제 데이터를 관리한다.

👉🏻 결국은 그냥 controller, service, repository로 나눈다는 것

 

 

 

  • 용어 설명
    • DTO(Data Transfer Object)
      • 계층간 데이터 전달을 위해 사용되는 객체이다.
      • 요청 데이터를 처리하는 객체는 일반적으로 RequestDto로 명명한다.
      • 응답 데이터를 처리하는 객체는 일반적으로 ResponseDto로 명명한다.
    • Model
      • Entity
        • 추후 숙련주차에 배울 JPA와 관련이 있다.
        • JPA에서는 Entity라는 형태로 데이터를 반환한다.
    • DAO(Data Access Object)

✏️ Database


DBMS

데이터베이스를 관리하고 운영하는 시스템 어플리케이션에서 DBMS에 데이터를 요청하면 DBMS에서 관리하는 DB에서 데이터를 가져와 응답한다.

 

  • DBMS의 종류
    1. 관계형 DMBS(RDBMS) 중요!
      • 가장 많이 사용하는 데이터베이스
      • 데이터를 테이블 형태로 구조화하여 저장하고 관리하는 시스템이다.
      • 테이블 간의 관계를 이용해 데이터를 연결한다.
      ex) Oracle, MySQL, PostgreSQL, Microsoft SQL Server 등
    2. 비관계형 DBMS(NoSQL)
      • 테이블이 아닌 key-value, document, graph 등의 다양한 형태로 데이터를 저장하고 관리한다.
      • 스키마가 고정되지 않고, 대규모 데이터 처리와 높은 확장성을 제공한다.
      ex) MongoDB, Cassandra, Redis 등
    3. 다중 모델 DBMS
      • 하나의 데이터베이스 관리 시스템에서 여러 데이터 모델을 지원하는 시스템이다.
      • 동일한 DBMS에서 관계형 데이터뿐만 아니라 문서형, 그래프형 데이터를 함께 관리할 수 있다.
      ex) Amazon DynamoDB, Microsoft Azure Cosmos DB 등

트랜잭션

DB에서 하나의 논리적인 작업단위. 트랜잭션으로 묶여있는 작업들은 모두 성공적으로 완료되거나 하나라도 실패하면 전체가 취소된다.

 


sql 종류

 

  1. DDL(Data Definition Language)
    • 데이터베이스 구조를 정의하는 데 사용된다.
    • CREATE
      • 새로운 데이터베이스 및 테이블을 생성한다.
    • ALTER
      • 기존 데이터베이스 및 테이블 구조를 수정한다.
    • DROP
      • 데이터베이스 및 테이블을 삭제한다.
  2. DML(Data Manipulation Language)
    • 데이터베이스의 데이터를 조작하는 데 사용된다.
    • INSERT
      • 데이터를 테이블에 삽입한다.
    • UPDATE
      • 테이블의 기존 데이터를 수정한다.
    • DELETE
      • 테이블의 데이터를 삭제한다.
  3. DQL(Data Query Language)
    • 데이터베이스에서 데이터를 검색하는 데 사용된다.
    • SELECT
      • 데이터를 조회한다. 특정 조건을 추가할 수 있다.
  4. DCL(Data Control Language)
    • 데이터베이스의 권한을 관리하는 데 사용된다.
    • GRANT
      • 사용자에게 권한을 부여한다.
    • REVOKE
      • 사용자의 권한을 회수한다.
  5. TCL(Transaction Control Language)
    • 여러 DML 작업을 하나의 논리적 단위로 묶어 트랜잭션으로 처리하는 데 사용된다.
    • COMMIT
      • 트랜잭션이 성공한 것을 데이터베이스에 알리고 모든 변경 사항을 영구적으로 저장한다.
    • ROLLBACK
      • 트랜잭션 중 발생한 모든 변경 사항을 취소하고, 데이터베이스를 트랜잭션 시작 시점의 상태로 되돌린다.

JDBC의 주요 특징

  1. 표준 API
    1. 대부분의 RDBMS (관계형 데이터베이스 관리 시스템)에 대한 드라이버가 제공되어 여러 종류의 DB 대해 일관된 방식으로 상호 작용할 수 있다.
    ex) Database 종류가 바뀌어도 쿼리문이 실행된다. MySQL → ORACLE
  2. 데이터베이스 연결
  3. SQL 쿼리 실행
  4. Prepared Statement
  5. 결과 집합 처리(Result Set)
    1. 데이터베이스로부터 반환된 결과 집합을 처리할 수 있다.
    ex) 데이터를 조회하고 결과를 Java 객체로 매핑할 수 있다.
  6. 트랜잭션 관리
    1. JDBC를 사용하여 데이터베이스 트랜잭션을 시작, 커밋(성공) 또는 롤백(실패)하는 등의 트랜잭션 관리 작업을 수행할 수 있습니다.

Mybatis

  • SQL 쿼리들을 XML 파일에 작성하여 코드와 SQL을 분리하여 관리되도록 만들어준다.
  • SQL과 Java Code의 분리가 핵심
  • Query를 JAVA에서 XML로
    • 복잡한 JDBC 코드가 사라진다.
    • ResultSet과 같이 결과값을 맵핑하는 객체가 없다.
    • 설정이 간단하다.
    • 관심사를 분리한다. → SQL 을 따로 관리한다.
    • XML 안에있는 SQL을 Java의 메소드에 매핑해준다.
  • MyBatis 장점
    1. 자동으로 Connection 관리를 해주면서 JDBC 사용할 때의 중복 작업 대부분을 없애준다.
    2. DB 결과 집합을 자바 객체로 매핑할 수 있다.
    3. 복잡한 쿼리나 다이나믹하게(동적쿼리) 변경되는 쿼리 작성이 쉽다.
      1. 상황에 따라 분기처리(IF)를 통해 쿼리를 동적으로 만들어주는것.
    4. 관심사 분리 - DAO로부터 SQL문을 분리하여 코드의 간결성 및 유지보수성이 향상된다.
    5. 쿼리 결과를 캐싱하여 성능을 향상시킬 수 있다.
// User 클래스
public class User {
    private Long id;
    private String userName;
    private String email;

    // Getter and Setter methods
}



// Mapper Interface 생성 : SQL 쿼리와 매핑을 정의하는 인터페이스
public interface UserMapper {
    User getUserById(Long id);
}


public class Main {
    public static void main(String[] args) {
        String resource = "mybatis-config.xml";
        try (Reader reader = Resources.getResourceAsReader(resource)) {
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            try (SqlSession session = sqlSessionFactory.openSession()) {
                UserMapper userMapper = session.getMapper(UserMapper.class);
                User user = userMapper.getUserById(1L);
                System.out.println(user.getId() + ", " + user.getUsername() + ", " + user.getEmail);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
<mapper namespace="com.example.UserMapper">
    <select id="getUserById" resultType="com.example.User">
        SELECT id, userName, email
        FROM users
        WHERE id = #{id}
    </select>
</mapper>
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mydb" />
                <property name="userName" value="userName" />
                <property name="password" value="password" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/example/UserMapper.xml" />
    </mappers>
</configuration>

✏️ 마무리

이것만은 꼭 기억하기

  1. Spring MVC 구조
    • 프론트 컨트롤러 : DispatcherServlet
    • 어댑터 패턴 : HandlerAdapter
    • View 응답 : View Resolver

  1. 중요! Client to Server 데이터 전송하는 방법 3가지
    • GET + Query Parameter(=Query String)
    • POST + HTML Form(x-www-form-urlencoded)
    • HTTP Request Body
  2. 중요! Server to Client 데이터 응답하는 방법 3가지
    • 정적 리소스
    • View Template
    • HTTP Response Body
  3. Spring Annotation
    1. Controller
      1. @Controller(View 응답), @RestController(데이터 응답)
      2. @RequestMapping(Post, Get, Put, Patch, Delete)
      3. @PathVariable, @RequestParam, @MoelAttribute, @RequestBody 요청
      4. @ResponseBody, HttpResponseEntity<> 응답
    • 각 어노테이션의 사용법 및 주의사항
    • HttpMessageConverter
  4. Layered Architecture
    • Controller의 역할을 분담한다.
    1. Controller
      1. 요청, 응답
    2. Service
      1. 비지니스 로직
      2. @Service
    3. Repository
      1. 데이터베이스 상호 작용
      2. @Repository
    4. DTO
      1. Layer간 데이터 전달
  5. Prepared Statement
    • query를 미리 준비한다.
    • Statement에 비해 성능면에서 뛰어나다.
    • 웹 보안을 유지할 수 있다.
  6. Persistence Framework
    • JDBC API를 사용한다.
    • Prepared Statement를 사용한다.
    • JDBC 처럼 복잡함이나 번거로움 없이 간단한 작업만으로 Database와 연동된다.
      • 자원 관리(Connection)를 자동으로 해준다.
    • SQL Mapper
      • JDBC Template

실습 요약

  • 실습을 기반으로 모든 CRUD API를 만들 수 있다.
  • 우리가 실습으로 만들어낸건 메모 CRUD API로 대부분의 구조가 정형화 되어있다.
  • 그렇다면 우리가 할일은? 메모 → 다른 무엇인가로 바꾸면된다.
  • 아직은 문제점들을 가지고 있다.
    1. 예외 발생시 공통적으로 처리가 불가능하다.
      • 각각의 모든 예외를 try-catch 하여 처리해야 한다.
      • 예시코드
@Slf4j
@RestController // @Controller + @ResponseBody
@RequestMapping("/memos") // Prefix
public class MemoController {

    // 주입된 의존성을 변경할 수 없어 객체의 상태를 안전하게 유지할 수 있다.
    private final MemoService memoService;

    /**
     * 생성자 주입
     * 클래스가 필요로 하는 의존성을 생성자를 통해 전달하는 방식
     * @param memoService @Service로 등록된 MemoService 구현체인 Impl
     */
    private MemoController(MemoService memoService) {
        this.memoService = memoService;
    }

    /**
     * 메모 삭제 API
     * @param id 식별자
     * @return {@link ResponseEntity<Void>} 성공시 Data 없이 200OK 상태코드만 응답.
     * @exception ResponseStatusException 식별자로 조회된 Memo가 없는 경우 404 Not Found
     */
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteMemo(@PathVariable Long id) {

        try {
            memoService.deleteMemo(id);
        } catch (ResponseStatusException e) {
            log.error(e.getReason());
        }

        // 성공한 경우
        return new ResponseEntity<>(HttpStatus.OK);
    }
    
}

 

 

                2. RequestDto, ResponseDto를 공유하여 null값이 들어오기도 한다.

                3.필요없는 필드에 추가적인 null 검사를 해야한다.

'코딩 > 자바' 카테고리의 다른 글

[Spring] SOLID 원칙  (0) 2025.02.04
[Spring] Spring 3 Layered, Spring MVC  (1) 2025.01.23
[Spring] HTTP API 설계 기본  (0) 2025.01.23
[Spring] 기초 5주차  (0) 2025.01.23
[Spring] 기초 4주차  (1) 2025.01.22