๐Ÿšฉ [์ž๋ฐ” ์›น ๊ฐœ๋ฐœ ์›Œํฌ๋ถ Ch.2] (2) : 2.3

NtoZยท2023๋…„ 6์›” 12์ผ
0

Study

๋ชฉ๋ก ๋ณด๊ธฐ
6/9
post-thumbnail

๐Ÿšฉ 2.3. ์›น MVC์™€ JDBC์˜ ๊ฒฐํ•ฉ

๐Ÿ ModelMapper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • TodoDTO์˜ ๊ฒฝ์šฐ Lombok์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ
    ์ด ๋” ์ข‹๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ„๋‹จํ•˜๊ฒŒ ๋‹ค์‹œ ๊ตฌ์„ฑ

  • ํ”„๋กœ์ ํŠธ ๋‚ด์— dto ํŒจํ‚ค์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  TodoDTO ํด๋ž˜์Šค๋ฅผ ์„ ์–ธ

  • TodoDTO์™€ TodoVO๋Š” ์™„์ „ํžˆ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ, ์–ด๋…ธํ…Œ์ด์…˜ ์ƒ์˜ ์ฐจ์ด๊ฐ€ ์กด์žฌํ•œ๋‹ค.

  • @Data๋Š” getter/setter/toString/equals/hashCode ๋“ฑ์„ ๋ชจ๋‘ ์ปดํŒŒ์ผ ๋•Œ ์ƒ์„ฑํ•˜๋Š” ๋ฐ˜๋ฉด VO์˜ ๊ฒฝ์šฐ getter๋งŒ์„ ์ด์šฉํ•ด ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ๊ตฌ์„ฑํ•œ๋‹ค.

โœ”๏ธ DTO์™€ VO๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ์ด์œ 

  1. JPA์—์„œ์˜ ์‚ฌ์šฉ์„ฑ์„ ์œ„ํ•จ.
  2. DTO๋Š” (์œ ํšจ์„ฑ)๊ฒ€์ฆ์ด๋‚˜ ๋ณ€ํ™˜์—์„œ ์ „ํ˜€ ๋‹ค๋ฅธ ์–ด๋…ธํ…Œ์ด์…˜ ํ•„์š”

ModelMapper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

// https://mvnrepository.com/artifact/org.modelmapper/modelmapper
implementation 'org.modelmapper:modelmapper:3.0.0'
  • ModelMapper ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
    : DTO โžก๏ธ VO, VO โžก๏ธ DTO ๋ณ€ํ™˜ ์‰ฝ๊ฒŒ ๋ณด์กฐ

  • (๋‹จ, ์š”์ฆ˜์€ ์„ฑ๋Šฅ์ƒ ์ด์  ๋•Œ๋ฌธ์— MapStruct๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.)

  • VO์— ์• ๋„ˆํ…Œ์ด์…˜ @AllArgsConstructor, @NoArgsConstructor๋ฅผ ์ถ”๊ฐ€ ์ ์šฉํ•ด์•ผ ํ•œ๋‹ค.
    (๋ชจ๋“  ํ•„๋“œ๊ฐ’์ด ํ•„์š”ํ•œ ์ƒ์„ฑ์ž์™€ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ ์šฉํ•˜์—ฌ, VOโฌ…๏ธโžก๏ธDTO์˜ ModelMapper๋ฅผ ํ†ตํ•œ ๋ณ€ํ™˜์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๊ธฐ ์œ„ํ•จ)

MapperUtil ํด๋ž˜์Šค ์ƒ์„ฑ

  • util.MapperUtil ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ModelMapper์˜ ์„ค์ •์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” MapperUtil์„ enum์œผ๋กœ ์„ค์ •
public enum MapperUtil {
    INSTANCE;
    
    private ModelMapper modelMapper;
    
    MapperUtil() {
        this.modelMapper = new ModelMapper();
        				//modelMapper ๊ตฌ์„ฑ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ
        this.modelMapper.getConfiguration()
                .setFieldMatchingEnabled(true) // ํ•„๋“œ ๋งค์นญ ๊ฐ€๋Šฅ
                		//PRIVATE ํ•„๋“œ๋„ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋„๋ก
                .setFieldAccessLevel(Configuration.AccessLevel.PRIVATE)
                .setMatchingStrategy(MatchingStrategies.STRICT);
    }
    
    public ModelMapper get() {
        return this.modelMapper
    }
}

TodoService์™€ ModelMapper ํ…Œ์ŠคํŠธ

  • TodoService๋Š” ์„œ๋น„์Šค ๊ณ„์ธต์—์„œ DTO์™€ VO๋ฅผ ๋‘˜ ๋‹ค ์ด์šฉํ•ด์•ผ ํ•œ๋‹ค.
    service.TodoService enum์œผ๋กœ ์„ ์–ธ.

  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ํ†ตํ•œ ๋“ฑ๋ก ํ™•์ธ : service.TodoServiceTests ์ง„ํ–‰ (140)



๐Ÿ Log4j2์™€ @Log4j2

  • System.out.println()์€ ๋กœ๊ทธ์˜ ๊ธฐ๋Šฅ์œผ๋กœ ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค. โถ์ž์› ์†Œ๋ชจ๊ฐ€ ๋งŽ๊ณ , โทํœ˜๋ฐœ์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • Log4j2๋Š” ๋ ˆ๋ฒจ(level)์ด๋ผ๋Š” ์„ค์ •์ด ์žˆ์–ด ๊ฐœ๋ฐœํ•  ๋•Œ, ํ•„์š”ํ•œ ๋ ˆ๋ฒจ์˜ ๋กœ๊ทธ์™€ ์‹ค์ œ ์šด์˜ ์‹œ์— ํ•„์š”ํ•œ ๋กœ๊ทธ๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

    Lombok์€ @Log4j2๋ผ๋Š” ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•ด์„œ ๊ฐ„๋‹จํžˆ ์†Œ์Šค ์ฝ”๋“œ ๋‚ด์— ๋กœ๊ทธ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Log4j2์˜ ํ•ต์‹ฌ ๊ฐœ๋… : โถ๋ ˆ๋ฒจ(Level) โท์–ดํŽœ๋”(Appender)

    • โถ๋ ˆ๋ฒจ(Level)โšก : ๋กœ๊ทธ์˜ '์ค‘์š”๋„' ๋กœ๊ทธ์˜ ๋ ˆ๋ฒจ์„ ์ง€์ •ํ•˜๋ฉด ํ•ด๋‹น ๋ ˆ๋ฒจ ์ด์ƒ์˜ ๋กœ๊ทธ๋“ค๋งŒ ์ถœ๋ ฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” ๋กœ๊ทธ์˜ ๋ ˆ๋ฒจ์„ ๋‚ฎ๊ฒŒํ•˜์—ฌ ๊ฐœ๋ฐœํ•˜๊ณ  ์šด์˜ํ•  ๋•Œ๋Š” ์ค‘์š”ํ•œ ๋กœ๊ทธ๋“ค๋งŒ ๊ธฐ๋กํ•˜๊ฒŒ ์„ค์ •ํ•œ๋‹ค.

    • โท์–ดํŽœ๋”(Appender)โšก : ๋กœ๊ทธ๋ฅผ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ๊ธฐ๋กํ•  ๊ฒƒ์ธ์ง€.
      ์ฝ˜์†”(console) ๋˜๋Š” ํŒŒ์ผ(File) ์ถœ๋ ฅ์ด ๊ฐ€๋Šฅ.
  • ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” Info ์ดํ•˜์˜ ๋ ˆ๋ฒจ ์‚ฌ์šฉ,
    ์šด์˜ํ•  ๋•Œ๋Š” Error๋‚˜ Warn์ด์ƒ์˜ ๋ ˆ๋ฒจ์„ ์‚ฌ์šฉ.

  • Log4j2 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

//log4j๊ด€๋ จ ์˜์กด์„ฑ ์ถ”๊ฐ€
    implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.17.2'
    implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.17.2'
    implementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.17.2'

log4j2.xml ์„ค์ •ํŒŒ์ผ

@Log4j2 ์–ด๋…ธํ…Œ์ด์…˜

  • log4j2.xml ์„ค์ • ํ™•์ธ์„ ์œ„ํ•œ Lombok ์ˆ˜์ •
    • ๊ธฐ์กด์˜ TodoService ์ฝ”๋“œ์— @Log4j2 ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜๊ณ , System.out~ ๋Œ€์‹ ์— log.info() ๊ฐ™์€ ์ฝ”๋“œ๋กœ ๋ณ€๊ฒฝ
package org.zerock.jdbcex.service;

import lombok.extern.log4j.Log4j2;
import org.modelmapper.ModelMapper;
import org.zerock.jdbcex.MapperUtil;
import org.zerock.jdbcex.dao.TodoDAO;
import org.zerock.jdbcex.domain.TodoVO;
import org.zerock.jdbcex.dto.TodoDTO;

@Log4j2 // โญ
public enum TodoService {
    INSTANCE;

    private TodoDAO dao; // DB์™€ ์—ฐ๊ณ„ํ•˜์—ฌ VO๋ฅผ ๊ฐ€์ ธ์˜ฌ ์—ญํ• 
    private ModelMapper modelMapper; // VO์™€ DTO์˜ ๋ณ€ํ™˜์„ ๋‹ด๋‹น

    TodoService() {
        dao = new TodoDAO(); //์„œ๋น„์Šค๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ dao ์ž๋™ ์ƒ์„ฑ
        modelMapper = MapperUtil.INSTANCE.get();
    }

    public void register(TodoDTO todoDTO) throws Exception {
            //โญmodelMapper.map ์ด๋ผ๋Š” ๋ฉ”์„œ๋“œ ์ด์šฉํ•˜์—ฌ DTO -> VO
        TodoVO todoVO = modelMapper.map(todoDTO, TodoVO.class);
        log.info("todoVO: " + todoVO); //โญ log.info๋กœ ๋ณ€๊ฒฝ

        dao.insert(todoVO); //๐Ÿ”ฅ int๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ์ด๋ฅผ ์ด์šฉํ•œ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋„ ๊ฐ€๋Šฅ
    }

}
  • ์ดํ›„ TodoServiceTests testRegister()์‹คํ–‰

  • Log4j2 ์ ์šฉ ํ›„ HikariCP์˜ ๋กœ๊ทธ๊ฐ€ ๋‹ค๋ฅด๊ฒŒ ์ถœ๋ ฅ๋˜๋Š” ์ด์œ ?

    HikariCP๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ slf4j ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•˜๋Š”๋ฐ, build.gradle์˜ log4j-slf4j-impl ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ Log4j2๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ @Log4j2 ์‚ฌ์šฉํ•˜๊ธฐ

  • ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ @Log4j2 ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ๋„ ์–ด๋…ธํ…Œ์ด์…˜์„ ์ฒ˜๋ฆฌํ•˜๋Š” testAnnotationProcessor์™€ testComplieOnly ์„ค์ •์„ ์ถ”๊ฐ€ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

  • build.gradle

testCompileOnly 'org.projectlombok:lombok:1.18.28'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.28'
  • TodoServiceTests.java
package org.zerock.service;

import lombok.extern.log4j.Log4j2;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.zerock.jdbcex.dto.TodoDTO;
import org.zerock.jdbcex.service.TodoService;

import java.time.LocalDate;

@Log4j2 //โญ
public class TodoServiceTests {

    private TodoService todoService;

    @BeforeEach
    public void ready() {
        todoService = TodoService.INSTANCE;
    }

    @Test
    public void testRegister() throws Exception {
        TodoDTO todoDTO = TodoDTO.builder()
                .title("JDBC Test Title")
                .dueDate(LocalDate.now())
                .build();

        log.info("-------------------------------------"); //โญ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ log4j2 ์„ค์ • ํ™•์ธ
        log.info(todoDTO); //โญ

        todoService.register(todoDTO);
    }
}



๐Ÿ ์ปจํŠธ๋กค๋Ÿฌ์™€ ์„œ๋น„์Šค ๊ฐ์ฒด ์—ฐ๋™ (147p)

  • ์„œ๋ธ”๋ฆฟ์œผ๋กœ ์ž‘์„ฑ๋˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ์™€ TodoService ์—ฐ๋™ํ•˜๋Š” ์ž‘์—…์„ ์ฒ˜๋ฆฌ

  • ์ด์ „ ์˜ˆ์ œ๋“ค์˜ ๊ตฌ์กฐ๋Š” TodoRegisterController์™€ ๊ฐ™์ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์กด์žฌํ•˜์—ฌ ํ•˜๋‚˜์˜ TodoService๋ฅผ ํ†ตํ•ด ์ž์‹ ์ด ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ „๋‹ฌํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ

  • jdbcex.controller ํŒจํ‚ค์ง€ ์ƒ์„ฑ

  • ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ

  • ํ”„๋กœ์ ํŠธ ์‹คํ–‰๊ฒฝ๋กœ /๋ฅผ ์ด์šฉํ•˜๋„๋ก ์ˆ˜์ •, [Deployment] ์—ญ์‹œ exploded๋กœ ๋ณ€๊ฒฝ

  • ๋ณ€๊ฒฝ๋œ ํŒŒ์ผ์˜ ๋น ๋ฅธ ์žฌ์‹คํ–‰
    On 'Update' action : Update classes and resources
    On frame deactivation : Update classes and resources

  • build.gradle JSTL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€

// https://mvnrepository.com/artifact/jstl/jstl
implementation group: 'jstl', name: 'jstl', version: '1.2'

๋ชฉ๋ก ๊ธฐ๋Šฅ ๊ตฌํ˜„ 149

  • ์‹ค์ œ ๊ฐœ๋ฐœ์€ DAO -> Service -> Controller์˜ ์ˆœ์„œ๋Œ€๋กœ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ 

๋“ฑ๋ก ๊ธฐ๋Šฅ ๊ตฌํ˜„ 154

์กฐํšŒ ๊ธฐ๋Šฅ ๊ตฌํ˜„ 158

์ˆ˜์ •/์‚ญ์ œ ๊ธฐ๋Šฅ ๊ตฌํ˜„ 162


์ฝ”๋“œ์˜ ๊ฐœ์„  ์‚ฌํ•ญ๋“ค

  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€ - TodoDAO๋‚˜ TodoService์™€ ๋‹ฌ๋ฆฌ HttpServLet์„ ์ƒ์†ํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ๋ถˆํŽธํ•จ
  • ๋™์ผํ•œ ๋กœ์ง์˜ ๋ฐ˜๋ณต์ ์ธ ์‚ฌ์šฉ - ๊ฒŒ์‹œ๋ฌผ์˜ ์กฐํšŒ๋‚˜ ์ˆ˜์ • ์ž‘์—…์€ ๋‘˜๋‹ค GET ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜์ง€๋งŒ, ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” JSP๋งŒ ๋‹ค๋ฅธ ํ˜•ํƒœ์ธ ์ƒํ™ฉ. ๊ฒฐ๊ตญ ๋™์ผํ•œ ์ฝ”๋“œ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์ž‘์„ฑํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ๋ฐœ์ƒ
  • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์˜ ๋ถ€์žฌ - ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์–ด๋–ค ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ์ง€์— ๋Œ€ํ•œ ์„ค๊ณ„๊ฐ€ ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋น„์ •์ƒ์ ์ธ ํ˜ธ์ถœ์ด ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ ๋Œ€๋น„๊ฐ€ ์•ˆ ๋˜๋Š” ๋ฌธ์ œ
  • ๋ฐ˜๋ณต์ ์ธ ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ - HttpServletRequest๋‚˜ HttpServletResponse๋ฅผ ์ด์šฉํ•ด์„œ TodoDTO๋ฅผ๊ตฌ์„ฑํ•˜๋Š” ์ž‘์—… ๋“ฑ์ด ๋™์ผํ•œ ์ฝ”๋“œ๋“ค๋กœ ์ž‘์„ฑ๋˜์–ด์„œ ์ด์— ๋Œ€ํ•œ ๊ฐœ์„ ์ด ํ•„์š”ํ•˜๊ณ  Long.parseLong()
    ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋“ค๋„ ๋งŽ์ด ๋ฐ˜๋ณต๋˜๋Š” ๋ฌธ์ œ

์ถœ์ฒ˜ ๋ฐ ์ฐธ๊ณ ์ž๋ฃŒ : ์ž๋ฐ” ์›น ๊ฐœ๋ฐœ ์›Œํฌ ๋ถ

profile
9์—์„œ 0์œผ๋กœ, ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ๋ธ”๋กœ๊ทธ

0๊ฐœ์˜ ๋Œ“๊ธ€