웹 서 비 스 를 이해 하 는 것 은 CXF 프레임 워 크 를 바탕 으로 [JAX - RS] 를 실현 합 니 다.

머리말
이전 글 에서 우 리 는 JAX - WS 가 SOAP (간단 한 대상 방문 프로 토 콜) 를 바탕 으로 XML 데이터 형식 으로 원 격 호출 할 수 있다 는 것 을 알 고 있 습 니 다. WSDL 문 서 는 데이터 분석 형식 과 요 구 를 정확하게 이해 하 는 데 도움 을 줄 수 있 습 니 다. 관심 이 있 는 학생 들 은 한 글 을 클릭 하여 WebService 가 CXF 프레임 워 크 를 바탕 으로 [JAX - WS] 를 실현 하 는 것 을 알 수 있 습 니 다.
Restful 컨 셉 이 뭐 예요?
REST 는 모두 Representational State Transfer (서술 적 상태 이전) 라 고 부 르 며 소프트웨어 구조 스타일 로 디자인 원칙 과 제약 조건 을 제공 했다.이 는 주로 클 라 이언 트 와 서버 의 상호작용 류 소프트웨어 에 사용 되 는데 이 스타일 을 바탕 으로 설정 한 소프트웨어 는 간결 하고 차원 이 있 으 며 실현 하기 쉽다.
Restful 스타일 의 서비스 가 무엇 입 니까?
REST 는 본질 적 으로 URL 을 사용 하여 자원 에 접근 하 는 방식 이다.전체적으로 알 수 있 듯 이 URL 은 우리 가 평소에 사용 하 는 요청 주소 입 니 다. 그 중에서 두 부분 을 포함 합 니 다. 요청 방식 과 요청 경로 입 니 다. 흔히 볼 수 있 는 요청 방식 은 GET 와 POST 이지 만 REST 에서 다른 몇 가지 다른 유형의 요청 방식 을 제 시 했 습 니 다. 모두 6 가지 가 있 습 니 다. GET, POST, PUT, DELETE, HEAD, OPTIONS 입 니 다.특히 앞의 네 가지 조작 은 바로 CRUD (첨삭, 개조) 네 가지 조작 과 대응 된다. GET (조사), POST (증가), PUT (수정), DELETE (삭제) 는 바로 REST 의 오묘 한 점 이다!
실제로 웹 응용 프로그램의 가장 중요 한 REST 원칙 은 클 라 이언 트 와 서버 간 의 상호작용 이 요청 사이 에 무상 태 라 는 것 이다. 클 라 이언 트 가 언제든지 요청 을 서버 로 보 내 고 원 하 는 데 이 터 를 되 돌 릴 수 있 기 때문이다.즉, 서버 에서 내부 자원 을 REST 서 비 스 를 발표 하고 클 라 이언 트 가 URL 을 통 해 이러한 자원 을 방문 하 는 것 이 바로 SOA 가 제창 하 는 '서비스 대상' 사상 이 아 닙 니까?그래서 REST 도 사람들 에 게 경량급 SOA 실현 기술 로 간주 되 기 때문에 기업 급 응용 과 인터넷 응용 에서 널리 사용 되 었 다.
요약:
  • Rest 는 강제 적 인 요구 가 아니 라 인 코딩 규범 이다
  • Rest 가 데이터 에 대한 제약 은 표준 xml 와 json
  • 이다.
    Spring, JAX - RS 구현 [복사 즉시 사용]
    서버 구축
    공용 설정 pom. xml 의존
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.zjf</groupId>
      <artifactId>jaxrs-parent</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>pom</packaging>
      <name>jaxrs-parent</name>
      <modules>
      	<module>rs-server</module>
      	<module>rs-client</module>
      </modules>
      
     <properties>
    		<junit.version>4.12</junit.version>
    		<spring.version>4.2.4.RELEASE</spring.version>
    	</properties>
    	
    <dependencyManagement>
    	<!--cxf jax-rs start -->
    	<dependencies>
    		<dependency>
    			<groupId>org.apache.cxf</groupId>
    			<artifactId>cxf-rt-transports-http</artifactId>
    			<version>3.1.7</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.apache.cxf</groupId>
    			<artifactId>cxf-rt-frontend-jaxrs</artifactId>
    			<version>3.1.7</version>
    		</dependency>
    <!-- 		<dependency> -->
    <!-- 			<groupId>org.apache.cxf</groupId> -->
    <!-- 			<artifactId>cxf-rt-transports-http-jetty</artifactId> -->
    <!-- 			<version>3.1.1</version> -->
    <!-- 		</dependency> -->
    
    		<dependency>
    			<groupId>org.codehaus.jettison</groupId>
    			<artifactId>jettison</artifactId>
    			<version>1.3.7</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.apache.cxf</groupId>
    			<artifactId>cxf-rt-rs-client</artifactId>
    			<version>3.1.7</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.cxf</groupId>
    			<artifactId>cxf-rt-rs-extension-providers</artifactId>
    			<version>3.1.7</version>
    		</dependency>
    <!-- 		<dependency> -->
    <!-- 			<groupId>org.apache.axis2</groupId> -->
    <!-- 			<artifactId>axis2-jaxws</artifactId> -->
    <!-- 			<version>1.6.2</version> -->
    <!-- 			<scope>runtime</scope> -->
    <!-- 			<exclusions> -->
    <!-- 				Causes java.lang.NoSuchMethodError: javax.ws.rs.core.Response$Status$Family.familyOf(I)Ljavax/ws/rs/core/Response$Status$Family; -->
    <!-- 				<exclusion> -->
    <!-- 					<groupId>javax.ws.rs</groupId> -->
    <!-- 					<artifactId>jsr311-api</artifactId> -->
    <!-- 				</exclusion> -->
    <!-- 			</exclusions> -->
    <!-- 		</dependency> -->
    		
    		<!-- cxf jax-rs end -->
    
    
    		<!-- Spring -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-context</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-beans</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<!-- <dependency> -->
    		<!-- <groupId>org.springframework</groupId> -->
    		<!-- <artifactId>spring-webmvc</artifactId> -->
    		<!-- <version>${spring.version}</version> -->
    		<!-- </dependency> -->
    		<!-- <dependency> -->
    		<!-- <groupId>org.springframework</groupId> -->
    		<!-- <artifactId>spring-jdbc</artifactId> -->
    		<!-- <version>3.2.13.RELEASE</version> -->
    		<!-- </dependency> -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-web</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<!-- <dependency> -->
    		<!-- <groupId>org.springframework</groupId> -->
    		<!-- <artifactId>spring-aspects</artifactId> -->
    		<!-- <version>${spring.version}</version> -->
    		<!-- </dependency> -->
    		<!-- <dependency> -->
    		<!-- <groupId>org.springframework</groupId> -->
    		<!-- <artifactId>spring-jms</artifactId> -->
    		<!-- <version>${spring.version}</version> -->
    		<!-- </dependency> -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-context-support</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-test</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    
    
    
    		<dependency>
    			<groupId>junit</groupId>
    			<artifactId>junit</artifactId>
    			<version>4.9</version>
    		</dependency>
    		<dependency>
    			<groupId>com.alibaba</groupId>
    			<artifactId>fastjson</artifactId>
    			<version>1.2.28</version>
    		</dependency>
    		<dependency>
    			<groupId>javassist</groupId>
    			<artifactId>javassist</artifactId>
    			<version>3.11.0.GA</version>
    		</dependency>
    		<dependency>
    			<groupId>commons-codec</groupId>
    			<artifactId>commons-codec</artifactId>
    			<version>1.10</version>
    		</dependency>
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>servlet-api</artifactId>
    			<version>2.5</version>
    			<scope>provided</scope>
    		</dependency>
    
    
    		<!--   -->
    		<dependency>
    			<groupId>log4j</groupId>
    			<artifactId>log4j</artifactId>
    			<version>1.2.17</version>
    		</dependency>
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-api</artifactId>
    			<version>1.7.25</version>
    		</dependency>
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-log4j12</artifactId>
    			<version>1.7.25</version>
    			<scope>test</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-simple</artifactId>
    			<version>1.7.25</version>
    			<scope>test</scope>
    		</dependency>
    	
    
    
    
    		<!-- <dependency> <groupId>javax.ws.rs</groupId> <artifactId>jsr311-api</artifactId> 
    			<version>1.1.1</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> 
    			<artifactId>cxf-rt-transports-http</artifactId> <version>3.1.7</version> 
    			</dependency> -->
    
    
    		<dependency>
    			<groupId>org.apache.httpcomponents</groupId>
    			<artifactId>httpclient</artifactId>
    			<version>4.3.6</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.httpcomponents</groupId>
    			<artifactId>httpcore</artifactId>
    			<version>4.3.3</version>
    		</dependency>
    	</dependencies>
    </dependencyManagement>
    
    </project>
    

    웹. xml 설정
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
      <display-name>Archetype Created Web Application</display-name>
      
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
      </context-param>
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
     
      <servlet>
        <servlet-name>cxfservlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>cxfservlet</servlet-name>
        <url-pattern>/rs/*
      
    
    
    

    차단 / rs URL 요청
    서버 설정 xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:cxf="http://cxf.apache.org/core"
    	xmlns:jaxrs="http://cxf.apache.org/jaxrs"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    		 http://cxf.apache.org/core
            http://cxf.apache.org/schemas/core.xsd
    		http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd ">
    
    	<!--
    		address        
    		servicesBeans       
     	 -->
    	<jaxrs:server id="userService" address="/userService" >
    		<jaxrs:serviceBeans>
    			<bean class="com.zjf.service.impl.UserServiceImpl" />
    		</jaxrs:serviceBeans>
    		<!--     -->
    		<jaxrs:inInterceptors>
    			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
    		</jaxrs:inInterceptors>
    		<jaxrs:outInterceptors>
    			<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
    		</jaxrs:outInterceptors>
    	</jaxrs:server>
    
    	
    </beans>
    

    Rest 스타일 서비스 인터페이스
    package com.zjf.service;
    
    import java.util.List;
    
    import javax.ws.rs.Consumes;
    import javax.ws.rs.GET;
    import javax.ws.rs.POST;
    import javax.ws.rs.PUT;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    
    import com.zjf.pojo.User;
    
    @Path("/userService")
    @Produces("*/*")
    public interface UserService {
    
    	@Path("/add")
    	@POST
    	@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    	public void saveUser(User user);
    
    	@Path("/update")
    	@PUT
    	@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    	public void upUser(User user);
    
    	@Path("/get")
    	@GET
    	@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    	public void getUser();
    
    	@Path("/find/{id}")
    	@GET
    	@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    	public User findUser(@PathParam("id") Integer id);
    
    	@Path("/list")
    	@GET
    	@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    	public List<User> listUser();
    
    }
    

    인터페이스 설명:
  • @ path: 현재 인터페이스의 URL 주 소 를 방문 하 는 것 을 의미 합 니 다. 주소 뒤에 전달 되 는 인자
  • 가 있 습 니 다.
  • @ GET | @ POST 표시 요청 방식 (GET 는 조회, POST 는 추가)
  • @ PUT 는 요청 방식 (데이터 수정 을 위 한 요청 URL)
  • @ DELETE 는 주로 데이터 삭제 작업
  • 에 사 용 됩 니 다.
  • @ Consumes 는 입력 (호출 방 입력) 의 매개 변수 형식 을 정의 합 니 다. (이 주 해 는 XML 과 JSON 의 형식 을 동시에 지원 한 다 는 뜻 입 니 다)
  • Produces 는 출력 (호출 자 에 게 돌아 가기) 의 데이터 형식 을 정의 합 니 다
  • 기타 매개 변수: @ PathParam (인터페이스 매개 변수 바 인 딩), @ FormParam (폼 매개 변수), 그 밖 에 @ QueryParam (요청 매개 변수)
  • 도 있 습 니 다.
    Rest 스타일 서비스 인터페이스 구현 클래스
    package com.zjf.service.impl;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.stereotype.Service;
    
    import com.zjf.pojo.User;
    import com.zjf.service.UserService;
    
    @Service
    public class UserServiceImpl implements UserService {
    
    	public void getUser() {
    		// TODO Auto-generated method stub
    		System.out.println("  User  ");
    
    	}
    
    	@Override
    	public void saveUser(User user) {
    		// TODO Auto-generated method stub
    		System.out.println("  User  :" + user.getName());
    
    	}
    
    	@Override
    	public void upUser(User user) {
    		// TODO Auto-generated method stub
    		System.out.println("  User  :" + user.getName());
    	}
    
    	@Override
    	public User findUser(Integer id) {
    		// TODO Auto-generated method stub
    		System.out.println("  User  :" + id);
    		User user = new User();
    		user.setName("  ");
    		user.setAge(19);
    		return user;
    	}
    
    	@Override
    	public List<User> listUser() {
    		// TODO Auto-generated method stub
    		List<User> list = new ArrayList<>();
    		for (int i = 0; i < 10; i++) {
    			User user = new User();
    			user.setName("  " + i);
    			user.setAge(20);
    			list.add(user);
    
    		}
    		return list;
    	}
    
    }
    
    

    실체 개체 파라미터 처리
    @XmlRootElement(name = "User")
    public class User implements Serializable {
    

    @ XmlRootElement 지정 직렬 화 (xml; json) 대상 이름
    클 라 이언 트 구축
    spring 기반 설정
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
    	xmlns:jaxrs-client="http://cxf.apache.org/jaxrs-client" 
    	xsi:schemaLocation="
    	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    	http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
    	http://cxf.apache.org/jaxrs-client http://cxf.apache.org/schemas/jaxrs-client.xsd"> 
            
    
    	<jaxrs-client:client id="webClient"
             address="http://localhost:8080/rs-server/rs/userService/userService/add"
             serviceClass="org.apache.cxf.jaxrs.client.WebClient">
        </jaxrs-client:client>
    
    </beans>
    

    CXF 프레임 워 크 클 라 이언 트 기반 웹 클 라 이언 트
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class clientTest {
    
        //  spring   CXF   
    	@Autowired
    	private WebClient webClient;
    
    	@Test
    	public void addUser() {
    		User user = new User();
    		user.setName("  ");
    		user.setAge(18);
    
    		Response post = WebClient.create("http://localhost:8080/rs-server/rs/userService/userService/add")
    				.type(MediaType.APPLICATION_JSON).post(user);
    		System.out.println("      :" + post.getStatus());
    
    	}
    
    	@Test
    	public void addUser1() {
    		User user = new User();
    		user.setName("  ");
    		user.setAge(18);
    		Response post = webClient.type(MediaType.APPLICATION_JSON).post(user);
    		System.out.println("      :" + post.getStatus());
    	}
    
    	@Test
    	public void findUser() {
    
    		User user = WebClient.create("http://localhost:8080/rs-server/rs/userService/userService/find/1")
    				.accept(MediaType.APPLICATION_JSON).get(User.class);
    		System.out.println(user);
    
    	}
    
    	@Test
    	public void listUser() {
    		Collection<? extends User> collection = WebClient
    				.create("http://localhost:8080/rs-server/rs/userService/userService/list")
    				.accept(MediaType.APPLICATION_JSON).getCollection(User.class);
    
    		System.out.println(collection);
    
    	}
    
    }
    
    

    WebClient 는 Spring 설정 을 통 해 만 들 수도 있 고 create ("접근 경로") 정적 방법 으로 만 들 수도 있 습 니 다. 정적 방법 을 통 해 실제 JAXRSClient Factory Bean 대상 을 통 해 만 들 수도 있 습 니 다.
    접근 URL 구체 적 인 단계 경로
  • 서버 프로젝트 주소 방문:http://localhost:prot/프로젝트 명 /
  • 서버 웹. xml 설정 CxfServlet 차단
  •  <servlet>
        <servlet-name>cxfservlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>cxfservlet</servlet-name>
        <url-pattern>/rs/*
      
    
  • 서버 spring 설정 노출 address 서비스 주소
  • <jaxrs:server id="userService" address="/userService" >
    
  • 서비스 인터페이스 클래스 이름 경로 @ Path ("/ 경로")
  • @Path("/userService")
    @Produces("*/*")
    public interface UserService {
    
  • 구체 적 인 서비스 인터페이스 방법 경로 @ Path ("/ 경로")
  •     @Path("/add")
    	@POST
    	@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    	public void saveUser(User user);
    
    

    클 라 이언 트 Junit 테스트
    package com.zjf.test;
    
    import java.util.Collection;
    
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    
    import org.apache.cxf.jaxrs.client.WebClient;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.zjf.pojo.User;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class clientTest {
    
    	@Autowired
    	private WebClient webClient;
    
    	@Test
    	public void addUser() {
    		User user = new User();
    		user.setName("  ");
    		user.setAge(18);
    
    		Response post = WebClient.create("http://localhost:8080/rs-server/rs/userService/userService/add")
    				.type(MediaType.APPLICATION_JSON).post(user);
    		System.out.println("      :" + post.getStatus());
    
    	}
    
    	@Test
    	public void addUser1() {
    		User user = new User();
    		user.setName("  ");
    		user.setAge(18);
    		Response post = webClient.type(MediaType.APPLICATION_JSON).post(user);
    		System.out.println("      :" + post.getStatus());
    	}
    
    	@Test
    	public void findUser() {
    
    		User user = WebClient.create("http://localhost:8080/rs-server/rs/userService/userService/find/1")
    				.accept(MediaType.APPLICATION_JSON).get(User.class);
    		System.out.println(user);
    
    	}
    
    	@Test
    	public void listUser() {
    		Collection<? extends User> collection = WebClient
    				.create("http://localhost:8080/rs-server/rs/userService/userService/list")
    				.accept(MediaType.APPLICATION_JSON).getCollection(User.class);
    
    		System.out.println(collection);
    
    	}
    
    }
    
    

    WebClient 에서 자주 사용 하 는 방법 설명:
  • create (): 웹 클 라 이언 트 정적 방법 호출 서비스 경 로 를 입력 하고 JAXRSClient Factory Bean 대상 만 들 기
  • type (): 서버 에 전 달 된 데이터 형식 을 정의 합 니 다
  • accept (): 서버 반환 데이터 형식 을 정의 합 니 다
  • post (매개 변수): 추가 조작, 전달 매개 변수
  • get: 조회 조작, 데이터 되 돌려 주기
  • put: 조작 수정, 전달 매개 변수
  • delete: 삭제 작업 (Restful 스타일 에 맞 춰 서비스 경로 에서 매개 변 수 를 전달 합 니 다)
  • getCollection (매개 변수): 조회 조작, 집합 데이터 되 돌려 주기
  • 호출 서비스 인터페이스 테스트:
    ----------------------------
    ID: 3
    Address: http://localhost:8080/rs-server/rs/userService/userService/add
    Encoding: ISO-8859-1
    Http-Method: POST
    Content-Type: application/json
    Headers: {Accept=[*/*], cache-control=[no-cache], connection=[keep-alive], Content-Length=[35], content-type=[application/json], host=[localhost:8080], pragma=[no-cache], user-agent=[Apache-CXF/3.1.7]}
    Payload: {"User":{"age":18,"name":"å¼ ä¸‰"}}
    --------------------------------------
      User  :  
       05, 2020 4:24:14    org.apache.cxf.interceptor.LoggingOutInterceptor
      : Outbound Message
    ---------------------------
    ID: 3
    Response-Code: 204
    Content-Type: */*
    Headers: {Date=[Sun, 05 Apr 2020 08:24:14 GMT], Content-Length=[0]}
    --------------------------------------
    

    좋은 웹페이지 즐겨찾기