[ KOSTA 교육 46일차 ] @JsonIgnore | Spring WebMVC ( Spring Web ) | Spring Web 파일 업로드 + MyBatis와 연동 | OAuth와 REST | REST란? | 쿠키,세션 vs 토큰 | 구글 로그인 OAuth 플로우 흐름

junjun·2024년 7월 3일

KOSTA

목록 보기
44/48

@JsonIgnore

  • Controller에서 데이터를 Body에 담아 내보낼 때, (@ResponseBody) Jackson에게 해당 JSON을 직렬화/역직렬화 하지 않도록 지시하는 어노테이션입니다.

[ 파일 업로드 ]

Spring-WebMVC 의존성

<!-- spring-webmvc 설치 시 spring-web 자동 설치 : 파일 업로드 -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>${org.springframework-version}</version>
</dependency>
  • 파일 업로드는 spring web 이 지원하는 유틸 기능입니다.
  • spring webmvcspring-web을 의존하기에, maven에 의해 자동으로 spring-web 의존성을 다운로드 받을 수 있습니다.

Servlet에서 파일 업로드 시 사용 ( pom.xml )

<dependecy>
  <groupdId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>

Tomcat의 context.xml에서 allowCasualMultipartParsing 활성화

<Context allowCasualMultipartParsing="true">

Servlet-Context.xml에 MultipartResolver 등록

<bean id="multipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
      <property name="maxUploadSize"
		value="10000000" />
</bean>

ViewResolover는 Chaining이 가능하다.

  • JSP 관련 뷰를 렌더링해주는 ViewResolver를 등록할 수 있다.
  • 이와 마찬가지로 첨부파일 관련 뷰를 렌더링해주는 ViewResolver 또한 추가 가능하다.
  • PDF, Excel 형식의 파일 다운로드를 가능하게 해주는 ViewResolver 또한 추가할 수 있다.
  • 즉, 이런 ViewResolver들이 Chaining을 하여, Response로 내릴 데이터의 종류를 정할 수 있다.

[ 파일 업로드 Step By Step ]

0. 파일 업로드 관련 의존성 설정 / Tomcat 설정 / web.xml 설정 / Spring 설정

  • 위 내용의 설정과정을 통해
    1) maven을 통한 관련 의존성 설치 ( spring-web, commons-fileupload, commons-io )
    2) 웹 어플리케이션이 올라가는 Tomcat의 context.xmlallowCasualMultipartParsing 활성화
    3) 우리 웹 어플리케이션의 web.xml에 파일 업로드 필터 추가 [ 추후 블로그에 추가해야함 ]
    4) Tomcat이 우리 어플리케이션의 web.xml 을 보고 DispatcherServlet을 초기화시킬 때, 전달하는 매개변수인 servlet-context.xml에 multipartResolver를 빈으로 등록

이 네가지 단계를 완료했습니다.

1. DB에 File 테이블 정의 및 Board와의 관계 설정

  • 일단 맨 뒷단인 DB에 파일을 담을 테이블을 정의해주어야 합니다.

  • 파일은 PK인 시퀀스 번호(fseq), 파일 사이즈(fsize), 서버 or S3와 같은 파일 서버에 파일이 저장된 경로(fpath), 게시 날짜, 유저가 올린 파일 이름, 시스템에서 관리하는 파일 이름을 컬럼으로 가집니다.

    • 유저가 올린 파일 이름 ( = oname; original name )은 cc.txt와 같이 유저가 올리고, 그래서 인지하고 있는 유저의 파일 이름입니다.
    • 시스템이 관리하는 파일 이름 ( = sname; system name )은 여러 유저가 올린 파일들의 이름을 겹치지 않게 저장하도록 서버에서 생성한 파일 이름입니다. 겹치지 않게 하는 이유는, 파일 이름이 겹치면 파일이 덮어씌워지기 떄문입니다. ( 유저 A가 올린 cc.txt라는 파일 이름으로 우연히 유저 B가 올린다면, 유저 A의 파일은 지워지고 유저 B의 파일이 남을 것입니다. )
      • 주로 Java의 UUID API를 사용하여 이를 가능하게 합니다.

파일 테이블의 시퀀스와 파일 테이블을 생성해주는 DDL입니다.

create sequence board_file_seq start with 1 increment by 1 nocache;

create table board_file (
fseq number primary key,     --pk
oname varchar2(40),
sname varchar2(40),
fsize number default 0,
fpath  varchar2(50),
bseq  number,
regid varchar2(20) ,
regdate date default sysdate,
CONSTRAINT "FK_BFSEQ" FOREIGN KEY(bseq) REFERENCES BOARD(SEQ)
);
  • Board와 연결을 위해 FK 제약조건을 사용하였습니다.
  • 파일은 게시물에 첨부파일 형식으로 속하는 관계를 가집니다. ( 1:1 or N:1 )

2. 파일 첨부 가능한 form 작성

  • DB가 완성되었으니, 웹 서비스의 시작점부터 진행합니다.
  • 일단, 웹 앱의 클라이언트 ( 프론트앤드 )에서 첨부파일을 포함한 데이터를 전송할 수 있어야합니다.
<!-- 파일 업로드에서 enctype(인코딩 타입)을 multipart/form-data로 반드시 설정해야함 -->
<form action="/file_upload" method="post" enctype="multipart/form-data">
  파일 선택 : <input type="file" name="ufile">
  <input type="submit" value="전송">
</form>

<!-- 파일 두개 이상 붙이기 -->
<form action="/file_upload2" method="post" enctype="multipart/form-data">
  파일 선택 : <input type="file" multiple="multiple" name="ufiles">
  <input type="submit" value="전송">
</form>
  • enctype 속성을 꼭 multipart/form-data라 해주어야 합니다.
  • multiple 속성을 "multiple"로 지정 시, 복수 파일이 업로드 됩니다.

3. Controller 단에서 File 받기

  • FE에서 데이터를 보내는 것은 완성했으니, 이제 서버에서 해당 데이터를 받는 방법을 생각해야 합니다.
  • Spring MVC Framework의 도움을 받아, @RequestParam을 사용하여 데이터를 받아옵니다.
@RequestMapping(value = "/board_insert", method = RequestMethod.POST )
public String boardInsert(@ModelAttribute BoardVO bvo, @RequestParam("file") MultipartFile file){
	
    // 파일 업로드 로직
}
  • 여러 개의 파일 업로드 시, List<MultipartFile>로 타입을 설정해주면 됩니다.

4. MyBatis와 연동

  • 컨트롤러까지 데이터가 왔으니, 이를 비즈니스 로직을 통해 가공 및 영속화하는 것을 신경써야 합니다.( Model )

  • DB 접근 기술로 MyBatis를 선택했으니, 이를 통해 서비스를 구성하기 위해 Mapper I/F 및 XML 파일을 정의해줍니다.

  • 그 이전에, MyBatis에서 @Mapper 로 설정한 인터페이스와 실제 SQL이 저장된 XML을 스프링이 인식하고 찾을 수 있도록, DispatcherServlet의 servlet-context.xml 에 다음과 같은 설정을 추가합니다.

<!-- MYBATIS SqlSessionFactory , SqlSessionTemplate -->
	<!-- Mapper XML을 찾는 역할 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- <property name="dataSource" ref="myDS_CONSOL_PRINT" /> -->
		<property name="dataSource" ref="MY_tomcat_ds" />
		<property name="mapperLocations" value="classpath:lec12-mappers/*-map.xml" />
	</bean> 
	
	<!-- 어플리케이션 코드에서 @Mapper 찾기 어노테이션 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.lec12.web"/>
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
	</bean>

4-1. 매퍼 인터페이스는 다음과 같습니다 ( 추가 예정 )

4-2. 매퍼 XML은 다음과 같습니다 ( 추가 예정 )

4-3. association 관계와 collection 관계, mapper 상세 내용 ( 추가 예정 )

4-4. MYBATIS : useGeneratedKeys, selectKey 속성의 효용성 ( 추가 예정 )

5. Application Logic 부분 작성 ( 추가 예정 )

5-1. 트랜잭션 중 파일 업로드 실패 시, 파일 삭제 여부 ( 추가 예정 )

  • 반반

OAuth와 REST

  • OAuth 토큰 ( 토큰 vs 세션 )
    • 일반적인 웹 서비스 vs 분산 웹 서비스 (REST)

REST

  • 면접 질문 : REST란 무엇인가요?

짧은 버전

분산된 서비스 환경에서
제 3의 서비스들의 도움을 받아
우리 서비스를 구성하는 기술, 구조적 형태를 REST라 합니다.

좀 더 긴 버전

(앞부분 내용) +
REST 방식의 서비스 구성은 일반적으로 HTTP 프로토콜을 사용하는데요,
일반적인 웹 서비스와 가장 큰 차이점은 세션이 아닌 토큰을 통해 서비스를 제공받는다는 것입니다.
통신 방법은 대부분 비동기적 통신으로 이루어지며,
전송받는 데이터는 JSON/XML 등의 타입이며, 주로 JSON 데이터 형식을 사용하여 통신합니다.

일반적인 웹 서비스와 REST 웹 서비스의 차이?

  • 인증/인가에 대해 세션 없이 토큰을 가지고 사용하는 것이 가장 큰 차이입니다.

  • REST API

    • 일반적인 웹 서비스는 세션, 쿠키를 사용합니다.
    • REST에서는 다른 서비스에서 데이터를 가져오기 위해 토큰을 사용합니다.
  • REST => JSON/XML으로 데이터를 주고받는게 정해짐 ( 일반적 웹 서비스는 String, Binary도 주고받기 가능 )

    • 서비스를 제공해주는 쪽 ( 프로바이더 )가 요청하라는 방식에 맞게 요청해야하고, 그렇게 하면 토큰을 받아 해당 프로바이더의 서비스를 이용할 수 있음.
    • 토큰을 받는 과정, 절차를 OAuth라고 합니다.

토큰

  • 남의 서비스 (REST 서비스) 이용하려면 토큰을 사용해야 한다.
  • 은행 서비스를 이용하기 위해 필요한 신분증과 같은 역할
  • 국민은행 가면 국민은행 신분증, 우리은행가면 우리은행 신분증
    신분증을 발급받는 절차도 다르다.
    땅문서를 달라고 하면 땅문서를 줘야하고, 자동차 운전면허증을 달라하면 운전면허증을 줘야한다.
  • 일정 시간이 지나면 재발급 해야함.

OAuth 플로우와 토큰, 그리고 REST

  • OAuth 플로우를 거쳐 제 3의 서비스로부터 Token을 받아올 수 있습니다.
  • OAuth-REST
    - REST Service를 이용하려면 Token이 필요한데, 이 Token을 받는 과정, 절차가 OAuth입니다.

OAuth는 크게 두가지 플로우로 이루어집니다.

1. 사용자(Resource Owner)의 동의를 얻는 과정 = Code를 받는 과정

  • 예시로 든 구글 로그인의 경우, 우리 WAS가 구글로부터 code를 받는 과정

  • 사용자와 구글 로그인 페이지와의 상호작용이 있고, 이를 통해 구글은 우리 서버에게 code를 넘겨줍니다.

2. Code를 통해 Google이 WAS에게 사용자 정보를 주는 과정

  • 우리 WAS가 1번 과정을 통해 전달받은 code를 사용하여 구글에 scope 범위 만큼의 사용자 정보를 요청하고, 받아 사용하는 과정

  • 사용자는 내부 동작 과정에 대해 인지하지 못함, WAS와 구글 서버간의 일임.

  • code를 받을 때까지는 Google의 OAuthService와 통신했지만, OAuthService로 부터 code를 발급받은 이후로는 Resource Service 등, 자원을 관리하는 구글의 서비스에 code를 들고 접근하여 사용자 정보를 받아옴.

0개의 댓글