ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 0921. 회원가입정보 저장하기
    카테고리 없음 2023. 9. 21. 18:35

    Ajax

    Asynchronous 비동기

     

    *모든 I/O 자바스크립트는 비동기 (통신)

     

    JSON

    서버로부터 데이터를 받으려면 요청을 보내야 서버가 응답을 할 때 응답 속에 데이터가 들어있다.

     

    <보통>

    1. 브라우저 창에 주소 입력

    2. <a> 주소 지정

    3. form = action에 주소 지정

    => 요청하면 브라우저가 페이지를 바꿔서 다시 렌더링을 해야하는 번거로움이 있다.

     

    전체 페이지는 유지하면서 페이지변경은 안 하고(브라우저가 현재 페이지 유지)

    그럼 브라우저 자체가 요청을 보낼 수는 없고(그럼 바뀜)

    자바스크립트가 서버와 개별통신을 하면 (요청 & 응답) 수신한 데이터를 가공해서 동적으로 화면에서 동조작을 통해 업데이트 하는 것이다.

    ex) 지도, 메일, 댓글처리

    => 거의 대부분 Ajax 기술을 내포

     

     

    SignUp(회원가입)

    유효성 맞다고 바로 insert할 수 없다.

    직접 해야하는 작업이 있기 때문이다.

     

    1. 유효성 검사(자동화되어있음)

    2. 추가 유효성 검사 (1번의 @Valid로 기본 체크가 되지 않는 사항들) : 비밀번호 확인, 아이디 중복확인 

    3. 확인 후 직접 에러 추가 (@Valid 뒤에 Errors 인터페이스 객체)

     - 전역 에러 : 필드에서 걸렀는데 수용할 수 없는 것들 => 로그인 시 비밀번호와 아이디가 안 맞는 경우

    *reject(에러코드, 메시지)

    필드 상관없으므로 필드 인자는 필요 x 

    - 필드 에러 : 특정 필드만

    *rejectValue(필드, 에러코드, 메시지)

     

    +) errors.hasErrors() : 전체적으로 에러가 있는지

    +) errors.hasFieldErrors() : 특정 구간에 에러가 존재하는지

     

    유효성 검사가 끝나면 실제 저장을 해야 한다. "2번"

    1. Member_tbl : 비밀번호 암호화(비밀번호 인코더를 @Bean으로 등록했는데 Service에서 @Autowired로 사용하면 된다.)

    2. Auth_tbl : 

     

    아바타 이미지 업로드


    🖤비밀번호 확인할 때 실제 사용 예

    모델 객체 설계

    우리는 DB에 있는 테이블을 염두에 두고 해당 컬럼의 정보를 담을 수 있도록 모델을 설계했다.

    (기존에는 signup을 있던 모델에 추가)

    그래서 화면에 form을 submit했을 때 전송되면 modelAttribute로 자동으로 채워지는 기법을 사용했다.

    그래서 form에서 입력받는 것과 테이블 내용이 일치한다.

     

    그런데, form의 필드와 테이블의 컬럼이 일치하지 않는 경우가 있다.

    이 경우 모델 객체를 설계할 때는 상황에 따라 맞춰야 한다.

    DB에 저장을 쉽게하기 위해 DB에 맞추면 form과 일치가 어렵고, form에 맞추면 submit해서 form정보 받아들이긴 쉬우나 DB에 저장할 때 문제가 생길 수 있다.

     

    [상황]

    Password2 (비밀번호확인) : 테이블에 존재하지 않음

    비밀번호 변경시 : 기존 비밀번호 / 새 비밀번호 / 새 비밀번호 확인 필요

     

    [권장사항]

    모델객체를 각자 따로 만드는 게 좋다.

    DB에 맞추는 것, form에 맞추는 것 (서로 변환해서 쓰기)

    DB 모델 특화 : VO

    form 모델 특화, view출력 : DTO(Data transfer object) / view를 위해서 만든 모델일 때 VM(view model)이라고도 쓴다.

     

    - Mybatis는 xml 기반 맵핑이라 XRM(xml relational mapping)이라 굳이 둘로 나누지 않아도 쓴다.

    - ORM(object relational) 은 객체를 관계 테이블로 맵핑하겠다는 뜻이라 VO 객체가 자동으로 테이블에 반영이 된다.
    VO 객체의 클래스명 = 테이블명/ VO객체의 필드명 = 테이블의 컬럼명 : SQL 문을 안 쓰고 객체의 메서드로 처리함
    그래서 VO와 DTO를 명확히 구분짓고 변환해서 사용하도록 운영해야 한다.

     DB에 회원가입 정보 저장하기

     

    인터페이스 MemberMapper

    package org.galapagos.mapper;
    
    import org.galapagos.domain.AuthVO;
    import org.galapagos.domain.MemberVO;
    
    public interface MemberMapper {
    	
    	public MemberVO read(String username);
    	
    	public void insert(MemberVO member); //member tbl에 대한 insert
    	
    	public void insertAuth(AuthVO auth);//auth tbl insert
    	
    	
    }

     

    MemberMapper.xml

    	<insert id="insert">
    		insert into tbl_member(username, password, email)
    		value(#{username}, #{password}, #{email})
    	</insert>
    	
    	<insert id="insertAuth" >
    		insert into tbl_member_auth(username, auth)
    		values(#{username}, #{auth})
    	</insert>

     

     

    MemberServiceImpl 구현체

    package org.galapagos.service;
    
    import org.galapagos.domain.AuthVO;
    import org.galapagos.domain.MemberVO;
    import org.galapagos.mapper.MemberMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.stereotype.Service;
    
    import lombok.extern.log4j.Log4j;
    
    @Service
    @Log4j
    public class MemberServiceImpl implements MemberService {
    	
    	@Autowired
    	MemberMapper mapper;
    	
    	@Autowired
    	private PasswordEncoder pwEncoder;
    	
    	@Override
    	public MemberVO get(String username) {
    		return mapper.read(username);
    	}
    	
    	@Override
    	public void register(MemberVO member) {
    		//1. 비밀번호 암호화
    		String encPassword = pwEncoder.encode(member.getPassword());
    		member.setPassword(encPassword);
    		
    		//2. tbl_member에 저장
    		mapper.insert(member);
    		
    		//3. tbl_member_auth에 저장(#{username} Foreign key 때문에 먼저 저장하면 에러)
    		AuthVO auth = new AuthVO(member.getUsername(), "ROLE_USER");
    		
    		//4. 아바타 이미지 저장
    		
    	}
    
    }

    *인메모리에서는 ROLE_MEMBER지만

    DB 에는 ROLE_USER

     

     

    SecurityController에서 호출

    		// DB 저장
    		service.register(member);
    		
    		return "redirect:/";

     

     


    썸네일 이미지

     

    아바타 이미지 하나 준비해서 temp 폴더에 저장

     

     

    Upload 폴더에는 avatar 폴더 하나 만들기 

    테스트 영역에 AvatarTest

    package org.galapagos.security;
    
    import org.galapagos.config.RootConfig;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {
    		RootConfig.class,
    		SecurityConfig.class
    })
    public class AvatarTest {
    	//업로드할 디렉토리 상수영역 정하기
    	public static final String AVATAR_UPLOAD_DIR = "c:/upload/avatar";
    
    	@Test
    	public void testUpload() {
    		
    	}
    }

    파일 업로드 코드 추가 

    @Test
    	public void testUpload() throws IOException { //파일 저장이니 예외처리 필수
    		String username = "unknown";
    		
    		File src = new File("c:/Temp/ninja.jpg");
    		File dest = new File(AVATAR_UPLOAD_DIR, username + ".png"); //해당 경로에서 양식에 맞게 저장해 주는 역할
    		
    		Thumbnails.of(src)
    			.size(50, 50)
    			.toFile(dest);
    	}

     

    Junit Test 해 주면 지정한 경로 폴더에 이렇게 png 확장자로 지정한 이름형식과 함께 파일이 하나 생긴다!

    unknown


    회원가입할 때 아바타 이미지 같이 등록되게 처리하기

     

    ex01에서 가져오기

     

    signup.jsp 의 form 에 추가 (인코딩 타입 지정하는 파트)

    이메일 form 밑에 input 타입으로 아바타 하나 추가

    여기서 avatar는 controller 에서 따로 처리할 것 

    name은 avatar

    SecurityController 의 Errors 뒤에 추가해서 받기

    >> MultipartFile avatar

    이제 register 할 때 아바타도 매개변수로 추가해야 함 

    에러가 나니, name과 이름이 같도록 추가하기

    signup.jsp 에서의 name과 같도록 

     

    MemberService 


    MemberServiceImpl

    매개변수 수정

    추가로 AvatarTest에서 쓴 상수를 맨 위에 복사해 오기 

     

    destination 부분도 복사해 와서 멤버명 수정하기

    파란 블록 부분 username에서 수정함

    thumbnail 도 추가하고 예외 던지기

    인터페이스와 안 맞아 에러가 발생하는 것이니 Controller, 인터페이스 수정 

     

    인터페이스
    컨트롤러

     

     

    🐲403 에러가 뜨는데 security 필터 문제이다

    회원가입을 할 때..multipart form(첨부파일 같이 넣느라)이라서 csrf 토큰이 없는 걸로 해석해서 403에러가 뜨는데

    csrf를 필터로 캐릭터 앞에 배치해야 하거나 이렇게 쿼리문으로 "?" 작성해야한다.

     

    https://shinsunyoung.tistory.com/78

     

    Spring Security로 로그인/회원가입 프로젝트

    안녕하세요! 이번 포스팅에서는 Spring Security에 대해 알아보겠습니다. 🤗 Spring Security는 정말 자주 사용하는 기능이자 그만큼 중요하기 때문에 전체적인 내용을 복습할 겸 잊어버리지 않기 위해

    shinsunyoung.tistory.com

    signup.jsp 에 기존 hidden 삭제

    action으로 csrf 토큰 추가 

     

     

    🐲+) 2개 이상의 update문을 실행할 때(insert 2개 등)는 transaction 처리를 해야 한다. 에러나면 rollback해야 되니

     

    menu.jsp 에서 랜덤으로 했던 아바타 이미지 바꾸기

    경로 설정

    sm : 아바타 크기 (작은 아바타) 더 크면 md, big 

     

    경로에 있는 변수 : Path Variable

    <!--menu.jsp-->
    <li class="nav-item">
    					<a class="nav-link" href="#">
    					<img src="/security/avatar/sm/${username}" class="avatar-sm" /> 
    					${username}
    					</a>
    				</li>

     

     

    글쓰기 버튼은 로그아웃상태에서 보이게만 하고 누르면 로그인이 필요한 서비스입니다 라고 뜨게 한다.

     

     

     

     

Designed by Tistory.