기록
  • 0117
    2024년 01월 17일 14시 05분 18초에 업로드 된 글입니다.
    작성자: 삶은고구마

    tailwind css utility class <주로 설정

    <->

    bootstrap component 주

                    utility class 부

     

    -

    src - resources

    webapp - resources

    이 둘의 사용처는 다름.

    -

    boot strap 4.x버전 

    아래 사이트에서 유틸리티나 컴포넌트중에 아무거나 골라서 css 작업 하면 될 듯. 

    부가적인걸 원한다면 따로 css작업을 해줘야함.

    +tailwindcss와 bootstrap은 혼용하면 충돌가능성이 있으므로 안전하게 둘 중 하나만 사용하자

    https://getbootstrap.com/docs/4.6/utilities/spacing/

     

    Spacing

    Bootstrap includes a wide range of shorthand responsive margin and padding utility classes to modify an element’s appearance.

    getbootstrap.com

     

     

    pop up 과 modal의 차이점

    요약

    팝업:짧은정보 제공

    모달:추가 정보 및 입력을 받음. (확인이나 취소를 누르기 전까지 꺼지지 않음)

     

    https://brunch.co.kr/@minakoro/156

     

    팝업(Popup)과 모달(Modal)의 차이

    UI 디자이너가 알면 좋은 개발 지식 | IT회사의 인하우스 디자이너로 10년 넘게 일을 하면서 얻은 것은 웹의 변화에 따라 넓어진 웹에 대한 지식이다. 아이폰이 불러온 모바일 혁명을 통해 다양한

    brunch.co.kr

     


     

    spring 구조

    maven 실습 ~semi p 때는 역할:class=1:1 로 나눴지만

    spring~ final p 까지는

    한 controller 안에 여러 method로 구분하여 n개의 class를 n개의 메소드로 구현할 수 있다.

    실제로 오늘 작성한 코드도 한개의 DevController에서

    다수의 GetMapping,PostMapping 어노테이션을 단 메소드들로 테스트함.

     

    컨트롤러단: 컨트롤러로 동작할 클래스에 Controller 어노테이션을 붙인다.
    
    @Controller
    
    public class TestController{
    
    }
    
    예시)
    
    @GetMapping("/hello")
    public String hello(Model model)
    {
    	model.addAttribute("msg","Hello World!");
        return "hello";
    }
    
    1.Model 객체는 뷰에 전달되는 객체로 컨트롤러에서 뷰로 전달할 값이 있으면
    model.addAttribute로 전달한다. jsp에서 request.setAttribute()와 같은 개념
    2.return 타입은 String이고, 값은 단순한 문자열이 아니라 view의 이름이 들어간다.
    즉, jsp 타임리프 파일의 이름을 확장자 없이 이름만 사용 <무슨소린지
    =>문자열인 hello를 반환하는게 아니라 문자열로 선언된 뷰로 데이터 반환
    hello.jsp 
    3.여기서는 hello.jsp(or html)을 호출하게 되고 실제 파일 위치는 스프링 설정마다 다름

     

     

    Spring Bean

    스프링 컨테이너에 의해 관리되는 자바객체

    빈 등록은 설정 xml,어노테이션,설정클래스 등을 이용해 등록할 수 있다.

    등록된 빈은 오토와이어링(@AutoWired)를 통해 공급된다.

    빈이 등록 되었다면 컨트롤러,DAO등의 구현 클래스에서 해당 객체가 필요할 때

    @AutoWired 어노테이션을 통해 객체를 참조할 수 있다.

     

    1)필드

    ->필드위에 @AutoWired 선언

    ->간단하고 편리함 

    ->순한 의존성 문제 발생 가능성 有

    ->final 사용 x

     

    2)생성자

    ->객체가 생성될 때 호출되는 생성자에 참조할 클래스를 인자로 받아 필드에 매핑

    ->생성자가 하나인 경우 @AutoWired 사용하지 않아도 됨. 단, 생성자에 참조할 객체 늘어나면 리팩토링 고려

    ->필드 주입방식보다 생성자 주입이 생성자로 집중되기때문에 코드관리 편리/분석/테스트에 유리 (권장되는 방식)

     

    3)Setter 주입 

    ->setter 메서드에 @AutoWired 선언

    ->final 사용 x

    ->생성자에 과도하게 의존성 주입이 되는 것을 보완 / 의존성이 선택적인 경우 사용

     

     

     

    Lombok

    entity class의 getter/setter, constructor, toString을 대신해주는 의존성

    pom.xml에 추가

    <dependencies>
    	<dependency>
    		<groupId>org.projectlombok</groupId>
    		<artifactId>lombok</artifactId>
    		<version>1.18.30</version>
    		<scope>provided</scope>
    	</dependency>
    </dependencies>

     

    추가 후 Enable a~ 체크

     

     

     

    앞으로는 sout 대신 log를 사용하자(PSA 적용)

    sout 대신 log를 사용하면 내가 무슨 정보를 얻고 싶은지, 해당 로그가 발생하는 시점이 어딘지를 알 수 있다.

    mvc 구조에서 어딘가 에러났을 때 ...

    System.out.println("service error");

    System.out.println("dao error");

    이런식으로 해당 클래스의 위치를 수기로 적었다..

    하지만 log를 사용한다면 위의 이미지처럼 log출력 발생 클래스위치까지 알아서 찍어줌. 

    그리고 info 부터 fatal까지 용도에 맞는 로그를 출력 할 수 있다.

    -

    처음에는 로그확인을 위해 log4j를 직접 사용했는데,

    이렇게 다이렉트로 라이브러리를 사용하지 말고,

    spring의 특징 중 하나인 추상화 레이어 기법을 이용하여 간접적으로 사용하는 것이 좋다고한다.

    (변화에 유연하게 대처 가능)

     

    요약:

    사용하고자 하는 클래스에서 로깅관련 라이브러리를 직접 사용하지 말고

    slf4j를 통해 로깅 라이브러리를 사용하자.

    구글링하다 줏은 이미지, 중간에 slf4j가 추상화 레이어 역할을 한다.

     

    * 로깅프레임워크 사용하기
     * -log4j2 <-요거 사용중 그외에도 여러개가있다.
     * -로깅메세지의 형식을 지정할 수 있다.
     * -어디서 발생하는 로그인지 판별하기 쉽다! sout으로 할 땐 해당 클래스를 수동으로 작성했었음.ㅠ
     * -레벨에 따른 출력 여부를 결정할 수 있다. (지정한 레벨 이상의 로그만 출력)
     * 위에서 아래로 갈 수록 레벨 높아짐
     * -trace : debug에서 조금 더 상세함~ 메소드의 시작 끝도 표시
     * -debug : 개발 환경에서 디버깅용
     * -info  : 정보성 메시지 출력
     * -warn  : 경고 메세지.현재 실행에는 문제 없지만, 향후에는 문제 될 수 있음 ex)deprecated
     * -error : 오류.예외발생 시 로깅
     * -fatal : 치명적인 오류. 심각한 시스템 장애
     *
     *직접 로깅구현체인 Log4j를 사용하지 않고(@Log4j2), 스프링의 추상화레이어(psa) slf4j를 통해 제어한다.
     * -slf4j : simple logging facade for java)

     

    main-src-resuorces-log4j2.xml

    내가 원하는 레벨이상부터 출력할수 있도록 해당 xml에서 설정할 수 있음.

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="INFO">
    	<Appenders>
    		<Console name="console" target="SYSTEM_OUT">
    			<PatternLayout pattern="[%-5level] %c{1.}.%M - %msg%n"/>
    		</Console>
    	</Appenders>
    
    	<Loggers>
    	    <Root level="INFO">
          		<AppenderRef ref="console"/>
        	</Root>
        	<Logger name="com.sh.app" level="TRACE"></Logger>
        	<!-- 3rdparty Loggers -->
    		<Logger name="org.springframework.core" level="DEBUG"></Logger>
    		<Logger name="org.springframework.beans" level="INFO"></Logger>
    		<Logger name="org.springframework.context" level="INFO"></Logger>
    		<Logger name="org.springframework.web" level="INFO"></Logger>
    	</Loggers>
    </Configuration>
    
    <!--
    	Appenders : 메세지 지정 형식
    
    	Loggers : <Logger name="com.sh.app" level="DEBUG"></Logger>
    	로 지정하면 debug 이상부터 출력. info로 수정하면 info 이상부터 출력(debug안찍힘)
    
    -->

     

     

     

     

     

     

     

    Command pattern

     

    사용자 입력값과 똑같은 필드가 있는 것.

     

     

     

    서버단에서도 유효성 검사를 할 수 있다.

    javascript를 통해 클라이언트 단에서만 유효성 검사를 해봤는데,

    서버단에서도 할 수 있다고 한다.

    강사님 설명으로는.. 클라이언트가 브라우저를 통해 데이터를 날린다는 보장이 없기 때문에 

    서버에서도 데이터 유효성 검사를 해야한다고..

     

    아래의 예시는 문자관련 유효성 검사범위를 그림판으로 간략하게 그려본 것이다..

    NotNull  null x
    NotEmpty  null , "" x
    NotBlank null, "", " " x (공백도 허용하지 않음)

     

     


    Design Pattern

    sw에서 자주 발생하는 문제를 효과적으로 해결하는 구조

     

    생성패턴 - 싱글턴패턴(하나의 객체를 재사용), 빌더패턴

    구조패턴

    행위패턴

     

    Builder Pattern

    https://readystory.tistory.com/121

     

    [생성 패턴] 빌더 패턴(Builder pattern) 이해 및 예제

    빌더 패턴은 복잡한 객체를 생성하는 방법을 정의하는 클래스와 표현하는 방법을 정의하는 클래스를 별도로 분리하여, 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공하는 패턴

    readystory.tistory.com


    빌더 패턴은 많은 Optional한 멤버 변수(혹은 파라미터)나 지속성 없는 상태 값들에 대해

    처리해야 하는 문제들을 해결합니다.

    예를 들어, 팩토리 패턴이나 추상 팩토리 패턴에서는 생성해야하는 클래스에 대한 속성 값이 많을 때

    아래와 같은 이슈들이 있습니다.

    1.  클라이언트 프로그램으로부터 팩토리 클래스로 많은 파라미터를 넘겨줄 때 타입, 순서 등에 대한 관리가 어려워져 에러가 발생할 확률이 높아집니다.
    2. 경우에 따라 필요 없는 파라미터들에 대해서 팩토리 클래스에 일일이 null 값을 넘겨줘야 합니다.
    3. 생성해야 하는 sub class가 무거워지고 복잡해짐에 따라 팩토리 클래스 또한 복잡해집니다. 

     

    예제

    /**
     * 객체 생성패턴
     * 1.기본생성자 + setter
     * 2.파라메터 생성자 (객체생성과 동시에 필드처리)
     * 3.new))빌더 - 객채생성시 필수입력 값 / 선택입력값 구분이 있는 경우..
     */
    public class UserMain {
        public static void main(String[] args){
            User user = User.builder()
                    .id(1L)
                    .username("nongdam")
                    .password("1234")
                    .build();
            //여기에 없는 createdAt,name값은 자동으로 null값이 되고, 위의 순서는 바뀌어도 상관없다.
            System.out.println(user);
        }
    }

     

    package com.sh.app.creation.builder;
    
    import lombok.*;
    
    import java.time.LocalDateTime;
    
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    @ToString
    @Builder //=>밑에 주석처리 한 것들을 이 어노테이션 하나로 해결
    public class User {
        private Long id;
        private String username;
        private String password;
        private String name;
        private LocalDateTime createdAt;
    
    //    public static UserBuilder builder()
    //    {
    //        return new UserBuilder();
    //    }
    //
    //
    //    static class UserBuilder
    //    {
    //        private Long id;
    //        private String username;
    //        private String password;
    //        private String name;
    //        private LocalDateTime createdAt;
    //
    //        public UserBuilder id(Long id)
    //        {
    //            this.id = id; //여기서의 this는 이 코드가 속한 class 즉, UserBuilder다.
    //            return this;
    //        }
    //
    //        public UserBuilder username(String username)
    //        {
    //            this.username = username;
    //            return this;
    //        }
    //
    //        public UserBuilder password(String password)
    //        {
    //            this.password = password;
    //            return this;
    //        }
    //
    //        public UserBuilder name(String name)
    //        {
    //            this.name = name;
    //            return this;
    //        }
    //
    //        public UserBuilder createdAt(LocalDateTime createdAt)
    //        {
    //            this.createdAt = createdAt;
    //            return this;
    //        }
    //
    //        //userbuilder의 객체값들을 user에 전달
    //        public User build()
    //        {
    //            //여기서의 this = UserBuilder
    //            return new User(this.id,username,password,name,createdAt);
    //        }
    //    }
    }

     

     

     

    DTO(Data Transfer Object)

    -getter / setter만 사용

    * DTO
     * -Data Transfer Object
     * -데이터 전송을 위한 객체
     * -Client에서 server로 넘어온 데이터를 담을 수 있는 규격 객체
     *  (전송하는 값만 담을 수 있어야 함, 그 외값은 필드도 만들지말자)
     * -mvc 흐름에서도 당연히 사용할 수 있다.
     * -getter,setter만 사용한다.
     
     @Getter
    @Setter
    public class DevCreateDto {
        @NotNull(message = "이름은 필수입니다.")
        private String name;
        @PositiveOrZero(message = "경력은 0이상 숫자부터 가능합니다.")
        private int career;
        @Email(message = "이메일 형식으로 작성하세요.")
        private String email;
        @Pattern(regexp="[MF]",message = "성별은 M 또는 F여야 합니다.")
        private String gender;
        private List<String> lang; //name값과 동일해야 한다.
    
    
        public Dev toDev()
        {
            Gender gender = this.gender != null ? Gender.valueOf(this.gender): null;
            return new Dev
                    (0,this.name,this.career,this.email, Gender.valueOf(this.gender), this.lang,LocalDateTime.now());
        }
    }

     

     

     


    DB연동 실습 

    pom.xml 에 db 관련 의존성 추가.

    중간에 업데이트 버전 이슈로 한차례 수정을 하였다..

     <!--DB 관련..-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>${org.springframework-version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.15</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>3.0.2</version>
            </dependency>
            <!-- Database Connection Pool -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-dbcp2</artifactId>
                <version>2.9.0</version>
            </dependency>
            <dependency>
                <groupId>com.oracle.database.jdbc</groupId>
                <artifactId>ojdbc11</artifactId>
                <version>23.2.0.0</version>
            </dependency>

     

     

    사용할 table 생성

    --관리자 계정(system)
    alter session set "_oracle_script" = true;
    
    create user spring
    identified by spring
    default tablespace users;
    
    select * from dba_users;
    
    alter user spring quota unlimited on users;
    
    grant connect, resource to spring;

     

     

    root-context.xml  

    <context:property-placeholder location="classpath:datasource-local.properties">
    </context:property-placeholder>

     

     

    1.기존 datasource-local.properties의 설정을 root-context에 기술함

    <!--DB관련 bean 등록 (여기서는 beans가 기본 네임스페이스이다.)-->
    	<bean class="org.apache.commons.dbcp2.BasicDataSource"
    		  id="dataSource" destroy-method="close">
    		<property name="driverClassName" value="${datasource.driverClassName}"/>
    		<property name="url" value="${datasource.url}"/>
    		<property name="username" value="${datasource.username}"/>
    		<property name="password" value="${datasource.password}"/>
    	</bean>

     

    참조하는 datasource-local.properteis

    //datasource-local.properties
    # datasource-local.properties spring에서는 값을 심플하게 하지말고 접두사 붙이기
    datasource.driverClassName = oracle.jdbc.OracleDriver
    datasource.url = jdbc:oracle:thin:@localhost:1521:xe
    datasource.username = spring
    datasource.password = spring

     

     

    2.기존 mybatis-config.xml 의 설정을 root-context에 기술함

    <!-- factory : db,설정,mapper 필요  -->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath*:mapper/**/*-mapper.xml"/>
    </bean>
    <bean class="org.mybatis.spring.SqlSessionTemplate" id="sqlSessionTemplate">
        <constructor-arg ref="sqlSessionFactoryBean"/>
    </bean>
     

    기존의 mybatis-config.xml는 이렇게 주석이 더 많아졌다.

     

    '공부 > spring' 카테고리의 다른 글

    0118 Spring boot / thymeleaf  (0) 2024.01.18
    spring db 연동 오류  (0) 2024.01.17
    댓글