User Flow 설계도

발생한 error

문제 상황

원인

숫자로 변환할 수 없는 문자열이 입력값으로 들어왔을 때 발생

해결방안

입력값을 문자로 비교해서 해결

입력값이 숫자로서 값을 비교하거나 연산하는 것이 아니었기에 사용할 수 있었던 방법

Python 코드

import random
import time

def error_page(mini, maxi):
    print(str(mini) + "~" + str(maxi) + "사이에 숫자만 입력 가능합니다!")

def exit_page():
    print("게임을 종료합니다.", end="")
    for i in range(2):
        time.sleep(0.5)
        print(".", end="")
    exit()

def start():
    while True:
        minimum = 1
        maximum = 100
        print("=== UP & DOWN Game ===")
        print("1. 시작하기")
        print("0. 종료하기")
        action = input()
        if (action == "0"):
            exit_page()
        elif (action == "1"):
            rand_num = random.randint(1, 100)
            # print("rand_num: " + str(rand_num))
            while True:
                print("숫자를 입력해주세요(" + str(minimum) + "~" + str(maximum) + ") >>")
                num = input()
                if not num.isnumeric() or int(num) < minimum or int(num) > maximum:
                    error_page(minimum, maximum)
                    continue
                if (int(num) == rand_num):
                    while True:
                        print("정답입니다!")
                        print("1. 다시하기")
                        print("0. 종료하기")
                        action = input()
                        if (action == "0"):
                            exit_page()
                        elif (action == "1"):
                            minimum = 1
                            maximum = 100
                            rand_num = random.randint(1, 100)
                            break
                        else:
                            error_page(0, 1)
                elif int(num) < rand_num:
                    minimum = int(num)
                    print("UP!")
                elif int(num) > rand_num:
                    maximum = int(num)
                    print("DOWN!")
        else:
            error_page(0, 1)

# Game Start
start()

'-- 기타 -- > IT KOREA 국비 지원 강의' 카테고리의 다른 글

@PathVariable  (0) 2024.03.11
Spring boot  (0) 2024.03.07
day067  (0) 2024.03.07
QnA  (0) 2024.03.06
[Spring] 자체 프레임워크로 이관  (0) 2024.03.05

@PathVariable

Command 객체 외에 해당 Controller 메서드에서 필요한 데이터를 View 측에서 전송한 경우

> 요청 경로에 보냄

View 측에서 전송한 데이터를 Controller 메서드에서 받기 위해 사용하는 어노테이션

> 메서드 인자에서 받음

'-- 기타 -- > IT KOREA 국비 지원 강의' 카테고리의 다른 글

[미니 프로젝트] UP & DOWN 게임 만들기  (0) 2024.05.04
Spring boot  (0) 2024.03.07
day067  (0) 2024.03.07
QnA  (0) 2024.03.06
[Spring] 자체 프레임워크로 이관  (0) 2024.03.05

src/main/resources

application.properties

- 컨테이너가 봐야 하는 설정을 알려줌

 

static

"정적" 웹 리소스들이 저장되는 공간

ex) html, css, js, img, ...

별도의 컴파일/파싱 등이 불필요한 파일들

 

src

"동적" 웹 리소스들이 저장되는 공간

 

maven의 pom.xml 역할 == build.gradle

라이브러리들 (.jar 파일들) 의존성 주입

'-- 기타 -- > IT KOREA 국비 지원 강의' 카테고리의 다른 글

[미니 프로젝트] UP & DOWN 게임 만들기  (0) 2024.05.04
@PathVariable  (0) 2024.03.11
day067  (0) 2024.03.07
QnA  (0) 2024.03.06
[Spring] 자체 프레임워크로 이관  (0) 2024.03.05

@Controller

인터페이스가 아니므로,

메서드 시그니쳐 강제성이 사라짐!

과거에는 req, res(servlet 관련)를 인자로 가지고 있으니까 완전한 POJO는 아니었음

사용자가 입력한 값들을 보관하는 역할의 req

 

바로 DTO를 받아올 수 있다

Command 객체

Spring 컨테이너

1) DTO(Command 객체)를 new해줌

1) req에 저장된 정보 중에 DTO 멤버변수와 같은 파라미터명이 있다면 해당 값 자동 추출

2) 추출한 값을 DTO 멤버변수에 set 가능 : setter 활용

'-- 기타 -- > IT KOREA 국비 지원 강의' 카테고리의 다른 글

@PathVariable  (0) 2024.03.11
Spring boot  (0) 2024.03.07
QnA  (0) 2024.03.06
[Spring] 자체 프레임워크로 이관  (0) 2024.03.05
[Spring] AOP  (2) 2024.02.29

Q1. 필터 클래스 등록하는게 헷갈려요!

1. 내가 등록하려는 클래스의 타입을 확인

2. POJO vs not POJO

- POJO

스프링 컨테이너

applicationContext.xml

dispatcher-servlet.xml

.jar >> pom.xml

 

- not POJO

서블릿, 필터, 리스너

서블릿 컨테이너

web.xml

 

3. POJO

DAO : @Repository

Service : @Service

Controller : @Controller

 

Q2. 현재 흐름을 이해하기 어렵습니다

웹의 흐름

요청 -> 응답

1. 사용자(브라우저, 클라이언트)가 요청

2. FrontController(DispatcherServlet)에서 요청을 확인

3. HandlerMapping으로 해당 요청에 대해서 어떤 Controller가 필요한지 확인

Controller를 반환

팩토리 패턴을 활용하여 요청(String)을 받으면 Controller(객체)를 반환

4. Controller는 메서드를 수행

Service -> DAO

String을 반환

5. ViewResolver가 Controller에서 반환된 String을 보고 사용자에게 VIEW 페이지를 응답

 

Q3. 의존 관계가 어려워요

 

DS <- HandlerMapping, ViewResolver

- init()으로 의존성 주입

 

HM

- Map<String, Controller> : 팩토리 패턴을 활용하기 위한 컬렉션

 

VR

- prefix, suffix

- setter로 의존성 주입 (필수가 아니라서 setter를 쓰는 경향이 있다)

'-- 기타 -- > IT KOREA 국비 지원 강의' 카테고리의 다른 글

Spring boot  (0) 2024.03.07
day067  (0) 2024.03.07
[Spring] 자체 프레임워크로 이관  (0) 2024.03.05
[Spring] AOP  (2) 2024.02.29
스프링 프레임워크  (1) 2024.02.28

패키지 관리

클래스 타입 중심 VS 기능 중심

Q. 왜 000 중심으로 패키지 관리 하셨어요?

 

버전01: 개발자가 직접 만든 DispatcherServlet 사용

우리가 만든 DispatcherServlet에는 다음 역할을 하는 init-method="init"

1. 멤버 변수 초기화

2. 생성자

3. setter

4. @Autowired

5. DI(의존성 주입)

6. init() 메서드

 

개발자가 직접 만든 Controller 인터페이스 사용

output이 ActionForward

 

버전02: Spring 프레임워크에서 제공하는 DispatcherServlet 사용

버전02에서도 DI를 위한 xml이 필요하다

dispatcher-servlet.xml

presentation layer(표현 계층)가 생겼다!

 

spring에서 제공하는 인코딩 필터를 쓰자

 

not POJO(Servlet, Filter, Listener)에 대한 객체 등록은 서블릿 컨테이너가 담당

서블릿 컨테이너의 설정 파일인 web.xml에서 해야한다!!!

 

View Resolver가 등장하면서 String으로 변경됨

어디로(경로), 어떻게(리다이렉트, 포워드)

기존에는 request를 통해 전달

현재는 ModelAndView 객체를 통해 전달

 

Spring에서 제공하는 HandlerMapping을 사용하면

DI로 setter 주입을 사용

 

특정 페이지의 URL을 알면 별도의 권한이 없어도 접근이 가능한 경우가 있다

이를 막기 위해 Controller 파트에서 별도의 접근 권한 유효성 검사를 구현해야만 한다

Spring에서는 애초에 페이지를 WEB-INF 폴더에 은닉(하이딩)하여 저장함

 

WEB-INF 폴더의 하위는 오직 VR을 통해서만 접근 가능함을 이용한 것!!

 

버전03: @ 추가

@Component + "implements Controller" => @Controller

@Override를 할 필요가 없어서 메서드 시그니처 강제가 안 된다

자유도가 높은 대신 개발자가 실수할 가능성이 생긴다

 

서로 관련된 기능을 작성할 수 있음 == 코드의 응집도가 높아짐

 

@RequestMapping(value="/login.do", method=RequestMethod.POST)

output으로 String 권장

요청 방식이 GET, POST, ...인지 쓰는 것을 권장

 

기타

중프 때 했던 비동기 Servlet -> 최프 때 Controller 흡수 예정

 

'-- 기타 -- > IT KOREA 국비 지원 강의' 카테고리의 다른 글

day067  (0) 2024.03.07
QnA  (0) 2024.03.06
[Spring] AOP  (2) 2024.02.29
스프링 프레임워크  (1) 2024.02.28
DI(Dependency Injection) 의존성 주입이란?  (0) 2024.02.27

공통 로직 == 횡단 관심

ex) 인증, 로깅, 트랜잭션, 예외처리

비즈니스 메서드 == 비즈니스 로직 == 핵심 관심 == CRUD에서 횡단 관심을 분리

관심 분리 (Separation of Concern) => AOP의 시작

로직끼리 코드를 관리하기 때문에 높은 응집도를 보장

 

공통 로직을 Advice라고 부름

 

1. 항상 찍는 로그는 공통로직

2. Advice 클래스로 분리 == 관심 분리

3. Advice를 Service의 멤버변수로 설정 -> 의존 관계 발생

4. 비즈니스 로직 수행 전에 호출

 

같은 기능, 같은 타입의 여러 객체 중에서 1개를 선택하는 경우 -> Complie을 다시 하지 않아도 되기 때문에 <bean> 방식이 유리

정해진 경우 -> @Component가 유리

 

<aop:config>

조인포인트

- 어플리케이션에 존재하는 모든 비즈니스 메서드

포인트컷

- 횡단 관심을 연결할 비즈니스 메서드

애스팩트(aspect)

- 포인트컷(핵심 로직)과 어드바이스(횡단 관심)의 조합

- 포인트컷과 어드바이스의 결합(위빙)

<aop:config>
	<aop:pointcut id="aPointcut" expression="execution(* com.spring.biz..*Impl.*(..))" />
	<aop:pointcut id="bPointcut" expression="execution(* com.spring.biz..*Impl.select*(..))" />

	<aop:aspect ref="logAdvice">
		<aop:before pointcut-ref="aPointcut" method="printLog" />
	</aop:aspect>
</aop:config>

 

Advice 동작 시점 종류

Aspect 설정할 때 함께 설정함

- before: 비즈니스 메서드 수행 전

- after: finally, 비즈니스 메서드 수행 후

- after-returning: 비즈니스 메서드 return 반환 후

- after-throwing: catch, 비즈니스 메서드 예외발생시

- around: 비즈니스 메서드 수행 전후로 접근가능, 핵심로직의 성능평가, 실 서비스에는 잘 없음

 

aop 설정 어노테이션으로 하기

<aop:aspectj-autoproxy>

 

바인드 변수

바인딩이란?

메서드를 호출했을 때, 현재 메모리에 존재하는 객체를 실제로 수행하는 것

다형성(상속)을 구현한 상황에서 사용 가능

 

 

'-- 기타 -- > IT KOREA 국비 지원 강의' 카테고리의 다른 글

QnA  (0) 2024.03.06
[Spring] 자체 프레임워크로 이관  (0) 2024.03.05
스프링 프레임워크  (1) 2024.02.28
DI(Dependency Injection) 의존성 주입이란?  (0) 2024.02.27
Spring 정리  (0) 2024.02.26

컨테이너

1. 톰캣: 서블릿 컨테이너, 웹 서버 (내장)

2. 스프링 컨테이너: POJO 클래스를 new 해줌 (ex. DAO, DTO, Action, ...)

3. 루트(최상위) 컨테이너: .jar(라이브러리)를 관리해줌, 설정 관련 컨테이너, 얘도 스프링 컨테이너라고 부름

 

pom.xml

설정 파일의 갯수 == 컨테이너의 갯수

1. 톰캣(web.xml)

2. 스프링 컨테이너(applicationContext.xml)

3. 루트 컨테이너(pom.xml)

 

스프링 프레임워크에서는 클릭하면 해당 라이브러리들을 알아서 주입해줌

다만 MySQL이나 최신 라이브러리들은 개발자가 추가로 설정해야할 수도 있음

톰캣을 내장 서버로 가지고 있음

 

xml 에 설정들이 많아지면

- 개발자에게 부담이 됨

- 작은 에러라도 발생한다면, 프로그램 실행이 안 된다

그래서 스프링에서 과도한 설정을 줄여주기 위해 @(어노테이션) 기능을 개발함

 

어노테이션

스프링은 xml과 어노테이션 모두 활용

스프링부트는 어노테이션 활용을 극대화함

 

어노테이션은 개발자 가독성이 증가하고

xml 접근을 줄여줌

java 파일에 작성함

 

@Component("name")

new 연산자 같은 역할

 

@Autowired

의존성 주입

메모리의 자료형을 인지하고 연결해주는 역할을 수행함

유니크 빈이 아니면 에러가 난다

이를 해결하기 위해 @Qualifier를 같이 해줌

 

@Qualifier("name")

빈이 여러개인 경우 이름을 지정하기 위해 사용

이 어노테이션이 없으면 유니크 빈이구나 유추 가능

 

@Service("name")

@Component를 상속받은 어노테이션

 

모델에 가까운 컨트롤러를 서비스라고 함

가독성이 좋아짐

 

스프링 컨테이너가 메모리 관리할 때, 같은 어노테이션끼리 묶어서 관리함

 

@Repository("name")

@Component를 상속받은 어노테이션

DAO 파트를 생성할 때 사용

'-- 기타 -- > IT KOREA 국비 지원 강의' 카테고리의 다른 글

[Spring] 자체 프레임워크로 이관  (0) 2024.03.05
[Spring] AOP  (2) 2024.02.29
DI(Dependency Injection) 의존성 주입이란?  (0) 2024.02.27
Spring 정리  (0) 2024.02.26
[디자인 패턴] MVC의 특징  (1) 2024.01.25

Dependency Injection

의존성 주입

주체가 개발자 -> 컨테이너(Spring framework)

 

의존성이란?

어떤 메서드를 수행할 때 다른 객체를 미리 new 해야하는 상황

 

1. 생성자 주입 (Constructor Injection)

생성자 주입은 2번 방식보다 더 강제성이 짙음

생성자 주입 할 때 에러가 발생하면 객체는 생성되지 않음 == 필수적일 때 사용하는 방식

 

2. Setter 주입 (Setter Injection)

1번 방식보다 덜 강제적임

기본 생성자와 함께 사용됨

'-- 기타 -- > IT KOREA 국비 지원 강의' 카테고리의 다른 글

[Spring] AOP  (2) 2024.02.29
스프링 프레임워크  (1) 2024.02.28
Spring 정리  (0) 2024.02.26
[디자인 패턴] MVC의 특징  (1) 2024.01.25
[문자인증 API] coolsms 이클립스 설정 (Java, maven, Spring)  (0) 2024.01.17

작년 말, 스프링부트2 deprecated

이관 작업할 사람을 많이 구했다

 

Spring 기반의 웹 프레임워크가 굉장히 많다

 

Spring 프레임워크가 뭔가요?

IoC와 AOP를 지원하는 경량의 프레임워크

 

1) IoC가 무엇인가요?

Inversion of Control

제어의 역행

Spring에서는 제어를 프레임워크에 맡길 예정

컨테이너를 통해 제어를 수행할 것임

컨테이너란? 객체를 생성하거나 객체를 관리하는 주체

관리란? 호출/소멸 시점을 정하는 것

 

웹서버, 톰캣 => 서블릿 컨테이너

서블릿만 생성 가능

 

Spring 프레임워크에서 사용하는 컨테이너 => Spring 컨테이너

POJO 생성 가능

코드에 new가 없는게 좋다

컨테이너가 하는게 좋다

C 파트는 new라는 연산자를 사용하지 않도록 한다

HM 안에 new 코드들 => 스프링 컨테이너가 대신 할 예정

 

2) AOP가 무엇인가요?

Aspect Oriented Programming

관점 지향 프로그래밍

 

- 절차 지향 프로그래밍: 순서대로 진행하는 방식, 일의 처리 순서가 가장 중요, 알고리즘이 중요, 성능-속도

- 객체 지향 프로그래밍: 모듈 단위로 코드를 구성하는 방식, 객체가 중요, 설계가 중요, 성능-메모리

- 관점 지향 프로그래밍

기존의 기능 개발은 "핵심 로직"을 중심으로 개발되었습니다

다양한 CRUD에 공통적으로 적용되는 로직을 따로 모듈화해서 저장, 호출 가능해짐

Spring 컨테이너가 AOP를 지원해주기 때문에 공통로직(횡단관심)을 별도의 클래스로 작성하게 됩니다

 

3) 경량이란 무엇인가요?

1. 다루는 객체가 가볍다 == POJO

2. 사용되는 메모리가 적다 == 싱글톤 패턴 활용

 

4) 프레임워크 vs 라이브러리 vs API

프레임워크를 활용했을 때의 장점이 무엇인가요?

SpringMVC 이미 적용된 프로젝트를 하나 생성해줌 == 구현이 빨라짐

개발자의 실력이 상향 평준화됨

일관성이 유지되기 쉬움

 

결합도를 낮추기 위한 개발자들의 다양한 노력

1. 인터페이스를 활용하는 방법

=> 객체가 변경되어도 메서드를 추가 변경하지 않아도 괜찮음

2. 팩토리 패턴을 활용하는 방법

=> 코드에 new가 없어짐 == 결합도가 낮아짐

모델

M SQL DAO

인자로 DTO

인자로 들어오는 DTO를 임의로 바꾸거나 값을 변경하면 안됨 => Ctrl가 DAO 진입 전에 전부 세팅해줘야 함!

 

V .jsp

JAVA가 보이면 안됨!

EL JSTL 커스텀태그

 

1. VC .jsp 같이 어떤 페이지를 보여주는 용도의 Action이 존재

2. MC 특정 DB의 데이터를 사용하는 용도의 Action이 존재

회사마다 스타일이 다르지만 우리 프로젝트에서는 MC는 사용 빈도가 높지 않으면 굳이 별도로 만들지 않음

API 인증키 받기

아래 사이트에서 회원가입 후 로그인

 

https://console.coolsms.co.kr/oauth2/login

 

COOLSMS - 알림톡과 문자메시지 발송, 최고의 안정성

 

console.coolsms.co.kr

 

우측 상단에 '개발/연동'에 'API Key 관리' 클릭

'새 API KEY 생성' 클릭

 

SDK 다운 받기

우측 상단에 '개발/연동'에 'SDK 다운로드' 클릭

 

Java용 SDK에서 '자세히' 클릭

'약관 동의 후 SDK 다운로드' 클릭

 

다운 받은 파일 압축을 해제하면 위와 같은 파일이 있음

우리는 'maven-spring-demo'를 활용할 예정

 

이클립스에 Spring 설치하기

상단 'Help'에 'Eclipse Marketplace...' 클릭

 

'spring' 검색하고 'install' 클릭

 

기존 프로젝트 Maven 프로젝트로 변경 및 pom.xml 수정

프로젝트에서 우클릭 후 'Configure' 선택 후 'Convert to Maven Project' 클릭

안내창 뜨면 'finish' 클릭

 

pom.xml 파일이 잘 생성됐는지 확인

 

아까 다운 받은 sdk에서 pom.xml을 프로젝트의 pom.xml에 복붙

 

예제 실행

이 페이지에 나온 예제를 활용해서 테스트

https://developers.coolsms.co.kr/sdk-list/Java/send-message

 

메시지 발송 예제 | Documents for COOLSMS Developers

해당 페이지에서는 COOLSMS Java/Kotlin SDK를 이용하여 메시지를 발송하는 방법에 대해 가이드하고 있습니다.

developers.coolsms.co.kr

 

저는 아래 코드에서 테스트 해봤습니다

DefaultMessageService messageService =  NurigoApp.INSTANCE.initialize("API 키 입력", "API 시크릿 키 입력", "https://api.coolsms.co.kr");
// Message 패키지가 중복될 경우 net.nurigo.sdk.message.model.Message로 치환하여 주세요
Message message = new Message();
message.setFrom("계정에서 등록한 발신번호 입력");
message.setTo("수신번호 입력");
message.setText("SMS는 한글 45자, 영자 90자까지 입력할 수 있습니다.");

try {
  // send 메소드로 ArrayList<Message> 객체를 넣어도 동작합니다!
  messageService.send(message);
} catch (NurigoMessageNotReceivedException exception) {
  // 발송에 실패한 메시지 목록을 확인할 수 있습니다!
  System.out.println(exception.getFailedMessageList());
  System.out.println(exception.getMessage());
} catch (Exception exception) {
  System.out.println(exception.getMessage());
}

위 코드를 main 함수가 있는 java 파일에 넣고

"API 키 입력", "API 시크릿 키 입력", "계정에서 등록한 발신번호 입력", "수신번호 입력"

위 4가지 요소만 수정해서 테스트 하니까 바로 동작했습니다

 

+ Recent posts