문제
  • 두 정수 A와 B를 입력받은 다음, A-B를 출력하는 프로그램을 작성하시오.
입력
  • 첫째 줄에 A와 B가 주어진다. (0 < A, B < 10)
출력
  • 첫째 줄에 A-B를 출력한다.
A. Number_1001.java
import java.util.Scanner;

public class Number_1001 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int a = sc.nextInt();
        int b = sc.nextInt();

        System.out.println(a - b);

        sc.close();
    }
}
알고리즘 분류
  • 수학
  • 구현
  • 사칙연산

'Java, Spring > 코딩테스트' 카테고리의 다른 글

Number_10869 사칙연산  (0) 2023.06.11
Number_1008 A/B  (0) 2023.06.11
Number_10998 A×B  (0) 2023.06.10
Number_1000 A+B  (0) 2023.06.10
Number_2557 Hello World  (0) 2023.06.10
문제
  • 두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
입력
  • 첫째 줄에 A와 B가 주어진다. (0 < A, B < 10)
출력
  • 첫째 줄에 A+B를 출력한다.
A. Number_1000.java
import java.util.Scanner;

public class Number_1000 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int a = sc.nextInt();
        int b = sc.nextInt();

        System.out.println(a + b);

        sc.close();
    }
}
알고리즘 분류
  • 수학
  • 구현
  • 사칙연산

'Java, Spring > 코딩테스트' 카테고리의 다른 글

Number_10869 사칙연산  (0) 2023.06.11
Number_1008 A/B  (0) 2023.06.11
Number_10998 A×B  (0) 2023.06.10
Number_1001 A-B  (0) 2023.06.10
Number_2557 Hello World  (0) 2023.06.10
문제
  • Hello World!를 출력하시오.
입력
  • 없음
출력
  • Hello World!를 출력하시오.
A. Number_2557.java
public class Number_2557 {
    public static void main(String[] args) {
        System.out.printf("Hello World!");
    }
}
알고리즘 분류
  • 구현

'Java, Spring > 코딩테스트' 카테고리의 다른 글

Number_10869 사칙연산  (0) 2023.06.11
Number_1008 A/B  (0) 2023.06.11
Number_10998 A×B  (0) 2023.06.10
Number_1001 A-B  (0) 2023.06.10
Number_1000 A+B  (0) 2023.06.10

thymeleaf와 Spring Security를 통해서 권한별로 볼 수 있게하는 메뉴를 설정을 하던 중, 갑작스럽게 아래와 같은 에러가 발생하였다.

 

There was an unexpected error (type=Internal Server Error, status=500).
org.thymelaf.context.IWebContext.getExchange()Lorg/thymeleaf/web/IWebExchange;
java.lang.NoSuchMethodError: org.thymeleaf.context.IWebContext.getExchange()Lorg/thymeleaf/web/IWebExchange;

구글링 결과 나오는 답이 최신버전의 thymeleaf-spring-security5를 사용할 때, 발생하는 일이라고 떠서, dependcy의 버전을 낮췄다.

<변경 전>

implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.1.RELEASE'

<변경 후>

implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.0.4.RELEASE'

이후에는 NoSuchMethodError가 발생하지 않았다.

쇼핑몰 프로젝트를 하던 중, 다음과 같은 오류가 발생하였다.

Caused by: java.lang.IllegalStateException: For queries with named parameters you need to provide names for method parameters; Use @Param for query method parameters, or when on Java 8+ use the javac flag -parameters

JPQL을 사용할 때, 발생되는 것으로 추정되었고, 당시의 나는 아래와 같은 레파지토리를 작성해뒀다.

@Query("SELECT new com.shop.dto.CartDetailDto(ci.id, i.itemNm, i.price, ci.count, im.imgUrl) " +
        "FROM CartItem ci, ItemImg im " +
        "JOIN ci.item i " +
        "WHERE ci.cart.id = :cartId " +
        "AND im.item.id = ci.item.id " +
        "AND im.repImgYn = 'Y' " +
        "ORDER BY ci.regTime DESC" )
List<CartDetailDto> findCartDetailDtoList(Long cartId);

검색 결과로는 @Param을 설정해라는 방식과 옵션에서 -parameters를 추가해라는 방식이 있었는데, 후자의 방법은 개인적으로 환경이 바뀌면 또 같은 상황이 일어나기 때문에 옳지 않다고 판단하였다.
@Param을 쓰는 방식으로 아래와 같이 수정하였다.

@Query("SELECT new com.shop.dto.CartDetailDto(ci.id, i.itemNm, i.price, ci.count, im.imgUrl) " +
        "FROM CartItem ci, ItemImg im " +
        "JOIN ci.item i " +
        "WHERE ci.cart.id = :cartId " +
        "AND im.item.id = ci.item.id " +
        "AND im.repImgYn = 'Y' " +
        "ORDER BY ci.regTime DESC" )
List<CartDetailDto> findCartDetailDtoList(@Param("cartId")Long cartId);

이후, IllegalStateException이 발생하지 않게 되었다.

DispatcherServlet

기본적으로 서블릿은 입력, 처리, 출력 순서로 되어있다.
공통적으로 처리해야할 입력부분을 제거해주는 것이 DispatcherServlet의 역할이다.
즉, DispatcherServlet은 전처리를 해주는 역할을 한다.
각 서블릿이나 컨트롤러가 처리해야하는 부분을 DispatcherServlet이 처리를 해주는 것이다.

'Java, Spring > 개념정리' 카테고리의 다른 글

스프링 프레임워크(Spring Framework)  (0) 2023.01.17
Spring JDBC 개요  (0) 2023.01.14
AOP(Aspect Oriented Programming)  (0) 2023.01.12
DI Container  (0) 2023.01.12
DI(Dependency Injection)  (0) 2023.01.12

Spring Framework

Java 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크이다.

  • 애플리케이션 프레임워크 : 특정 계층이나 기술, 업무 분야에 국한되지 않고, 애플리케이션의 전 영역을 포괄하는 범용적인 프레임워크를 말한다.
  • 경량급 프레임워크 : 단순한 웹컨테이너에서도 엔터프라이즈 개발의 고급기술을 대부분 사용할 수 있다.
  • 엔터프라이즈 개발 용이 : 개발자가 복잡하고 실수하기 쉬운 Low Level 에 많이 신경 쓰지 않으면서 Business Logic 개발에 전념할 수 있도록 해준다.
  • 오픈 소스 : Spring 은 OpenSource 의 장점을 충분히 취하면서 동시에 OpenSource 제품의 단점과 한계를 잘 극복한다.

Spring Framework 전략

Spring 삼각형

엔터프라이즈 개발의 복잡함을 상대하는 Spring 의 전략 → PSA, AOP, DI, POJO

  1. PSA(Portable Service Abstraction, 서비스 추상화)
    트랜잭션 추상화, OXM(Object XML Mapping) 추상화, 데이터 액세스의 Exception 변환기능 등 기술적인 복잡함은 추상화를 통해 Low Level 의 기술 구현 부분과 기술을 사용하는 개발자는 분리된 인터페이스만 보고 개발하도록 인터페이스로 분리한다.
  2. 객체지향과 DI(Dependency Injection, 의존관계주입)
    Spring 은 객체지향에 충실한 설계가 가능하도록 단순한 객체형태로 개발할 수 있고, DI 는 유연하게 확장 가능한 객체를 만들어 두고, 그 관계는 외부(컨테이너)에서 다이나믹(동적)하게 설정해준다.
  3. AOP(Aspect Oriented Programming, 관점지향프로그래밍)
    AOP 는 애플리케이션 로직을 담당하는 코드에 남아있는 기술 관련 코드를 분리해서, 별도의 모듈로 관리하게 해주는 강력한 기술이다.
  4. POJO(Plain Old Java Object, 일반 자바 객체)
    POJO 는 객체 지향 원리에 충실하면서, 특정 환경이나 규약에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 객체이다.

Spring Framework 의 특징

  1. 컨테이너 역할
    Spring 컨테이너는 Java 객체의 LifeCycle 을 관리하며, Spring 컨테이너로 부터 필요한 객체를 가져와 사용할 수 있다.
  2. DI(Dependency Injection) 지원
    Spring 은 설정 파일이나 어노테이션을 통해서 객체 간의 의존관계를 설정할 수 있도록 한다.
  3. AOP(Aspect Oriented Programming) 지원
    Spring 은 트랜잭션이나 로깅, 보안과 같이 공통적으로 필요로 하는 모듈들을 실제 핵심 모듈에서 분리하여 적용할 수 있다.
  4. POJO(Plain Old Java Object)
    Spring 컨테이너에 저장되는 Java 객체는 특정한 인터페이스를 구현하거나, 특정 클래스를 상속 받지 않아도 된다.
  5. 트랜잭션 처리를 위한 일관된 방법을 지원
    JDBC, JPA 등 어떤 트랜잭션을 사용하건 설정(XML, annotation)을 통해 정보를 관리하므로, 트랜잭션 구현에 상관없이 동일한 코드로 사용가능하다.
  6. 영속성(Persistence)과 관련된 다양한 API 지원
    Spring 은 MyBatis, Hibernate 등 데이터베이스 처리를 위한 ORM(Object Relation Mapping) 프레임워크들과의 연동 지원

Spring Framework 를 구성하는 기능 요소

  • Spring Core
    • Spring Framework 의 기본기능(컨테이너)을 제공한다.
    • 이 모듈에 있는 BeanFactory 는 Spring 의 기본 컨테이너면서 Spring DI 기반이다.
  • Spring AOP
    • AOP 모듈을 통해 Aspect 지향 프로그래밍(공통 로직 분리)을 지원한다.
    • AOP 모듈은 스프링 애플리케이션에서 Aspect 를 개발할 수 있는 기반을 지원한다.
  • Spring ORM
    • MyBatis, Hibernate, JPA 등 널리 사용되는 ORM 프레임워크와의 연결고리를 제공한다.
    • ORM 제품들을 Spring 의 기능과 조합해서 사용할 수 있도록 해준다.
  • Spring DAO
    • JDBC 에 대한 추상화 계층으로 JDBC 코딩이나 예외처리 하는 부분을 간편화 시켰으며, AOP 모듈을 이용해 트랜잭션 관리 서비스도 제공한다.
  • Spring Web
    • 일반적인 웹 애플리케이션 개발에 필요한 기본 기능을 제공한다.
    • Webwork 나 Struts 와 같은 다른 웹 애플리케이션 프레임워크와의 통합을 지원한다.
  • Spring Context
    • Context 모듈은 Spring Core 의 BeanFactory 개념을 확장한 것으로, 국제화(I18N) 메시지, 애플리케이션 생명주기, 이벤트, 유효성 검증 등을 지원한다.
  • Spring Web MVC
    • MVC 란 Model, View, Controller 를 의미하며, Spring Web MVC 는 사용자의 인터페이스가 애플리케이션 로직과 분리되는 웹 애플리케이션을 만드는 경우에 일반적으로 사용되는 패러다임이다.

'Java, Spring > 개념정리' 카테고리의 다른 글

DispatcherServlet  (0) 2023.02.02
Spring JDBC 개요  (0) 2023.01.14
AOP(Aspect Oriented Programming)  (0) 2023.01.12
DI Container  (0) 2023.01.12
DI(Dependency Injection)  (0) 2023.01.12

DAO(Data Acess Object) 패턴

  • 데이터 액세스 계층은 DAO 패턴을 적용하여 비즈니스 로직과 데이터 액세스 로직을 분리하는 것이 원칙이다.
  • 비즈니스 로직이 없거나 단순하면 DAO 와 서비스 계층을 통합 할 수도 있지만, 의미있는 비즈니스 로직을 가진 엔터프라이즈 애플리케이션이라면 데이터 엑세스 계층을 DAO 패턴으로 분리해야 한다.
  • DAO 패턴은 서비스 계층에 영향을 주지 않고 데이터 액세스 기술을 변경할 수 있는 장점을 가지고 있다.

Connection Pooling을 지원하는 DataSource

Connection Pooling은 미리 정해진 개수만큼의 DB Connection 을 Pool 에 준비해두고, 애플리케이션이 요청할 때마다 Pool 에서 꺼내서 하나씩 할당해주고, 다시 돌려받아서 Pool 에 넣는 식의 기법이다.

  • 다중 사용자를 갖는 엔터프라이즈 시스템에서라면 반드시 DB Connection Pooling 기능을 지원하는 DataSource 를 사용해야 한다.
  • Spring 에서는 DataSource 를 공유가능한 Spring Bean 으로 등록해주어 사용할 수 있도록 해준다.

DataSoucre 구현 클래스 종류

  1. 테스트 환경을 위한 DataSource
    • SimpleDriverDataSource
      • Spring 이 제공하는 가장 단순한 DataSource 구현 클래스
      • getConnection() 을 호출할 때 마다, 매번 DB Connection 을 새로 만들고, 따로 pool 을 관리하지 않으므로, 단순한 테스트용으로만 사용해야한다.
    • SingleConnectionDriverDataSource
      • 순차적으로 진행되는 통합 테스트에서는 사용 가능하다.
      • 매번 DB Connection 을 생성하지 않기 때문에, SimpleDriverDataSource 보다 빠르게 동작한다.
  2. 오픈소스 DataSource
    • Apache Commons DBCP
    • c3p0 JDBC / DataSource Resource Pool]
    • 두 가지 모두 setter 메서드를 제공하므로 Spring Bean 으로 등록해서 사용하기 편리하다.

Spring JDBC

JDBC 는 모든 자바의 데이터 액세스 기술의 근간이 된다. Entity Class 와 annotation 을 이용하는 최신 ORM 기술도 내부적으로는 DB 와의 연동을 위해 JDBC 를 이용한다.

  • 안정적이고 유연한 기술이지만, low level 기술로 인식되고 있다.
  • 간단한 SQL 을 실행하는 데도 중복된 코드가 반복적으로 사용되며, DB 에 따라 일관성 없는 정보를 가진 채로 Checked Exception 으로 처리한다.
장점 단점
대부분의 개발자가 잘 알고 있는 친숙한 데이터 액세스 기술로, 별도의 학습 없이 개발이 가능하다. Connection 과 같은 공유 리소스를 제대로 릴리즈 해주지 않으면 시스템의 자원이 바닥나는 버그를 발생시킨다.

Spring JDBC 는 JDBC 의 장점과 단순성을 그대로 유지하면서도 기존 JDBC 의 단점을 극복할 수 있게 해주고, 간결한 형태의 API 사용법을 제공하며, JDBC API 에서 지원되지 않는 편리한 기능을 제공한다.

  • Spring JDBC 는 반복적으로 해야 하는 많은 작업들을 대신 해준다.
  • Spring JDBC 를 사용할 때는 실행할 SQL 과 바인딩 할 파라미터를 넘겨주거나, 쿼리의 실행 결과를 어떤 객체에 넘겨 받을지를 지정하는 것만 하면 된다.
  • Spring JDBC 를 사용하려면 먼저, DB Connection 을 가져오는 DataSource 를 Bean 으로 등록해야한다.

Spring JDBC 가 해주는 작업

  1. Connection 열기와 닫기
    • Connection 과 관련된 모든 작업을 Spring JDBC 가 필요한 시점에서 알아서 진행한다.
    • 진행 중에 예외가 발생했을 때도 열린 모든 Connection 객체를 닫아준다.
  2. Statement 준비와 닫기
    • SQL 정보가 담긴 Statement 또는 PreparedStatement 를 생성하고, 필요한 준비 작업을 해주는 것도 Spring JDBC가 한다.
    • Statement 도 Connection 과 마찬가지로 사용이 끝나고 나면 Spring JDBC 가 알아서 객체를 닫아준다.
  3. Statement 실행
    • SQL 담긴 Statement 를 실행하는 것도 Spring JDBC 가 해준다.
    • Statement 의 실행결과는 다양한 형태로 가져올 수 있다.
  4. ResultSet Loop 처리
    • ResultSet 에 담긴 쿼리 실행 결과가 한 건 이상이면 ResultSet Loop 를 만들어서 반복해주는 것도 Spring JDBC 가 해주는 작업이다.
  5. Exception 처리와 반환
    • JDBC 작업 중 발생하는 모든 예외는 Spring JDBC 예외 변환기가 처리한다.
    • 체크 예외(Checked Exception)인 SQLException 을 런타임 에외(Runtime Exception)인 DataAccessException 타입으로 변환한다.
  6. Transaction 처리
    • Spring JDBC 를 사용하면 transaction 과 관련된 모든 작업에 대해서는 신경 쓰지 않아도 된다. (ex. commit, rollback)

JdbcTemplate 클래스

Spring JDBC 가 제공하는 클래스 중 JdbcTemplate 은 JDBC 의 모든 기능을 최대한 활용할 수 있는 유연성을 제공하는 클래스이다.

  • JdbcTemplate 이 제공하는 기능은 실행, 조회, 배치의 세가지 작업이다.
    • 실행 : Insert 나 Update 같이 DB 의 데이터에 변경이 일어나는 쿼리를 수행하는 작업
    • 조회 : Select 를 이용해 데이터를 조회하는 작업
    • 배치 : 여러 개의 쿼리를 한 번에 수행해야 하는 작업

JdbcTemplate 클래스 생성

  • JdbcTemplate 은 DataSource 를 파라미터로 받아서 아래와 같이 생성할 수 있다.
JdbcTemplate template = new JdbcTemplate(dataSoucrce);
  • DataSource 는 보통 Bean 으로 등록해서 사용하므로 JdbcTemplate 이 필요한 DAO 클래스에서 DataSource Bean 을 DI 받아서 JdbcTemplate 을 생성할 때 인자로 넘겨주면 된다.
  • JdbcTemplate 은 멀티스레드 환경에서도 안전하게 공유해서 쓸 수 있기 때문에 DAO 클래스의 인스턴스 변수에 저장해 두고 사용할 수 있다.

JdbcTemplate 클래스 생성 Code

  • 아래의 코드는 일반적으로 사용되는 DAO 클래스의 기본 구조이다. DataSource 에 대한 수정자 메서드에서 직접 JdbcTemplate 객체를 생성해준다.
public class UserDAOJdbc {
  JdbcTemplate jdbcTemplate;

  @Autowired
  public void setDataSource(Datasource dataSource) {
    jdbcTemplate = new JdbcTemplate(dataSource);
  }
}

JdbcTemplate 클래스의 update() 메서드

  • INSERT, UPDATE, DELETE 와 같은 SQL 을 실행할 때는 JdbcTemplate 의 update() 메서드를 사용한다.
int update(String sql, [SQL 파라미터])
  • update() 메서드를 호출할 때는 SQL 과 함께 바인딩 할 파라미터는 Object 타입 가변인자 (Object ... args) 를 사용할 수 있다.
  • update() 메서드의 리턴되는 값은 SQL 실행으로 영향을 받은 레코드의 개수를 리턴한다. (-1, 0, 1 이 성공, 실패의 기준이 되는 이유)

JdbcTemplate 클래스의 update() 메서드 Code

public int update(User user) {
  StringBuffer updateQuery = new StringBuffer();
  updateQuery.append("UPDATE users SET ");
  updateQuery.append("password=?, name=?");
  updateQuery.append("WHERE id=? ");

  int result = this.jdbcTemplate.update(updateQuery.toString(), user.getName(), user.getPassword(), user.getId()); // StringBuffer 로 만든 SQL 문을 toString() 메서드를 이용
  // 각 값들을 get() 메서드를 통해서 얻어온다.

  return result; // 값을 반환
}

JdbcTemplate 클래스의 queryForObject() 메서드

  • SELECT SQL 을 실행하여 하나의 Row 를 가져올 때는 JdbcTemplate 의 queryForObject() 메서드를 사용한다.
    • queryForObject() 메서드는 여러개의 Column, 하나의 Row
    • query() 메서드는 여러개의 Column, 여러개의 Row
<T> T queryForObject(String sql, [SQL 파라미터], RowMapper<T> rm)
  • SQL 실행 결과는 여러 개의 Column 을 가진 하나의 Row
  • T 는 VO(Value Object) 객체의 타입에 해당된다. (T 는 Colum 이 여러개, Row 가 하나일 때 VO 객체의 타입에 해당된다.)
  • SQL 실행 결과로 돌아온 여러 개의 column 을 가진 한 개의 Row 를 RowMapper 콜백을 이용해 VO 객체로 매핑해준다.

JdbcTemplate 클래스의 queryForObject() 메서드 Code

public User findUser (String id) {
  return this.jdbcTemplate.queryForObejct("SELECT * FROM users WHERE id=?", new Object[] {id}),

  new RowMapper<User>() {
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
      User user = new User();
      user.setId(rs.getString("id"));
      user.setName(rs.getString("name"));
      user.setPassword(rs.getString("password"));

      return user;
        } // RowMapper
      }; // queryForObject
} // findUser

JdbcTemplate 클래스의 query() 메서드

  • SELECT SQL 을 실행하여 여러 개의 Row 를 가져올 때는 JdbcTemplate 의 query() 메서드를 사용한다.
<T> List<T> query(String sql, [SQL 파라미터], RowMapper<T> rm)
  • SQL 실행 결과로 돌아온 여러 개의 column 을 가진 여러 개의 Row 를 RowMapper 콜백을 이용해 VO 객체로 매핑해준다.
  • 결과 값은 매핑한 VO 객체를 포함하고 있는 List 형태로 받는다. (Row 가 여러개이기 때문에) List의 각 요소가 하나의 Row 에 해당한다.

DataSource 설정

  • DataSource 를 Spring Bean 으로 등록하여 사용할 수 있다.

bean.xml

<context:property-placeholder location="classpath:config/value.properties" />

<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
  <property name= "driverClass" value="${db.driverClass}" />
  <property name= "url" value="${db.url}" />
  <property name= "username" value="${db.username}" />
  <property name= "password" value="${db.password}" />
</bean>

value.properties

db.driverClass=oracle.jdbc.OracleDriver
#mysql, mariadb 의 경우에는 다른 driverClass 와 다른 url 을 사용해야한다.
db.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
db.username=scott
db.password=tiger

'Java, Spring > 개념정리' 카테고리의 다른 글

DispatcherServlet  (0) 2023.02.02
스프링 프레임워크(Spring Framework)  (0) 2023.01.17
AOP(Aspect Oriented Programming)  (0) 2023.01.12
DI Container  (0) 2023.01.12
DI(Dependency Injection)  (0) 2023.01.12

+ Recent posts